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 <vladzzag@gmail.com> * | 3 | * Copyright (C) 2018, 2020 by Vlad Zahorodnii <vladzzag@gmail.com> * | ||
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 | _leftTile = nullptr; | ||
164 | if( Helper::isX11() ) | 112 | _topLeftTile = nullptr; | ||
165 | { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } | 113 | _topTile = nullptr; | ||
166 | #endif | 114 | _topRightTile = nullptr; | ||
167 | 115 | _rightTile = nullptr; | |||
168 | _pixmaps.clear(); | 116 | _bottomRightTile = nullptr; | ||
117 | _bottomTile = nullptr; | ||||
118 | _bottomLeftTile = nullptr; | ||||
169 | _shadowTiles = TileSet(); | 119 | _shadowTiles = TileSet(); | ||
170 | 120 | | |||
171 | } | 121 | } | ||
172 | 122 | | |||
173 | //_______________________________________________________ | 123 | //_______________________________________________________ | ||
174 | bool ShadowHelper::registerWidget( QWidget* widget, bool force ) | 124 | bool ShadowHelper::registerWidget( QWidget* widget, bool force ) | ||
175 | { | 125 | { | ||
176 | // make sure widget is not already registered | 126 | // make sure widget is not already registered | ||
177 | if( _widgets.contains( widget ) ) return false; | 127 | if( _widgets.contains( widget ) ) return false; | ||
178 | 128 | | |||
179 | // check if widget qualifies | 129 | // check if widget qualifies | ||
180 | if( !( force || acceptWidget( widget ) ) ) | 130 | if( !( force || acceptWidget( widget ) ) ) | ||
181 | { return false; } | 131 | { return false; } | ||
182 | 132 | | |||
183 | // try create shadow directly | 133 | // try create shadow directly | ||
184 | if( installShadows( widget ) ) _widgets.insert( widget, widget->winId() ); | 134 | installShadows( widget ); | ||
185 | else _widgets.insert( widget, 0 ); | 135 | _widgets.insert( widget ); | ||
186 | 136 | | |||
187 | // install event filter | 137 | // install event filter | ||
188 | widget->removeEventFilter( this ); | 138 | widget->removeEventFilter( this ); | ||
189 | widget->installEventFilter( this ); | 139 | widget->installEventFilter( this ); | ||
190 | 140 | | |||
191 | // connect destroy signal | 141 | // connect destroy signal | ||
192 | connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); | 142 | connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); | ||
193 | 143 | | |||
194 | return true; | 144 | return true; | ||
195 | 145 | | |||
196 | } | 146 | } | ||
197 | 147 | | |||
198 | //_______________________________________________________ | 148 | //_______________________________________________________ | ||
199 | void ShadowHelper::unregisterWidget( QWidget* widget ) | 149 | void ShadowHelper::unregisterWidget( QWidget* widget ) | ||
200 | { | 150 | { | ||
201 | if( _widgets.remove( widget ) ) | 151 | if( _widgets.remove( widget ) ) | ||
202 | { uninstallShadows( widget ); } | 152 | { uninstallShadows( widget ); } | ||
203 | } | 153 | } | ||
204 | 154 | | |||
205 | //_______________________________________________________ | 155 | //_______________________________________________________ | ||
206 | void ShadowHelper::loadConfig() | 156 | void ShadowHelper::loadConfig() | ||
207 | { | 157 | { | ||
208 | 158 | | |||
159 | // uninstall "old" shadows | ||||
160 | qDeleteAll( _shadows ); | ||||
161 | _shadows.clear(); | ||||
162 | | ||||
209 | // reset | 163 | // reset | ||
210 | reset(); | 164 | reset(); | ||
211 | 165 | | |||
212 | // update property for registered widgets | 166 | // update property for registered widgets | ||
213 | for( QMap<QWidget*,WId>::const_iterator iter = _widgets.constBegin(); iter != _widgets.constEnd(); ++iter ) | 167 | for( QWidget* widget : _widgets ) | ||
214 | { installShadows( iter.key() ); } | 168 | { installShadows( widget ); } | ||
215 | 169 | | |||
216 | } | 170 | } | ||
217 | 171 | | |||
218 | //_______________________________________________________ | 172 | //_______________________________________________________ | ||
219 | bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) | 173 | bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) | ||
220 | { | 174 | { | ||
221 | if( Helper::isWayland() ) | 175 | if( Helper::isX11() ) { | ||
222 | { | 176 | | ||
177 | // check event type | ||||
178 | if( event->type() != QEvent::WinIdChange ) return false; | ||||
223 | 179 | | |||
224 | #if BREEZE_HAVE_KWAYLAND | 180 | // cast widget | ||
225 | QWidget* widget( static_cast<QWidget*>( object ) ); | 181 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||
226 | if( event->type() == QEvent::Paint ) | | |||
227 | { | | |||
228 | 182 | | |||
229 | auto iter = _widgetSurfaces.constFind( widget ); | 183 | // reinstall shadows | ||
230 | if( iter == _widgetSurfaces.constEnd() ) | 184 | uninstallShadows( widget ); | ||
231 | { | | |||
232 | // install shadows and update winId | | |||
233 | installShadows( widget ); | 185 | installShadows( widget ); | ||
234 | } | 186 | } else { | ||
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 | | ||||
244 | } | | |||
245 | #endif | | |||
246 | | ||||
247 | } else if( Helper::isX11() ) { | | |||
248 | 187 | | |||
249 | // check event type | 188 | if( event->type() != QEvent::PlatformSurface ) return false; | ||
250 | if( event->type() != QEvent::WinIdChange ) return false; | | |||
251 | 189 | | |||
252 | // cast widget | | |||
253 | QWidget* widget( static_cast<QWidget*>( object ) ); | 190 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||
191 | QPlatformSurfaceEvent* surfaceEvent( static_cast<QPlatformSurfaceEvent*>( event ) ); | ||||
254 | 192 | | |||
255 | // install shadows and update winId | 193 | switch( surfaceEvent->surfaceEventType() ) | ||
256 | if( installShadows( widget ) ) | 194 | { | ||
257 | { _widgets.insert( widget, widget->winId() ); } | 195 | case QPlatformSurfaceEvent::SurfaceCreated: | ||
196 | installShadows( widget ); | ||||
197 | break; | ||||
198 | case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: | ||||
199 | uninstallShadows( widget ); | ||||
200 | break; | ||||
201 | } | ||||
258 | } | 202 | } | ||
259 | 203 | | |||
260 | return false; | 204 | return false; | ||
261 | 205 | | |||
262 | } | 206 | } | ||
263 | 207 | | |||
264 | //_______________________________________________________ | 208 | //_______________________________________________________ | ||
265 | TileSet ShadowHelper::shadowTiles() | 209 | TileSet ShadowHelper::shadowTiles() | ||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Line(s) | 282 | _shadowTiles = TileSet( | |||
342 | 1, 1); | 286 | 1, 1); | ||
343 | 287 | | |||
344 | return _shadowTiles; | 288 | return _shadowTiles; | ||
345 | } | 289 | } | ||
346 | 290 | | |||
347 | 291 | | |||
348 | //_______________________________________________________ | 292 | //_______________________________________________________ | ||
349 | void ShadowHelper::objectDeleted( QObject* object ) | 293 | void ShadowHelper::objectDeleted( QObject* object ) | ||
350 | { _widgets.remove( static_cast<QWidget*>( object ) ); } | 294 | { | ||
295 | | ||||
296 | QWidget* widget( static_cast<QWidget*>( object ) ); | ||||
297 | _widgets.remove( widget ); | ||||
298 | uninstallShadows( widget ); | ||||
299 | } | ||||
351 | 300 | | |||
352 | //_______________________________________________________ | 301 | //_______________________________________________________ | ||
353 | bool ShadowHelper::isMenu( QWidget* widget ) const | 302 | bool ShadowHelper::isMenu( QWidget* widget ) const | ||
354 | { return qobject_cast<QMenu*>( widget ); } | 303 | { return qobject_cast<QMenu*>( widget ); } | ||
355 | 304 | | |||
356 | //_______________________________________________________ | 305 | //_______________________________________________________ | ||
357 | bool ShadowHelper::isToolTip( QWidget* widget ) const | 306 | bool ShadowHelper::isToolTip( QWidget* widget ) const | ||
358 | { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } | 307 | { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } | ||
Show All 27 Lines | 319 | { | |||
386 | // detached widgets | 335 | // detached widgets | ||
387 | if( isDockWidget( widget ) || isToolBar( widget ) ) | 336 | if( isDockWidget( widget ) || isToolBar( widget ) ) | ||
388 | { return true; } | 337 | { return true; } | ||
389 | 338 | | |||
390 | // reject | 339 | // reject | ||
391 | return false; | 340 | return false; | ||
392 | } | 341 | } | ||
393 | 342 | | |||
394 | //______________________________________________ | | |||
395 | const QVector<quint32>& ShadowHelper::createPixmapHandles() | | |||
396 | { | | |||
397 | | ||||
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 | | |||
409 | if( _pixmaps.empty() ) | | |||
410 | { | | |||
411 | _pixmaps = QVector<quint32> { | | |||
412 | createPixmap( _shadowTiles.pixmap( 1 ) ), | | |||
413 | createPixmap( _shadowTiles.pixmap( 2 ) ), | | |||
414 | createPixmap( _shadowTiles.pixmap( 5 ) ), | | |||
415 | createPixmap( _shadowTiles.pixmap( 8 ) ), | | |||
416 | createPixmap( _shadowTiles.pixmap( 7 ) ), | | |||
417 | createPixmap( _shadowTiles.pixmap( 6 ) ), | | |||
418 | createPixmap( _shadowTiles.pixmap( 3 ) ), | | |||
419 | createPixmap( _shadowTiles.pixmap( 0 ) ) | | |||
420 | }; | | |||
421 | } | | |||
422 | | ||||
423 | // return relevant list of pixmap handles | | |||
424 | return _pixmaps; | | |||
425 | | ||||
426 | } | | |||
427 | | ||||
428 | //______________________________________________ | | |||
429 | quint32 ShadowHelper::createPixmap( 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 | { | | |||
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 | xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.sizeInBytes(), image.constBits()); | | |||
461 | | ||||
462 | return pixmap; | | |||
463 | | ||||
464 | #else | | |||
465 | return 0; | | |||
466 | #endif | | |||
467 | | ||||
468 | } | | |||
469 | | ||||
470 | //_______________________________________________________ | 343 | //_______________________________________________________ | ||
471 | bool ShadowHelper::installShadows( QWidget* widget ) | 344 | bool ShadowHelper::installShadows( QWidget* widget ) | ||
472 | { | 345 | { | ||
473 | if( !widget ) return false; | 346 | Q_ASSERT( !_shadows.contains( widget ) ); | ||
474 | 347 | | |||
475 | /* | 348 | // Decorate only toplevel widgets. | ||
476 | From bespin code. Supposedly prevent playing with some 'pseudo-widgets' | 349 | if( !widget || !widget->isWindow() ) return false; | ||
477 | that have winId matching some other -random- window | 350 | | ||
478 | */ | 351 | // The widget is not backed by a native window, bail out. | ||
479 | if( !(widget->testAttribute(Qt::WA_WState_Created) && widget->internalWinId() )) | 352 | if( !widget->windowHandle() ) return false; | ||
480 | { return false; } | | |||
481 | 353 | | |||
482 | // create shadow tiles if needed | 354 | // create shadow tiles if needed | ||
483 | shadowTiles(); | 355 | shadowTiles(); | ||
484 | 356 | | |||
485 | if( !_shadowTiles.isValid() ) return false; | 357 | if( !_shadowTiles.isValid() ) return false; | ||
486 | 358 | | |||
487 | if( Helper::isX11() ) return installX11Shadows( widget ); | 359 | KWindowShadow *shadow = new KWindowShadow(); | ||
488 | if( Helper::isWayland() ) return installWaylandShadows( widget ); | | |||
489 | 360 | | |||
490 | return false; | 361 | shadow->setLeftTile( getOrCreateLeftTile() ); | ||
491 | } | 362 | shadow->setTopLeftTile( getOrCreateTopLeftTile() ); | ||
492 | 363 | shadow->setTopTile( getOrCreateTopTile() ); | |||
493 | //_______________________________________________________ | 364 | shadow->setTopRightTile( getOrCreateTopRightTile() ); | ||
494 | bool ShadowHelper::installX11Shadows( QWidget* widget ) | 365 | shadow->setRightTile( getOrCreateRightTile() ); | ||
495 | { | 366 | shadow->setBottomRightTile( getOrCreateBottomRightTile() ); | ||
496 | #if BREEZE_HAVE_X11 | 367 | shadow->setBottomTile( getOrCreateBottomTile() ); | ||
497 | #ifndef QT_NO_XRENDER | 368 | shadow->setBottomLeftTile( getOrCreateBottomLeftTile() ); | ||
369 | shadow->setPadding( shadowMargins(widget) ); | ||||
370 | shadow->setWindow( widget->windowHandle() ); | ||||
371 | shadow->create(); | ||||
498 | 372 | | |||
499 | // create pixmap handles if needed | 373 | _shadows.insert( widget, shadow ); | ||
500 | QVector<quint32> data( createPixmapHandles() ); | | |||
501 | if( data.size() != numPixmaps ) return false; | | |||
502 | | ||||
503 | const QMargins margins = shadowMargins( widget ); | | |||
504 | const quint32 topSize = margins.top(); | | |||
505 | const quint32 bottomSize = margins.bottom(); | | |||
506 | const quint32 leftSize( margins.left() ); | | |||
507 | const quint32 rightSize( margins.right() ); | | |||
508 | | ||||
509 | // assign to data and xcb property | | |||
510 | data << QVector<quint32>{topSize, rightSize, bottomSize, leftSize}; | | |||
511 | xcb_change_property( Helper::connection(), XCB_PROP_MODE_REPLACE, widget->winId(), _atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); | | |||
512 | xcb_flush( Helper::connection() ); | | |||
513 | 374 | | |||
514 | return true; | 375 | return true; | ||
515 | | ||||
516 | #endif | | |||
517 | #endif | | |||
518 | | ||||
519 | return false; | | |||
520 | | ||||
521 | } | | |||
522 | | ||||
523 | //_______________________________________________________ | | |||
524 | bool ShadowHelper::installWaylandShadows( QWidget* widget ) | | |||
525 | { | | |||
526 | #if BREEZE_HAVE_KWAYLAND | | |||
527 | if( widget->windowHandle()->parent() ) return false; | | |||
528 | if( !_shadowManager || !_shmPool ) return false; | | |||
529 | | ||||
530 | // create shadow | | |||
531 | using namespace KWayland::Client; | | |||
532 | auto s = Surface::fromWindow( widget->windowHandle() ); | | |||
533 | if( !s ) return false; | | |||
534 | | ||||
535 | auto shadow = _shadowManager->createShadow( s, widget ); | | |||
536 | if( !shadow->isValid() ) return false; | | |||
537 | | ||||
538 | // add the shadow elements | | |||
539 | shadow->attachTop( _shmPool->createBuffer( _shadowTiles.pixmap( 1 ).toImage() ) ); | | |||
540 | shadow->attachTopRight( _shmPool->createBuffer( _shadowTiles.pixmap( 2 ).toImage() ) ); | | |||
541 | shadow->attachRight( _shmPool->createBuffer( _shadowTiles.pixmap( 5 ).toImage() ) ); | | |||
542 | shadow->attachBottomRight( _shmPool->createBuffer( _shadowTiles.pixmap( 8 ).toImage() ) ); | | |||
543 | shadow->attachBottom( _shmPool->createBuffer( _shadowTiles.pixmap( 7 ).toImage() ) ); | | |||
544 | shadow->attachBottomLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 6 ).toImage() ) ); | | |||
545 | shadow->attachLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 3 ).toImage() ) ); | | |||
546 | shadow->attachTopLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 0 ).toImage() ) ); | | |||
547 | | ||||
548 | shadow->setOffsets( shadowMargins( widget ) ); | | |||
549 | shadow->commit(); | | |||
550 | s->commit( Surface::CommitFlag::None ); | | |||
551 | _widgetSurfaces.insert(widget, s); | | |||
552 | | ||||
553 | return true; | | |||
554 | #else | | |||
555 | Q_UNUSED( widget ); | | |||
556 | #endif | | |||
557 | | ||||
558 | return false; | | |||
559 | } | 376 | } | ||
560 | 377 | | |||
561 | //_______________________________________________________ | 378 | //_______________________________________________________ | ||
562 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | 379 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | ||
563 | { | 380 | { | ||
564 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | 381 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | ||
565 | if (params.isNone()) { | 382 | if (params.isNone()) { | ||
566 | return QMargins(); | 383 | return QMargins(); | ||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Line(s) | |||||
616 | #else | 433 | #else | ||
617 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | 434 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | ||
618 | #endif | 435 | #endif | ||
619 | 436 | | |||
620 | return margins; | 437 | return margins; | ||
621 | } | 438 | } | ||
622 | 439 | | |||
623 | //_______________________________________________________ | 440 | //_______________________________________________________ | ||
624 | void ShadowHelper::uninstallShadows( QWidget* widget ) const | 441 | void ShadowHelper::uninstallShadows( QWidget* widget ) | ||
625 | { | 442 | { | ||
626 | if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; | 443 | delete _shadows.take( widget ); | ||
627 | if( Helper::isX11() ) uninstallX11Shadows( widget ); | | |||
628 | if( Helper::isWayland() ) uninstallWaylandShadows( widget ); | | |||
629 | } | 444 | } | ||
630 | 445 | | |||
631 | //_______________________________________________________ | 446 | //_______________________________________________________ | ||
632 | void ShadowHelper::uninstallX11Shadows( QWidget* widget ) const | 447 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateLeftTile() | ||
633 | { | 448 | { | ||
634 | #if BREEZE_HAVE_X11 | 449 | if( _leftTile ) return _leftTile; | ||
635 | xcb_delete_property( Helper::connection(), widget->winId(), _atom); | 450 | | ||
636 | #else | 451 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||
637 | Q_UNUSED( widget ) | 452 | tile->setImage( _shadowTiles.pixmap( 3 ).toImage() ); | ||
638 | #endif | | |||
639 | 453 | | |||
454 | _leftTile = tile; | ||||
455 | | ||||
456 | return tile; | ||||
640 | } | 457 | } | ||
641 | 458 | | |||
642 | //_______________________________________________________ | 459 | //_______________________________________________________ | ||
643 | void ShadowHelper::uninstallWaylandShadows( QWidget* widget ) const | 460 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateTopLeftTile() | ||
644 | { | 461 | { | ||
645 | #if BREEZE_HAVE_KWAYLAND | 462 | if( _topLeftTile ) return _topLeftTile; | ||
646 | if( widget->windowHandle() && widget->windowHandle()->parent() ) return; | | |||
647 | if( !_shadowManager ) return; | | |||
648 | | ||||
649 | using namespace KWayland::Client; | | |||
650 | auto s = Surface::fromWindow( widget->windowHandle() ); | | |||
651 | if( !s ) return; | | |||
652 | 463 | | |||
653 | _shadowManager->removeShadow( s ); | 464 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||
654 | s->commit( Surface::CommitFlag::None ); | 465 | tile->setImage( _shadowTiles.pixmap( 0 ).toImage() ); | ||
655 | #else | 466 | | ||
656 | Q_UNUSED( widget ) | 467 | _topLeftTile = tile; | ||
657 | #endif | 468 | | ||
469 | return tile; | ||||
470 | } | ||||
471 | | ||||
472 | //_______________________________________________________ | ||||
473 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateTopTile() | ||||
474 | { | ||||
475 | if( _topTile ) return _topTile; | ||||
476 | | ||||
477 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||||
478 | tile->setImage( _shadowTiles.pixmap( 1 ).toImage() ); | ||||
479 | | ||||
480 | _topTile = tile; | ||||
481 | | ||||
482 | return tile; | ||||
483 | } | ||||
484 | | ||||
485 | //_______________________________________________________ | ||||
486 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateTopRightTile() | ||||
487 | { | ||||
488 | if( _topRightTile ) return _topRightTile; | ||||
489 | | ||||
490 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||||
491 | tile->setImage( _shadowTiles.pixmap( 2 ).toImage() ); | ||||
492 | | ||||
493 | _topRightTile = tile; | ||||
494 | | ||||
495 | return tile; | ||||
496 | } | ||||
497 | | ||||
498 | //_______________________________________________________ | ||||
499 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateRightTile() | ||||
500 | { | ||||
501 | if( _rightTile ) return _rightTile; | ||||
502 | | ||||
503 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||||
504 | tile->setImage( _shadowTiles.pixmap( 5 ).toImage() ); | ||||
505 | | ||||
506 | _rightTile = tile; | ||||
507 | | ||||
508 | return tile; | ||||
509 | } | ||||
510 | | ||||
511 | //_______________________________________________________ | ||||
512 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateBottomRightTile() | ||||
513 | { | ||||
514 | if( _bottomRightTile ) return _bottomRightTile; | ||||
515 | | ||||
516 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||||
517 | tile->setImage( _shadowTiles.pixmap( 8 ).toImage() ); | ||||
518 | | ||||
519 | _bottomRightTile = tile; | ||||
520 | | ||||
521 | return tile; | ||||
522 | } | ||||
523 | | ||||
524 | //_______________________________________________________ | ||||
525 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateBottomTile() | ||||
526 | { | ||||
527 | if( _bottomTile ) return _bottomTile; | ||||
528 | | ||||
529 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||||
530 | tile->setImage( _shadowTiles.pixmap( 7 ).toImage() ); | ||||
531 | | ||||
532 | _bottomTile = tile; | ||||
533 | | ||||
534 | return tile; | ||||
535 | } | ||||
536 | | ||||
537 | //_______________________________________________________ | ||||
538 | KWindowShadowTile::Ptr ShadowHelper::getOrCreateBottomLeftTile() | ||||
539 | { | ||||
540 | if( _bottomLeftTile ) return _bottomLeftTile; | ||||
541 | | ||||
542 | KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); | ||||
543 | tile->setImage( _shadowTiles.pixmap( 6 ).toImage() ); | ||||
544 | | ||||
545 | _bottomLeftTile = tile; | ||||
546 | | ||||
547 | return tile; | ||||
658 | } | 548 | } | ||
659 | 549 | | |||
660 | } | 550 | } |