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 76 Lines • ▼ Show 20 Line(s) | 270 | _shadowTiles = TileSet( | |||
342 | 1, 1); | 274 | 1, 1); | ||
343 | 275 | | |||
344 | return _shadowTiles; | 276 | return _shadowTiles; | ||
345 | } | 277 | } | ||
346 | 278 | | |||
347 | 279 | | |||
348 | //_______________________________________________________ | 280 | //_______________________________________________________ | ||
349 | void ShadowHelper::objectDeleted( QObject* object ) | 281 | void ShadowHelper::objectDeleted( QObject* object ) | ||
350 | { _widgets.remove( static_cast<QWidget*>( object ) ); } | 282 | { | ||
283 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||||
284 | _widgets.remove( widget ); | ||||
285 | _shadows.remove( widget ); | ||||
286 | | ||||
287 | } | ||||
351 | 288 | | |||
352 | //_______________________________________________________ | 289 | //_______________________________________________________ | ||
353 | bool ShadowHelper::isMenu( QWidget* widget ) const | 290 | bool ShadowHelper::isMenu( QWidget* widget ) const | ||
354 | { return qobject_cast<QMenu*>( widget ); } | 291 | { return qobject_cast<QMenu*>( widget ); } | ||
355 | 292 | | |||
356 | //_______________________________________________________ | 293 | //_______________________________________________________ | ||
357 | bool ShadowHelper::isToolTip( QWidget* widget ) const | 294 | bool ShadowHelper::isToolTip( QWidget* widget ) const | ||
358 | { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } | 295 | { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } | ||
Show All 28 Lines | 307 | { | |||
387 | if( isDockWidget( widget ) || isToolBar( widget ) ) | 324 | if( isDockWidget( widget ) || isToolBar( widget ) ) | ||
388 | { return true; } | 325 | { return true; } | ||
389 | 326 | | |||
390 | // reject | 327 | // reject | ||
391 | return false; | 328 | return false; | ||
392 | } | 329 | } | ||
393 | 330 | | |||
394 | //______________________________________________ | 331 | //______________________________________________ | ||
395 | const QVector<quint32>& ShadowHelper::createPixmapHandles() | 332 | const QVector<KWindowShadowTile::Ptr>& ShadowHelper::createShadowTiles() | ||
396 | { | 333 | { | ||
397 | 334 | | |||
398 | /** | | |||
399 | shadow atom and property specification available at | | |||
400 | https://community.kde.org/KWin/Shadow | | |||
401 | */ | | |||
402 | | ||||
403 | // create atom | | |||
404 | #if BREEZE_HAVE_X11 | | |||
405 | if( !_atom && Helper::isX11() ) _atom = _helper.createAtom( QLatin1String( netWMShadowAtomName ) ); | | |||
406 | #endif | | |||
407 | | ||||
408 | // make sure size is valid | 335 | // make sure size is valid | ||
409 | if( _pixmaps.empty() ) | 336 | if( _tiles.isEmpty() ) | ||
410 | { | 337 | { | ||
411 | _pixmaps = QVector<quint32> { | 338 | _tiles = { | ||
412 | createPixmap( _shadowTiles.pixmap( 1 ) ), | 339 | createTile( _shadowTiles.pixmap( 1 ) ), | ||
413 | createPixmap( _shadowTiles.pixmap( 2 ) ), | 340 | createTile( _shadowTiles.pixmap( 2 ) ), | ||
414 | createPixmap( _shadowTiles.pixmap( 5 ) ), | 341 | createTile( _shadowTiles.pixmap( 5 ) ), | ||
415 | createPixmap( _shadowTiles.pixmap( 8 ) ), | 342 | createTile( _shadowTiles.pixmap( 8 ) ), | ||
416 | createPixmap( _shadowTiles.pixmap( 7 ) ), | 343 | createTile( _shadowTiles.pixmap( 7 ) ), | ||
417 | createPixmap( _shadowTiles.pixmap( 6 ) ), | 344 | createTile( _shadowTiles.pixmap( 6 ) ), | ||
418 | createPixmap( _shadowTiles.pixmap( 3 ) ), | 345 | createTile( _shadowTiles.pixmap( 3 ) ), | ||
419 | createPixmap( _shadowTiles.pixmap( 0 ) ) | 346 | createTile( _shadowTiles.pixmap( 0 ) ) | ||
420 | }; | 347 | }; | ||
421 | } | 348 | } | ||
422 | 349 | | |||
423 | // return relevant list of pixmap handles | 350 | // return relevant list of shadow tiles | ||
424 | return _pixmaps; | 351 | return _tiles; | ||
425 | 352 | | |||
426 | } | 353 | } | ||
427 | 354 | | |||
428 | //______________________________________________ | 355 | //______________________________________________ | ||
429 | quint32 ShadowHelper::createPixmap( const QPixmap& source ) | 356 | KWindowShadowTile::Ptr ShadowHelper::createTile( const QPixmap& source ) | ||
430 | { | | |||
431 | | ||||
432 | // do nothing for invalid pixmaps | | |||
433 | if( source.isNull() ) return 0; | | |||
434 | if( !Helper::isX11() ) return 0; | | |||
435 | | ||||
436 | /* | | |||
437 | in some cases, pixmap handle is invalid. This is the case notably | | |||
438 | when Qt uses to RasterEngine. In this case, we create an X11 Pixmap | | |||
439 | explicitly and draw the source pixmap on it. | | |||
440 | */ | | |||
441 | | ||||
442 | #if BREEZE_HAVE_X11 | | |||
443 | | ||||
444 | const int width( source.width() ); | | |||
445 | const int height( source.height() ); | | |||
446 | | ||||
447 | // create X11 pixmap | | |||
448 | xcb_pixmap_t pixmap = xcb_generate_id( Helper::connection() ); | | |||
449 | xcb_create_pixmap( Helper::connection(), 32, pixmap, QX11Info::appRootWindow(), width, height ); | | |||
450 | | ||||
451 | // create gc | | |||
452 | if( !_gc ) | | |||
453 | { | 357 | { | ||
454 | _gc = xcb_generate_id( Helper::connection() ); | | |||
455 | xcb_create_gc( Helper::connection(), _gc, pixmap, 0, nullptr ); | | |||
456 | } | | |||
457 | | ||||
458 | // create image from QPixmap and assign to pixmap | | |||
459 | QImage image( source.toImage() ); | | |||
460 | 358 | | |||
461 | 359 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | |||
462 | #if QT_VERSION >= 0x051000 | 360 | tile->setImage( source.toImage() ); | ||
463 | xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.sizeInBytes(), image.constBits()); | 361 | return tile; | ||
464 | #else | | |||
465 | xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.byteCount(), image.constBits()); | | |||
466 | #endif | | |||
467 | | ||||
468 | return pixmap; | | |||
469 | | ||||
470 | #else | | |||
471 | return 0; | | |||
472 | #endif | | |||
473 | 362 | | |||
474 | } | 363 | } | ||
475 | 364 | | |||
476 | //_______________________________________________________ | 365 | //_______________________________________________________ | ||
477 | bool ShadowHelper::installShadows( QWidget* widget ) | 366 | void ShadowHelper::installShadows( QWidget* widget ) | ||
478 | { | 367 | { | ||
479 | if( !widget ) return false; | 368 | if( !widget ) return; | ||
480 | 369 | | |||
481 | /* | 370 | // only toplevel widgets can cast drop-shadows | ||
482 | From bespin code. Supposedly prevent playing with some 'pseudo-widgets' | 371 | if( !widget->isWindow() ) return; | ||
483 | that have winId matching some other -random- window | 372 | | ||
484 | */ | 373 | // widget must have valid native window | ||
485 | if( !(widget->testAttribute(Qt::WA_WState_Created) && widget->internalWinId() )) | 374 | if( !widget->testAttribute( Qt::WA_WState_Created ) ) return; | ||
486 | { return false; } | | |||
487 | 375 | | |||
488 | // create shadow tiles if needed | 376 | // create shadow tiles if needed | ||
489 | shadowTiles(); | 377 | shadowTiles(); | ||
378 | if( !_shadowTiles.isValid() ) return; | ||||
490 | 379 | | |||
491 | if( !_shadowTiles.isValid() ) return false; | 380 | // create platform shadow tiles if needed | ||
492 | 381 | const QVector<KWindowShadowTile::Ptr>& tiles = createShadowTiles(); | |||
493 | if( Helper::isX11() ) return installX11Shadows( widget ); | 382 | if( tiles.count() != numTiles ) return; | ||
494 | if( Helper::isWayland() ) return installWaylandShadows( widget ); | 383 | | ||
495 | 384 | // find a shadow associated with the widget | |||
496 | return false; | 385 | KWindowShadow*& shadow = _shadows[ widget ]; | ||
497 | } | 386 | | ||
498 | 387 | // we want the shadow to be deleted after the decorated window is destroyed | |||
499 | //_______________________________________________________ | 388 | if( !shadow ) | ||
500 | bool ShadowHelper::installX11Shadows( QWidget* widget ) | 389 | { shadow = new KWindowShadow( widget->windowHandle() ); } | ||
501 | { | 390 | | ||
502 | #if BREEZE_HAVE_X11 | 391 | if( shadow->isCreated() ) | ||
503 | #ifndef QT_NO_XRENDER | 392 | { shadow->destroy(); } | ||
504 | 393 | | |||
505 | // create pixmap handles if needed | 394 | shadow->setTopTile( tiles[ 0 ] ); | ||
506 | QVector<quint32> data( createPixmapHandles() ); | 395 | shadow->setTopRightTile( tiles[ 1 ] ); | ||
507 | if( data.size() != numPixmaps ) return false; | 396 | shadow->setRightTile( tiles[ 2 ] ); | ||
508 | 397 | shadow->setBottomRightTile( tiles[ 3 ] ); | |||
509 | const QMargins margins = shadowMargins( widget ); | 398 | shadow->setBottomTile( tiles[ 4 ] ); | ||
510 | const quint32 topSize = margins.top(); | 399 | shadow->setBottomLeftTile( tiles[ 5 ] ); | ||
511 | const quint32 bottomSize = margins.bottom(); | 400 | shadow->setLeftTile( tiles[ 6 ] ); | ||
512 | const quint32 leftSize( margins.left() ); | 401 | shadow->setTopLeftTile( tiles[ 7 ] ); | ||
513 | const quint32 rightSize( margins.right() ); | 402 | shadow->setPadding( shadowMargins( widget ) ); | ||
514 | 403 | shadow->setWindow( widget->windowHandle() ); | |||
515 | // assign to data and xcb property | 404 | shadow->create(); | ||
516 | data << QVector<quint32>{topSize, rightSize, bottomSize, leftSize}; | | |||
517 | xcb_change_property( Helper::connection(), XCB_PROP_MODE_REPLACE, widget->winId(), _atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); | | |||
518 | xcb_flush( Helper::connection() ); | | |||
519 | | ||||
520 | return true; | | |||
521 | | ||||
522 | #endif | | |||
523 | #endif | | |||
524 | | ||||
525 | return false; | | |||
526 | | ||||
527 | } | | |||
528 | | ||||
529 | //_______________________________________________________ | | |||
530 | bool ShadowHelper::installWaylandShadows( QWidget* widget ) | | |||
531 | { | | |||
532 | #if BREEZE_HAVE_KWAYLAND | | |||
533 | if( widget->windowHandle()->parent() ) return false; | | |||
534 | if( !_shadowManager || !_shmPool ) return false; | | |||
535 | | ||||
536 | // create shadow | | |||
537 | using namespace KWayland::Client; | | |||
538 | auto s = Surface::fromWindow( widget->windowHandle() ); | | |||
539 | if( !s ) return false; | | |||
540 | | ||||
541 | auto shadow = _shadowManager->createShadow( s, widget ); | | |||
542 | if( !shadow->isValid() ) return false; | | |||
543 | | ||||
544 | // add the shadow elements | | |||
545 | shadow->attachTop( _shmPool->createBuffer( _shadowTiles.pixmap( 1 ).toImage() ) ); | | |||
546 | shadow->attachTopRight( _shmPool->createBuffer( _shadowTiles.pixmap( 2 ).toImage() ) ); | | |||
547 | shadow->attachRight( _shmPool->createBuffer( _shadowTiles.pixmap( 5 ).toImage() ) ); | | |||
548 | shadow->attachBottomRight( _shmPool->createBuffer( _shadowTiles.pixmap( 8 ).toImage() ) ); | | |||
549 | shadow->attachBottom( _shmPool->createBuffer( _shadowTiles.pixmap( 7 ).toImage() ) ); | | |||
550 | shadow->attachBottomLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 6 ).toImage() ) ); | | |||
551 | shadow->attachLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 3 ).toImage() ) ); | | |||
552 | shadow->attachTopLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 0 ).toImage() ) ); | | |||
553 | | ||||
554 | shadow->setOffsets( shadowMargins( widget ) ); | | |||
555 | shadow->commit(); | | |||
556 | s->commit( Surface::CommitFlag::None ); | | |||
557 | _widgetSurfaces.insert(widget, s); | | |||
558 | | ||||
559 | return true; | | |||
560 | #else | | |||
561 | Q_UNUSED( widget ); | | |||
562 | #endif | | |||
563 | | ||||
564 | return false; | | |||
565 | } | 405 | } | ||
566 | 406 | | |||
567 | //_______________________________________________________ | 407 | //_______________________________________________________ | ||
568 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | 408 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | ||
569 | { | 409 | { | ||
570 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | 410 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | ||
571 | if (params.isNone()) { | 411 | if (params.isNone()) { | ||
572 | return QMargins(); | 412 | return QMargins(); | ||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Line(s) | |||||
622 | #else | 462 | #else | ||
623 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | 463 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | ||
624 | #endif | 464 | #endif | ||
625 | 465 | | |||
626 | return margins; | 466 | return margins; | ||
627 | } | 467 | } | ||
628 | 468 | | |||
629 | //_______________________________________________________ | 469 | //_______________________________________________________ | ||
630 | void ShadowHelper::uninstallShadows( QWidget* widget ) const | 470 | void ShadowHelper::uninstallShadows( QWidget* widget ) | ||
631 | { | 471 | { | ||
632 | if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; | 472 | delete _shadows.take( widget ); | ||
633 | if( Helper::isX11() ) uninstallX11Shadows( widget ); | | |||
634 | if( Helper::isWayland() ) uninstallWaylandShadows( widget ); | | |||
635 | } | | |||
636 | | ||||
637 | //_______________________________________________________ | | |||
638 | void ShadowHelper::uninstallX11Shadows( QWidget* widget ) const | | |||
639 | { | | |||
640 | #if BREEZE_HAVE_X11 | | |||
641 | xcb_delete_property( Helper::connection(), widget->winId(), _atom); | | |||
642 | #else | | |||
643 | Q_UNUSED( widget ) | | |||
644 | #endif | | |||
645 | | ||||
646 | } | | |||
647 | | ||||
648 | //_______________________________________________________ | | |||
649 | void ShadowHelper::uninstallWaylandShadows( QWidget* widget ) const | | |||
650 | { | | |||
651 | #if BREEZE_HAVE_KWAYLAND | | |||
652 | if( widget->windowHandle() && widget->windowHandle()->parent() ) return; | | |||
653 | if( !_shadowManager ) return; | | |||
654 | | ||||
655 | using namespace KWayland::Client; | | |||
656 | auto s = Surface::fromWindow( widget->windowHandle() ); | | |||
657 | if( !s ) return; | | |||
658 | | ||||
659 | _shadowManager->removeShadow( s ); | | |||
660 | s->commit( Surface::CommitFlag::None ); | | |||
661 | #else | | |||
662 | Q_UNUSED( widget ) | | |||
663 | #endif | | |||
664 | } | 473 | } | ||
665 | 474 | | |||
666 | } | 475 | } |