Changeset View
Changeset View
Standalone View
Standalone View
kstyle/breezeshadowhelper.cpp
1 | /************************************************************************* | 1 | /************************************************************************* | ||
---|---|---|---|---|---|
2 | * Copyright (C) 2014 by Hugo Pereira Da Costa <hugo.pereira@free.fr> * | 2 | * Copyright (C) 2014 by Hugo Pereira Da Costa <hugo.pereira@free.fr> * | ||
3 | * Copyright (C) 2018 by Vlad Zagorodniy <vlad.zahorodnii@kde.org> * | 3 | * Copyright (C) 2018, 2020 by Vlad Zahorodnii <vlad.zahorodnii@kde.org> * | ||
4 | * * | 4 | * * | ||
5 | * This program is free software; you can redistribute it and/or modify * | 5 | * This program is free software; you can redistribute it and/or modify * | ||
6 | * it under the terms of the GNU General Public License as published by * | 6 | * it under the terms of the GNU General Public License as published by * | ||
7 | * the Free Software Foundation; either version 2 of the License, or * | 7 | * the Free Software Foundation; either version 2 of the License, or * | ||
8 | * (at your option) any later version. * | 8 | * (at your option) any later version. * | ||
9 | * * | 9 | * * | ||
10 | * This program is distributed in the hope that it will be useful, * | 10 | * This program is distributed in the hope that it will be useful, * | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
Show All 15 Lines | |||||
27 | #include "breezestyleconfigdata.h" | 27 | #include "breezestyleconfigdata.h" | ||
28 | 28 | | |||
29 | #include <QDockWidget> | 29 | #include <QDockWidget> | ||
30 | #include <QEvent> | 30 | #include <QEvent> | ||
31 | #include <QApplication> | 31 | #include <QApplication> | ||
32 | #include <QMenu> | 32 | #include <QMenu> | ||
33 | #include <QPainter> | 33 | #include <QPainter> | ||
34 | #include <QPixmap> | 34 | #include <QPixmap> | ||
35 | #include <QPlatformSurfaceEvent> | ||||
35 | #include <QToolBar> | 36 | #include <QToolBar> | ||
36 | #include <QTextStream> | 37 | #include <QTextStream> | ||
37 | 38 | | |||
38 | #if BREEZE_HAVE_X11 | | |||
39 | #include <QX11Info> | | |||
40 | #endif | | |||
41 | | ||||
42 | #if BREEZE_HAVE_KWAYLAND | | |||
43 | #include <KWayland/Client/buffer.h> | | |||
44 | #include <KWayland/Client/connection_thread.h> | | |||
45 | #include <KWayland/Client/registry.h> | | |||
46 | #include <KWayland/Client/shadow.h> | | |||
47 | #include <KWayland/Client/shm_pool.h> | | |||
48 | #include <KWayland/Client/surface.h> | | |||
49 | #endif | | |||
50 | | ||||
51 | namespace | 39 | namespace | ||
52 | { | 40 | { | ||
53 | using Breeze::CompositeShadowParams; | 41 | using Breeze::CompositeShadowParams; | ||
54 | using Breeze::ShadowParams; | 42 | using Breeze::ShadowParams; | ||
55 | 43 | | |||
56 | const CompositeShadowParams s_shadowParams[] = { | 44 | const CompositeShadowParams s_shadowParams[] = { | ||
57 | // None | 45 | // None | ||
58 | CompositeShadowParams(), | 46 | CompositeShadowParams(), | ||
Show All 18 Lines | 63 | CompositeShadowParams( | |||
77 | ShadowParams(QPoint(0, 0), 24, 0.2), | 65 | ShadowParams(QPoint(0, 0), 24, 0.2), | ||
78 | ShadowParams(QPoint(0, -3), 12, 0.1)) | 66 | ShadowParams(QPoint(0, -3), 12, 0.1)) | ||
79 | }; | 67 | }; | ||
80 | } | 68 | } | ||
81 | 69 | | |||
82 | namespace Breeze | 70 | namespace Breeze | ||
83 | { | 71 | { | ||
84 | 72 | | |||
85 | const char ShadowHelper::netWMShadowAtomName[] ="_KDE_NET_WM_SHADOW"; | | |||
86 | | ||||
87 | //_____________________________________________________ | 73 | //_____________________________________________________ | ||
88 | CompositeShadowParams ShadowHelper::lookupShadowParams(int shadowSizeEnum) | 74 | CompositeShadowParams ShadowHelper::lookupShadowParams(int shadowSizeEnum) | ||
89 | { | 75 | { | ||
90 | 76 | | |||
91 | switch (shadowSizeEnum) { | 77 | switch (shadowSizeEnum) { | ||
92 | case StyleConfigData::ShadowNone: | 78 | case StyleConfigData::ShadowNone: | ||
93 | return s_shadowParams[0]; | 79 | return s_shadowParams[0]; | ||
94 | case StyleConfigData::ShadowSmall: | 80 | case StyleConfigData::ShadowSmall: | ||
Show All 11 Lines | |||||
106 | 92 | | |||
107 | } | 93 | } | ||
108 | 94 | | |||
109 | //_____________________________________________________ | 95 | //_____________________________________________________ | ||
110 | ShadowHelper::ShadowHelper( QObject* parent, Helper& helper ): | 96 | ShadowHelper::ShadowHelper( QObject* parent, Helper& helper ): | ||
111 | QObject( parent ), | 97 | QObject( parent ), | ||
112 | _helper( helper ) | 98 | _helper( helper ) | ||
113 | { | 99 | { | ||
114 | // delay till event dispatcher is running as Wayland is highly async | | |||
115 | QMetaObject::invokeMethod(this, "initializeWayland", Qt::QueuedConnection); | | |||
116 | } | 100 | } | ||
117 | 101 | | |||
118 | //_______________________________________________________ | 102 | //_______________________________________________________ | ||
119 | ShadowHelper::~ShadowHelper() | 103 | ShadowHelper::~ShadowHelper() | ||
120 | { | 104 | { | ||
121 | 105 | qDeleteAll( _shadows ); | |||
122 | #if BREEZE_HAVE_X11 | | |||
123 | if( Helper::isX11() ) | | |||
124 | { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } | | |||
125 | #endif | | |||
126 | | ||||
127 | } | | |||
128 | | ||||
129 | //_______________________________________________________ | | |||
130 | void ShadowHelper::initializeWayland() | | |||
131 | { | | |||
132 | #if BREEZE_HAVE_KWAYLAND | | |||
133 | if( !Helper::isWayland() ) return; | | |||
134 | | ||||
135 | using namespace KWayland::Client; | | |||
136 | auto connection = ConnectionThread::fromApplication( this ); | | |||
137 | if( !connection ) { | | |||
138 | return; | | |||
139 | } | | |||
140 | auto registry = new Registry( connection ); | | |||
141 | registry->create( connection ); | | |||
142 | connect(registry, &Registry::interfacesAnnounced, this, | | |||
143 | [registry, this] { | | |||
144 | const auto interface = registry->interface( Registry::Interface::Shadow ); | | |||
145 | if( interface.name != 0 ) { | | |||
146 | _shadowManager = registry->createShadowManager( interface.name, interface.version, registry ); | | |||
147 | } | | |||
148 | const auto shmInterface = registry->interface( Registry::Interface::Shm ); | | |||
149 | if( shmInterface.name != 0 ) { | | |||
150 | _shmPool = registry->createShmPool( shmInterface.name, shmInterface.version, registry ); | | |||
151 | } | | |||
152 | } | | |||
153 | ); | | |||
154 | | ||||
155 | registry->setup(); | | |||
156 | connection->roundtrip(); | | |||
157 | #endif | | |||
158 | } | 106 | } | ||
159 | 107 | | |||
160 | //______________________________________________ | 108 | //______________________________________________ | ||
161 | void ShadowHelper::reset() | 109 | void ShadowHelper::reset() | ||
162 | { | 110 | { | ||
163 | #if BREEZE_HAVE_X11 | 111 | _tiles.clear(); | ||
164 | if( Helper::isX11() ) | | |||
165 | { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } | | |||
166 | #endif | | |||
167 | | ||||
168 | _pixmaps.clear(); | | |||
169 | _shadowTiles = TileSet(); | 112 | _shadowTiles = TileSet(); | ||
170 | 113 | | |||
171 | } | 114 | } | ||
172 | 115 | | |||
173 | //_______________________________________________________ | 116 | //_______________________________________________________ | ||
174 | bool ShadowHelper::registerWidget( QWidget* widget, bool force ) | 117 | bool ShadowHelper::registerWidget( QWidget* widget, bool force ) | ||
175 | { | 118 | { | ||
176 | // make sure widget is not already registered | 119 | // make sure widget is not already registered | ||
177 | if( _widgets.contains( widget ) ) return false; | 120 | if( _widgets.contains( widget ) ) return false; | ||
178 | 121 | | |||
179 | // check if widget qualifies | 122 | // check if widget qualifies | ||
180 | if( !( force || acceptWidget( widget ) ) ) | 123 | if( !( force || acceptWidget( widget ) ) ) | ||
181 | { return false; } | 124 | { return false; } | ||
182 | 125 | | |||
183 | // try create shadow directly | 126 | // try create shadow directly | ||
184 | if( installShadows( widget ) ) _widgets.insert( widget, widget->winId() ); | 127 | installShadows( widget ); | ||
185 | else _widgets.insert( widget, 0 ); | 128 | _widgets.insert( widget ); | ||
186 | 129 | | |||
187 | // install event filter | 130 | // install event filter | ||
188 | widget->removeEventFilter( this ); | 131 | widget->removeEventFilter( this ); | ||
189 | widget->installEventFilter( this ); | 132 | widget->installEventFilter( this ); | ||
190 | 133 | | |||
191 | // connect destroy signal | 134 | // connect destroy signal | ||
192 | connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); | 135 | connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); | ||
193 | 136 | | |||
Show All 11 Lines | |||||
205 | //_______________________________________________________ | 148 | //_______________________________________________________ | ||
206 | void ShadowHelper::loadConfig() | 149 | void ShadowHelper::loadConfig() | ||
207 | { | 150 | { | ||
208 | 151 | | |||
209 | // reset | 152 | // reset | ||
210 | reset(); | 153 | reset(); | ||
211 | 154 | | |||
212 | // update property for registered widgets | 155 | // update property for registered widgets | ||
213 | for( QMap<QWidget*,WId>::const_iterator iter = _widgets.constBegin(); iter != _widgets.constEnd(); ++iter ) | 156 | for( QWidget* widget : _widgets) | ||
214 | { installShadows( iter.key() ); } | 157 | { installShadows( widget ); } | ||
215 | 158 | | |||
216 | } | 159 | } | ||
217 | 160 | | |||
218 | //_______________________________________________________ | 161 | //_______________________________________________________ | ||
219 | bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) | 162 | bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) | ||
220 | { | 163 | { | ||
221 | if( Helper::isWayland() ) | 164 | if( Helper::isX11() ) | ||
222 | { | 165 | { | ||
166 | // check event type | ||||
167 | if( event->type() != QEvent::WinIdChange ) return false; | ||||
223 | 168 | | |||
224 | #if BREEZE_HAVE_KWAYLAND | 169 | // cast widget | ||
225 | QWidget* widget( static_cast<QWidget*>( object ) ); | 170 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||
226 | if( event->type() == QEvent::Paint ) | | |||
227 | { | | |||
228 | 171 | | |||
229 | auto iter = _widgetSurfaces.constFind( widget ); | | |||
230 | if( iter == _widgetSurfaces.constEnd() ) | | |||
231 | { | | |||
232 | // install shadows and update winId | 172 | // install shadows and update winId | ||
233 | installShadows( widget ); | 173 | installShadows( widget ); | ||
234 | } | | |||
235 | | ||||
236 | } else if( event->type() == QEvent::Hide ) { | | |||
237 | | ||||
238 | auto iter = _widgetSurfaces.find( widget ); | | |||
239 | if( iter != _widgetSurfaces.end() ) | | |||
240 | { | | |||
241 | _widgetSurfaces.erase( iter ); | | |||
242 | } | | |||
243 | 174 | | |||
244 | } | 175 | } else { | ||
245 | #endif | 176 | if( event->type() != QEvent::PlatformSurface ) return false; | ||
246 | | ||||
247 | } else if( Helper::isX11() ) { | | |||
248 | | ||||
249 | // check event type | | |||
250 | if( event->type() != QEvent::WinIdChange ) return false; | | |||
251 | 177 | | |||
252 | // cast widget | | |||
253 | QWidget* widget( static_cast<QWidget*>( object ) ); | 178 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||
179 | QPlatformSurfaceEvent* surfaceEvent( static_cast<QPlatformSurfaceEvent*>( event ) ); | ||||
254 | 180 | | |||
255 | // install shadows and update winId | 181 | switch( surfaceEvent->surfaceEventType() ) | ||
256 | if( installShadows( widget ) ) | 182 | { | ||
257 | { _widgets.insert( widget, widget->winId() ); } | 183 | case QPlatformSurfaceEvent::SurfaceCreated: | ||
184 | installShadows( widget ); | ||||
185 | break; | ||||
186 | case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: | ||||
187 | // Don't care. | ||||
188 | break; | ||||
189 | } | ||||
258 | } | 190 | } | ||
259 | 191 | | |||
260 | return false; | 192 | return false; | ||
261 | 193 | | |||
262 | } | 194 | } | ||
263 | 195 | | |||
264 | //_______________________________________________________ | 196 | //_______________________________________________________ | ||
265 | TileSet ShadowHelper::shadowTiles() | 197 | TileSet ShadowHelper::shadowTiles() | ||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Line(s) | 261 | _shadowTiles = TileSet( | |||
333 | 1, 1); | 265 | 1, 1); | ||
334 | 266 | | |||
335 | return _shadowTiles; | 267 | return _shadowTiles; | ||
336 | } | 268 | } | ||
337 | 269 | | |||
338 | 270 | | |||
339 | //_______________________________________________________ | 271 | //_______________________________________________________ | ||
340 | void ShadowHelper::objectDeleted( QObject* object ) | 272 | void ShadowHelper::objectDeleted( QObject* object ) | ||
341 | { _widgets.remove( static_cast<QWidget*>( object ) ); } | 273 | { | ||
274 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||||
275 | _widgets.remove( widget ); | ||||
276 | _shadows.remove( widget ); | ||||
277 | | ||||
278 | } | ||||
342 | 279 | | |||
343 | //_______________________________________________________ | 280 | //_______________________________________________________ | ||
344 | bool ShadowHelper::isMenu( QWidget* widget ) const | 281 | bool ShadowHelper::isMenu( QWidget* widget ) const | ||
345 | { return qobject_cast<QMenu*>( widget ); } | 282 | { return qobject_cast<QMenu*>( widget ); } | ||
346 | 283 | | |||
347 | //_______________________________________________________ | 284 | //_______________________________________________________ | ||
348 | bool ShadowHelper::isToolTip( QWidget* widget ) const | 285 | bool ShadowHelper::isToolTip( QWidget* widget ) const | ||
349 | { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } | 286 | { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } | ||
Show All 28 Lines | 298 | { | |||
378 | if( isDockWidget( widget ) || isToolBar( widget ) ) | 315 | if( isDockWidget( widget ) || isToolBar( widget ) ) | ||
379 | { return true; } | 316 | { return true; } | ||
380 | 317 | | |||
381 | // reject | 318 | // reject | ||
382 | return false; | 319 | return false; | ||
383 | } | 320 | } | ||
384 | 321 | | |||
385 | //______________________________________________ | 322 | //______________________________________________ | ||
386 | const QVector<quint32>& ShadowHelper::createPixmapHandles() | 323 | const QVector<KWindowShadowTile::Ptr>& ShadowHelper::createShadowTiles() | ||
387 | { | 324 | { | ||
388 | 325 | | |||
389 | /** | | |||
390 | shadow atom and property specification available at | | |||
391 | https://community.kde.org/KWin/Shadow | | |||
392 | */ | | |||
393 | | ||||
394 | // create atom | | |||
395 | #if BREEZE_HAVE_X11 | | |||
396 | if( !_atom && Helper::isX11() ) _atom = _helper.createAtom( QLatin1String( netWMShadowAtomName ) ); | | |||
397 | #endif | | |||
398 | | ||||
399 | // make sure size is valid | 326 | // make sure size is valid | ||
400 | if( _pixmaps.empty() ) | 327 | if( _tiles.isEmpty() ) | ||
401 | { | 328 | { | ||
402 | _pixmaps = QVector<quint32> { | 329 | _tiles = { | ||
403 | createPixmap( _shadowTiles.pixmap( 1 ) ), | 330 | createTile( _shadowTiles.pixmap( 1 ) ), | ||
404 | createPixmap( _shadowTiles.pixmap( 2 ) ), | 331 | createTile( _shadowTiles.pixmap( 2 ) ), | ||
405 | createPixmap( _shadowTiles.pixmap( 5 ) ), | 332 | createTile( _shadowTiles.pixmap( 5 ) ), | ||
406 | createPixmap( _shadowTiles.pixmap( 8 ) ), | 333 | createTile( _shadowTiles.pixmap( 8 ) ), | ||
407 | createPixmap( _shadowTiles.pixmap( 7 ) ), | 334 | createTile( _shadowTiles.pixmap( 7 ) ), | ||
408 | createPixmap( _shadowTiles.pixmap( 6 ) ), | 335 | createTile( _shadowTiles.pixmap( 6 ) ), | ||
409 | createPixmap( _shadowTiles.pixmap( 3 ) ), | 336 | createTile( _shadowTiles.pixmap( 3 ) ), | ||
410 | createPixmap( _shadowTiles.pixmap( 0 ) ) | 337 | createTile( _shadowTiles.pixmap( 0 ) ) | ||
411 | }; | 338 | }; | ||
412 | } | 339 | } | ||
413 | 340 | | |||
414 | // return relevant list of pixmap handles | 341 | // return relevant list of shadow tiles | ||
415 | return _pixmaps; | 342 | return _tiles; | ||
416 | 343 | | |||
417 | } | 344 | } | ||
418 | 345 | | |||
419 | //______________________________________________ | 346 | //______________________________________________ | ||
420 | quint32 ShadowHelper::createPixmap( const QPixmap& source ) | 347 | KWindowShadowTile::Ptr ShadowHelper::createTile( const QPixmap& source ) | ||
421 | { | | |||
422 | | ||||
423 | // do nothing for invalid pixmaps | | |||
424 | if( source.isNull() ) return 0; | | |||
425 | if( !Helper::isX11() ) return 0; | | |||
426 | | ||||
427 | /* | | |||
428 | in some cases, pixmap handle is invalid. This is the case notably | | |||
429 | when Qt uses to RasterEngine. In this case, we create an X11 Pixmap | | |||
430 | explicitly and draw the source pixmap on it. | | |||
431 | */ | | |||
432 | | ||||
433 | #if BREEZE_HAVE_X11 | | |||
434 | | ||||
435 | const int width( source.width() ); | | |||
436 | const int height( source.height() ); | | |||
437 | | ||||
438 | // create X11 pixmap | | |||
439 | xcb_pixmap_t pixmap = xcb_generate_id( Helper::connection() ); | | |||
440 | xcb_create_pixmap( Helper::connection(), 32, pixmap, QX11Info::appRootWindow(), width, height ); | | |||
441 | | ||||
442 | // create gc | | |||
443 | if( !_gc ) | | |||
444 | { | 348 | { | ||
445 | _gc = xcb_generate_id( Helper::connection() ); | | |||
446 | xcb_create_gc( Helper::connection(), _gc, pixmap, 0, nullptr ); | | |||
447 | } | | |||
448 | | ||||
449 | // create image from QPixmap and assign to pixmap | | |||
450 | QImage image( source.toImage() ); | | |||
451 | | ||||
452 | 349 | | |||
453 | #if QT_VERSION >= 0x051000 | 350 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||
454 | xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.sizeInBytes(), image.constBits()); | 351 | tile->setImage( source.toImage() ); | ||
455 | #else | 352 | return tile; | ||
456 | xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.byteCount(), image.constBits()); | | |||
457 | #endif | | |||
458 | | ||||
459 | return pixmap; | | |||
460 | | ||||
461 | #else | | |||
462 | return 0; | | |||
463 | #endif | | |||
464 | 353 | | |||
465 | } | 354 | } | ||
466 | 355 | | |||
467 | //_______________________________________________________ | 356 | //_______________________________________________________ | ||
468 | bool ShadowHelper::installShadows( QWidget* widget ) | 357 | void ShadowHelper::installShadows( QWidget* widget ) | ||
469 | { | 358 | { | ||
470 | if( !widget ) return false; | 359 | if( !widget ) return; | ||
471 | 360 | | |||
472 | /* | 361 | // only toplevel widgets can cast drop-shadows | ||
473 | From bespin code. Supposedly prevent playing with some 'pseudo-widgets' | 362 | if( !widget->isWindow() ) return; | ||
474 | that have winId matching some other -random- window | 363 | | ||
475 | */ | 364 | // widget must have valid native window | ||
476 | if( !(widget->testAttribute(Qt::WA_WState_Created) && widget->internalWinId() )) | 365 | if( !widget->testAttribute( Qt::WA_WState_Created ) ) return; | ||
477 | { return false; } | | |||
478 | 366 | | |||
479 | // create shadow tiles if needed | 367 | // create shadow tiles if needed | ||
480 | shadowTiles(); | 368 | shadowTiles(); | ||
369 | if( !_shadowTiles.isValid() ) return; | ||||
481 | 370 | | |||
482 | if( !_shadowTiles.isValid() ) return false; | 371 | // create platform shadow tiles if needed | ||
483 | 372 | const QVector<KWindowShadowTile::Ptr>& tiles = createShadowTiles(); | |||
484 | if( Helper::isX11() ) return installX11Shadows( widget ); | 373 | if( tiles.count() != numTiles ) return; | ||
485 | if( Helper::isWayland() ) return installWaylandShadows( widget ); | 374 | | ||
486 | 375 | // find a shadow associated with the widget | |||
487 | return false; | 376 | KWindowShadow*& shadow = _shadows[ widget ]; | ||
488 | } | 377 | | ||
489 | 378 | // we want the shadow to be deleted after the decorated window is destroyed | |||
490 | //_______________________________________________________ | 379 | if( !shadow ) | ||
491 | bool ShadowHelper::installX11Shadows( QWidget* widget ) | 380 | { shadow = new KWindowShadow( widget->windowHandle() ); } | ||
492 | { | 381 | | ||
493 | #if BREEZE_HAVE_X11 | 382 | if( shadow->isCreated() ) | ||
494 | #ifndef QT_NO_XRENDER | 383 | { shadow->destroy(); } | ||
495 | 384 | | |||
496 | // create pixmap handles if needed | 385 | shadow->setTopTile( tiles[ 0 ] ); | ||
497 | QVector<quint32> data( createPixmapHandles() ); | 386 | shadow->setTopRightTile( tiles[ 1 ] ); | ||
498 | if( data.size() != numPixmaps ) return false; | 387 | shadow->setRightTile( tiles[ 2 ] ); | ||
499 | 388 | shadow->setBottomRightTile( tiles[ 3 ] ); | |||
500 | const QMargins margins = shadowMargins( widget ); | 389 | shadow->setBottomTile( tiles[ 4 ] ); | ||
501 | const quint32 topSize = margins.top(); | 390 | shadow->setBottomLeftTile( tiles[ 5 ] ); | ||
502 | const quint32 bottomSize = margins.bottom(); | 391 | shadow->setLeftTile( tiles[ 6 ] ); | ||
503 | const quint32 leftSize( margins.left() ); | 392 | shadow->setTopLeftTile( tiles[ 7 ] ); | ||
504 | const quint32 rightSize( margins.right() ); | 393 | shadow->setPadding( shadowMargins( widget ) ); | ||
505 | 394 | shadow->setWindow( widget->windowHandle() ); | |||
506 | // assign to data and xcb property | 395 | shadow->create(); | ||
507 | data << QVector<quint32>{topSize, rightSize, bottomSize, leftSize}; | | |||
508 | xcb_change_property( Helper::connection(), XCB_PROP_MODE_REPLACE, widget->winId(), _atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); | | |||
509 | xcb_flush( Helper::connection() ); | | |||
510 | | ||||
511 | return true; | | |||
512 | | ||||
513 | #endif | | |||
514 | #endif | | |||
515 | | ||||
516 | return false; | | |||
517 | | ||||
518 | } | | |||
519 | | ||||
520 | //_______________________________________________________ | | |||
521 | bool ShadowHelper::installWaylandShadows( QWidget* widget ) | | |||
522 | { | | |||
523 | #if BREEZE_HAVE_KWAYLAND | | |||
524 | if( widget->windowHandle()->parent() ) return false; | | |||
525 | if( !_shadowManager || !_shmPool ) return false; | | |||
526 | | ||||
527 | // create shadow | | |||
528 | using namespace KWayland::Client; | | |||
529 | auto s = Surface::fromWindow( widget->windowHandle() ); | | |||
530 | if( !s ) return false; | | |||
531 | | ||||
532 | auto shadow = _shadowManager->createShadow( s, widget ); | | |||
533 | if( !shadow->isValid() ) return false; | | |||
534 | | ||||
535 | // add the shadow elements | | |||
536 | shadow->attachTop( _shmPool->createBuffer( _shadowTiles.pixmap( 1 ).toImage() ) ); | | |||
537 | shadow->attachTopRight( _shmPool->createBuffer( _shadowTiles.pixmap( 2 ).toImage() ) ); | | |||
538 | shadow->attachRight( _shmPool->createBuffer( _shadowTiles.pixmap( 5 ).toImage() ) ); | | |||
539 | shadow->attachBottomRight( _shmPool->createBuffer( _shadowTiles.pixmap( 8 ).toImage() ) ); | | |||
540 | shadow->attachBottom( _shmPool->createBuffer( _shadowTiles.pixmap( 7 ).toImage() ) ); | | |||
541 | shadow->attachBottomLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 6 ).toImage() ) ); | | |||
542 | shadow->attachLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 3 ).toImage() ) ); | | |||
543 | shadow->attachTopLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 0 ).toImage() ) ); | | |||
544 | | ||||
545 | shadow->setOffsets( shadowMargins( widget ) ); | | |||
546 | shadow->commit(); | | |||
547 | s->commit( Surface::CommitFlag::None ); | | |||
548 | _widgetSurfaces.insert(widget, s); | | |||
549 | | ||||
550 | return true; | | |||
551 | #else | | |||
552 | Q_UNUSED( widget ); | | |||
553 | #endif | | |||
554 | | ||||
555 | return false; | | |||
556 | } | 396 | } | ||
557 | 397 | | |||
558 | //_______________________________________________________ | 398 | //_______________________________________________________ | ||
559 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | 399 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | ||
560 | { | 400 | { | ||
561 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | 401 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | ||
562 | if (params.isNone()) { | 402 | if (params.isNone()) { | ||
563 | return QMargins(); | 403 | return QMargins(); | ||
Show All 34 Lines | |||||
598 | } | 438 | } | ||
599 | 439 | | |||
600 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | 440 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | ||
601 | 441 | | |||
602 | return margins; | 442 | return margins; | ||
603 | } | 443 | } | ||
604 | 444 | | |||
605 | //_______________________________________________________ | 445 | //_______________________________________________________ | ||
606 | void ShadowHelper::uninstallShadows( QWidget* widget ) const | 446 | void ShadowHelper::uninstallShadows( QWidget* widget ) | ||
607 | { | 447 | { | ||
608 | if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; | 448 | delete _shadows.take( widget ); | ||
609 | if( Helper::isX11() ) uninstallX11Shadows( widget ); | | |||
610 | if( Helper::isWayland() ) uninstallWaylandShadows( widget ); | | |||
611 | } | | |||
612 | | ||||
613 | //_______________________________________________________ | | |||
614 | void ShadowHelper::uninstallX11Shadows( QWidget* widget ) const | | |||
615 | { | | |||
616 | #if BREEZE_HAVE_X11 | | |||
617 | xcb_delete_property( Helper::connection(), widget->winId(), _atom); | | |||
618 | #else | | |||
619 | Q_UNUSED( widget ) | | |||
620 | #endif | | |||
621 | | ||||
622 | } | | |||
623 | | ||||
624 | //_______________________________________________________ | | |||
625 | void ShadowHelper::uninstallWaylandShadows( QWidget* widget ) const | | |||
626 | { | | |||
627 | #if BREEZE_HAVE_KWAYLAND | | |||
628 | if( widget->windowHandle() && widget->windowHandle()->parent() ) return; | | |||
629 | if( !_shadowManager ) return; | | |||
630 | | ||||
631 | using namespace KWayland::Client; | | |||
632 | auto s = Surface::fromWindow( widget->windowHandle() ); | | |||
633 | if( !s ) return; | | |||
634 | | ||||
635 | _shadowManager->removeShadow( s ); | | |||
636 | s->commit( Surface::CommitFlag::None ); | | |||
637 | #else | | |||
638 | Q_UNUSED( widget ) | | |||
639 | #endif | | |||
640 | } | 449 | } | ||
641 | 450 | | |||
642 | } | 451 | } |