diff --git a/kdecoration/CMakeLists.txt b/kdecoration/CMakeLists.txt index e79d7288..42e0fd15 100644 --- a/kdecoration/CMakeLists.txt +++ b/kdecoration/CMakeLists.txt @@ -1,96 +1,96 @@ add_definitions(-DTRANSLATION_DOMAIN="breeze_kwin_deco") find_package(KF5 REQUIRED COMPONENTS CoreAddons GuiAddons ConfigWidgets WindowSystem I18n) find_package(Qt5 CONFIG REQUIRED COMPONENTS DBus) ### XCB find_package(XCB COMPONENTS XCB) set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding" - URL "http://xcb.freedesktop.org" + URL "https://xcb.freedesktop.org" TYPE OPTIONAL PURPOSE "Required to pass style properties to native Windows on X11 Platform" ) if(UNIX AND NOT APPLE) set(BREEZE_HAVE_X11 ${XCB_XCB_FOUND}) if (XCB_XCB_FOUND) find_package(Qt5 REQUIRED CONFIG COMPONENTS X11Extras) endif() else() set(BREEZE_HAVE_X11 FALSE) endif() ################# configuration ################# configure_file(config-breeze.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-breeze.h ) ################# includes ################# include_directories(${CMAKE_SOURCE_DIR}/libbreezecommon) include_directories(${CMAKE_BINARY_DIR}/libbreezecommon) ################# newt target ################# ### plugin classes set(breezedecoration_SRCS breezebutton.cpp breezedecoration.cpp breezeexceptionlist.cpp breezesettingsprovider.cpp breezesizegrip.cpp) kconfig_add_kcfg_files(breezedecoration_SRCS breezesettings.kcfgc) ### config classes ### they are kept separately because they might move in a separate library in the future set(breezedecoration_config_SRCS config/breezeconfigwidget.cpp config/breezedetectwidget.cpp config/breezeexceptiondialog.cpp config/breezeexceptionlistwidget.cpp config/breezeexceptionmodel.cpp config/breezeitemmodel.cpp ) set(breezedecoration_config_PART_FORMS config/ui/breezeconfigurationui.ui config/ui/breezedetectwidget.ui config/ui/breezeexceptiondialog.ui config/ui/breezeexceptionlistwidget.ui ) ki18n_wrap_ui(breezedecoration_config_PART_FORMS_HEADERS ${breezedecoration_config_PART_FORMS}) ### build library add_library(breezedecoration MODULE ${breezedecoration_SRCS} ${breezedecoration_config_SRCS} ${breezedecoration_config_PART_FORMS_HEADERS}) target_link_libraries(breezedecoration PUBLIC Qt5::Core Qt5::Gui Qt5::DBus PRIVATE breezecommon5 KDecoration2::KDecoration KF5::ConfigCore KF5::CoreAddons KF5::ConfigWidgets KF5::GuiAddons KF5::I18n KF5::WindowSystem) if(BREEZE_HAVE_X11) target_link_libraries(breezedecoration PUBLIC Qt5::X11Extras XCB::XCB) endif() install(TARGETS breezedecoration DESTINATION ${PLUGIN_INSTALL_DIR}/org.kde.kdecoration2) install(FILES config/breezedecorationconfig.desktop DESTINATION ${SERVICES_INSTALL_DIR}) diff --git a/kstyle/CMakeLists.txt b/kstyle/CMakeLists.txt index 2b061acf..ff16a72b 100644 --- a/kstyle/CMakeLists.txt +++ b/kstyle/CMakeLists.txt @@ -1,196 +1,196 @@ set(BREEZE_USE_KDE4 ${USE_KDE4}) if(BREEZE_USE_KDE4) ############ Language and toolchain features ############ copied from ECM if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" AND NOT WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") endif() endif() ################# Qt/KDE ################# if(BREEZE_USE_KDE4) ### XCB if(UNIX AND NOT APPLE) find_package(PkgConfig REQUIRED) pkg_check_modules(XCB xcb x11-xcb) add_feature_info("x11-xcb" XCB_FOUND "Required to pass style properties to native Windows on X11 Platform") - set_feature_info("x11-xcb" "Required to pass style properties to native Windows on X11 Platform" "http://xcb.freedesktop.org") + set_feature_info("x11-xcb" "Required to pass style properties to native Windows on X11 Platform" "https://xcb.freedesktop.org") set(BREEZE_HAVE_X11 ${XCB_FOUND}) else() set(BREEZE_HAVE_X11 FALSE) endif() set(BREEZE_HAVE_QTQUICK FALSE) set(BREEZE_HAVE_KWAYLAND FALSE) ### KStyle set(BREEZE_HAVE_KSTYLE FALSE) else() find_package(Qt5 REQUIRED CONFIG COMPONENTS Widgets DBus) find_package(KF5 REQUIRED COMPONENTS I18n Config GuiAddons ConfigWidgets WindowSystem) find_package(Qt5 COMPONENTS Quick) set(BREEZE_HAVE_QTQUICK ${Qt5Quick_FOUND}) find_package( KF5FrameworkIntegration CONFIG ) set_package_properties(KF5FrameworkIntegration PROPERTIES DESCRIPTION "KF5 Framework Integration" URL "https://projects.kde.org/projects/frameworks/frameworkintegration" TYPE OPTIONAL PURPOSE "Required to use KStyle convenience functionalities in style") set(BREEZE_HAVE_KSTYLE ${KF5FrameworkIntegration_FOUND}) find_package(XCB COMPONENTS XCB) set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding" - URL "http://xcb.freedesktop.org" + URL "https://xcb.freedesktop.org" TYPE OPTIONAL PURPOSE "Required to pass style properties to native Windows on X11 Platform" ) find_package(KF5Wayland CONFIG) set(BREEZE_HAVE_KWAYLAND ${KF5Wayland_FOUND}) if(UNIX AND NOT APPLE) set(BREEZE_HAVE_X11 ${XCB_XCB_FOUND}) if (XCB_XCB_FOUND) find_package(Qt5 REQUIRED CONFIG COMPONENTS X11Extras) endif() else() set(BREEZE_HAVE_X11 FALSE) endif() endif() ################# includes ################# include_directories( animations debug ) include_directories(${CMAKE_SOURCE_DIR}/libbreezecommon) include_directories(${CMAKE_BINARY_DIR}/libbreezecommon) ################# configuration ################# configure_file(config-breeze.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-breeze.h ) ########### next target ############### set(breeze_PART_SRCS animations/breezeanimation.cpp animations/breezeanimations.cpp animations/breezeanimationdata.cpp animations/breezebaseengine.cpp animations/breezebusyindicatordata.cpp animations/breezebusyindicatorengine.cpp animations/breezedialdata.cpp animations/breezedialengine.cpp animations/breezeenabledata.cpp animations/breezegenericdata.cpp animations/breezeheaderviewdata.cpp animations/breezeheaderviewengine.cpp animations/breezescrollbardata.cpp animations/breezescrollbarengine.cpp animations/breezespinboxengine.cpp animations/breezespinboxdata.cpp animations/breezestackedwidgetdata.cpp animations/breezestackedwidgetengine.cpp animations/breezetabbarengine.cpp animations/breezetabbardata.cpp animations/breezetoolboxengine.cpp animations/breezetransitiondata.cpp animations/breezetransitionwidget.cpp animations/breezewidgetstateengine.cpp animations/breezewidgetstatedata.cpp debug/breezewidgetexplorer.cpp breezeaddeventfilter.cpp breezeframeshadow.cpp breezehelper.cpp breezemdiwindowshadow.cpp breezemnemonics.cpp breezepropertynames.cpp breezeshadowhelper.cpp breezesplitterproxy.cpp breezestyle.cpp breezestyleplugin.cpp breezetileset.cpp breezewindowmanager.cpp ) if(NOT BREEZE_USE_KDE4) set(breeze_PART_SRCS ${breeze_PART_SRCS} breezeblurhelper.cpp ) endif() if(BREEZE_USE_KDE4) kde4_add_kcfg_files(breeze_PART_SRCS breezestyleconfigdata.kcfgc) kde4_add_plugin(breeze ${breeze_PART_SRCS} kstylekde4compat.cpp) target_link_libraries(breeze ${KDE4_KDEUI_LIBS}) target_link_libraries(breeze breezecommon4) if(BREEZE_HAVE_X11) target_link_libraries(breeze ${X11_XCB_LIBRARIES}) target_link_libraries(breeze ${XCB_LIBRARIES}) endif() install(TARGETS breeze DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/styles/) else() kconfig_add_kcfg_files(breeze_PART_SRCS breezestyleconfigdata.kcfgc) add_library(breeze MODULE ${breeze_PART_SRCS}) target_link_libraries(breeze Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus) if( BREEZE_HAVE_QTQUICK ) target_link_libraries(breeze Qt5::Quick) endif() target_link_libraries(breeze KF5::ConfigCore KF5::ConfigWidgets KF5::GuiAddons KF5::WindowSystem) target_link_libraries(breeze breezecommon5) if( KF5FrameworkIntegration_FOUND ) target_link_libraries(breeze KF5::Style) endif() if (WIN32) - # As stated in http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx M_PI only gets defined + # As stated in https://docs.microsoft.com/en-us/cpp/c-runtime-library/math-constants M_PI only gets defined # when if _USE_MATH_DEFINES is defined target_compile_definitions(breeze PRIVATE _USE_MATH_DEFINES _BSD_SOURCE) endif() if(BREEZE_HAVE_X11) target_link_libraries(breeze ${XCB_LIBRARIES}) target_link_libraries(breeze Qt5::X11Extras) endif() if(BREEZE_HAVE_KWAYLAND) target_link_libraries(breeze KF5::WaylandClient) endif() install(TARGETS breeze DESTINATION ${QT_PLUGIN_INSTALL_DIR}/styles/) endif() ########### install files ############### install(FILES breeze.themerc DESTINATION ${DATA_INSTALL_DIR}/kstyle/themes) ########### subdirectories ############### add_subdirectory(config) diff --git a/kstyle/breezeshadowhelper.cpp b/kstyle/breezeshadowhelper.cpp index 3ffdea4a..19249011 100644 --- a/kstyle/breezeshadowhelper.cpp +++ b/kstyle/breezeshadowhelper.cpp @@ -1,661 +1,661 @@ /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * Copyright (C) 2018 by Vlad Zagorodniy * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezeshadowhelper.h" #include "breeze.h" #include "breezeboxshadowrenderer.h" #include "breezehelper.h" #include "breezepropertynames.h" #include "breezestyleconfigdata.h" #include #include #include #include #include #include #include #include #if BREEZE_HAVE_X11 #include #endif #if BREEZE_HAVE_KWAYLAND #include #include #include #include #include #include #endif namespace { using Breeze::CompositeShadowParams; using Breeze::ShadowParams; const CompositeShadowParams s_shadowParams[] = { // None CompositeShadowParams(), // Small CompositeShadowParams( QPoint(0, 3), ShadowParams(QPoint(0, 0), 12, 0.26), ShadowParams(QPoint(0, -2), 6, 0.16)), // Medium CompositeShadowParams( QPoint(0, 4), ShadowParams(QPoint(0, 0), 16, 0.24), ShadowParams(QPoint(0, -2), 8, 0.14)), // Large CompositeShadowParams( QPoint(0, 5), ShadowParams(QPoint(0, 0), 20, 0.22), ShadowParams(QPoint(0, -3), 10, 0.12)), // Very Large CompositeShadowParams( QPoint(0, 6), ShadowParams(QPoint(0, 0), 24, 0.2), ShadowParams(QPoint(0, -3), 12, 0.1)) }; } namespace Breeze { const char ShadowHelper::netWMShadowAtomName[] ="_KDE_NET_WM_SHADOW"; //_____________________________________________________ CompositeShadowParams ShadowHelper::lookupShadowParams(int shadowSizeEnum) { switch (shadowSizeEnum) { case StyleConfigData::ShadowNone: return s_shadowParams[0]; case StyleConfigData::ShadowSmall: return s_shadowParams[1]; case StyleConfigData::ShadowMedium: return s_shadowParams[2]; case StyleConfigData::ShadowLarge: return s_shadowParams[3]; case StyleConfigData::ShadowVeryLarge: return s_shadowParams[4]; default: // Fallback to the Large size. return s_shadowParams[3]; } } //_____________________________________________________ ShadowHelper::ShadowHelper( QObject* parent, Helper& helper ): QObject( parent ), _helper( helper ) { // delay till event dispatcher is running as Wayland is highly async QMetaObject::invokeMethod(this, "initializeWayland", Qt::QueuedConnection); } //_______________________________________________________ ShadowHelper::~ShadowHelper() { #if BREEZE_HAVE_X11 if( Helper::isX11() ) { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } #endif } //_______________________________________________________ void ShadowHelper::initializeWayland() { #if BREEZE_HAVE_KWAYLAND if( !Helper::isWayland() ) return; using namespace KWayland::Client; auto connection = ConnectionThread::fromApplication( this ); if( !connection ) { return; } auto registry = new Registry( connection ); registry->create( connection ); connect(registry, &Registry::interfacesAnnounced, this, [registry, this] { const auto interface = registry->interface( Registry::Interface::Shadow ); if( interface.name != 0 ) { _shadowManager = registry->createShadowManager( interface.name, interface.version, registry ); } const auto shmInterface = registry->interface( Registry::Interface::Shm ); if( shmInterface.name != 0 ) { _shmPool = registry->createShmPool( shmInterface.name, shmInterface.version, registry ); } } ); registry->setup(); connection->roundtrip(); #endif } //______________________________________________ void ShadowHelper::reset() { #if BREEZE_HAVE_X11 if( Helper::isX11() ) { foreach( const quint32& value, _pixmaps ) xcb_free_pixmap( Helper::connection(), value ); } #endif _pixmaps.clear(); _shadowTiles = TileSet(); } //_______________________________________________________ bool ShadowHelper::registerWidget( QWidget* widget, bool force ) { // make sure widget is not already registered if( _widgets.contains( widget ) ) return false; // check if widget qualifies if( !( force || acceptWidget( widget ) ) ) { return false; } // try create shadow directly if( installShadows( widget ) ) _widgets.insert( widget, widget->winId() ); else _widgets.insert( widget, 0 ); // install event filter widget->removeEventFilter( this ); widget->installEventFilter( this ); // connect destroy signal connect( widget, SIGNAL(destroyed(QObject*)), SLOT(objectDeleted(QObject*)) ); return true; } //_______________________________________________________ void ShadowHelper::unregisterWidget( QWidget* widget ) { if( _widgets.remove( widget ) ) { uninstallShadows( widget ); } } //_______________________________________________________ void ShadowHelper::loadConfig() { // reset reset(); // update property for registered widgets for( QMap::const_iterator iter = _widgets.constBegin(); iter != _widgets.constEnd(); ++iter ) { installShadows( iter.key() ); } } //_______________________________________________________ bool ShadowHelper::eventFilter( QObject* object, QEvent* event ) { if( Helper::isWayland() ) { #if BREEZE_HAVE_KWAYLAND QWidget* widget( static_cast( object ) ); if( event->type() == QEvent::Paint ) { auto iter = _widgetSurfaces.constFind( widget ); if( iter == _widgetSurfaces.constEnd() ) { // install shadows and update winId installShadows( widget ); } } else if( event->type() == QEvent::Hide ) { auto iter = _widgetSurfaces.find( widget ); if( iter != _widgetSurfaces.end() ) { _widgetSurfaces.erase( iter ); } } #endif } else if( Helper::isX11() ) { // check event type if( event->type() != QEvent::WinIdChange ) return false; // cast widget QWidget* widget( static_cast( object ) ); // install shadows and update winId if( installShadows( widget ) ) { _widgets.insert( widget, widget->winId() ); } } return false; } //_______________________________________________________ TileSet ShadowHelper::shadowTiles() { const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); if (params.isNone()) { return TileSet(); } else if (_shadowTiles.isValid()) { return _shadowTiles; } auto withOpacity = [](const QColor &color, qreal opacity) -> QColor { QColor c(color); c.setAlphaF(opacity); return c; }; const QColor color = StyleConfigData::shadowColor(); const qreal strength = static_cast(StyleConfigData::shadowStrength()) / 255.0; const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius) .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius)); #if QT_VERSION >= 0x050300 const qreal dpr = qApp->devicePixelRatio(); #else const qreal dpr = 1.0; #endif const qreal frameRadius = _helper.frameRadius(); BoxShadowRenderer shadowRenderer; shadowRenderer.setBorderRadius(frameRadius); shadowRenderer.setBoxSize(boxSize); shadowRenderer.setDevicePixelRatio(dpr); shadowRenderer.addShadow(params.shadow1.offset, params.shadow1.radius, withOpacity(color, params.shadow1.opacity * strength)); shadowRenderer.addShadow(params.shadow2.offset, params.shadow2.radius, withOpacity(color, params.shadow2.opacity * strength)); QImage shadowTexture = shadowRenderer.render(); const QRect outerRect(QPoint(0, 0), shadowTexture.size() / dpr); QRect boxRect(QPoint(0, 0), boxSize); boxRect.moveCenter(outerRect.center()); // Mask out inner rect. QPainter painter(&shadowTexture); painter.setRenderHint(QPainter::Antialiasing); const QMargins margins = QMargins( boxRect.left() - outerRect.left() - Metrics::Shadow_Overlap - params.offset.x(), boxRect.top() - outerRect.top() - Metrics::Shadow_Overlap - params.offset.y(), outerRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(), outerRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y()); painter.setPen(Qt::NoPen); painter.setBrush(Qt::black); painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); painter.drawRoundedRect( #if BREEZE_USE_KDE4 outerRect.adjusted(margins.left(), margins.top(), -margins.right(), -margins.bottom()), #else outerRect - margins, #endif frameRadius, frameRadius); // We're done. painter.end(); const QPoint innerRectTopLeft = outerRect.center(); _shadowTiles = TileSet( QPixmap::fromImage(shadowTexture), innerRectTopLeft.x(), innerRectTopLeft.y(), 1, 1); return _shadowTiles; } //_______________________________________________________ void ShadowHelper::objectDeleted( QObject* object ) { _widgets.remove( static_cast( object ) ); } //_______________________________________________________ bool ShadowHelper::isMenu( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::isToolTip( QWidget* widget ) const { return widget->inherits( "QTipLabel" ) || (widget->windowFlags() & Qt::WindowType_Mask) == Qt::ToolTip; } //_______________________________________________________ bool ShadowHelper::isDockWidget( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::isToolBar( QWidget* widget ) const { return qobject_cast( widget ); } //_______________________________________________________ bool ShadowHelper::acceptWidget( QWidget* widget ) const { // flags if( widget->property( PropertyNames::netWMSkipShadow ).toBool() ) return false; if( widget->property( PropertyNames::netWMForceShadow ).toBool() ) return true; // menus if( isMenu( widget ) ) return true; // combobox dropdown lists if( widget->inherits( "QComboBoxPrivateContainer" ) ) return true; // tooltips if( isToolTip( widget ) && !widget->inherits( "Plasma::ToolTip" ) ) { return true; } // detached widgets if( isDockWidget( widget ) || isToolBar( widget ) ) { return true; } // reject return false; } //______________________________________________ const QVector& ShadowHelper::createPixmapHandles() { /** shadow atom and property specification available at - http://community.kde.org/KWin/Shadow + https://community.kde.org/KWin/Shadow */ // create atom #if BREEZE_HAVE_X11 if( !_atom && Helper::isX11() ) _atom = _helper.createAtom( QLatin1String( netWMShadowAtomName ) ); #endif // make sure size is valid if( _pixmaps.empty() ) { _pixmaps = QVector { createPixmap( _shadowTiles.pixmap( 1 ) ), createPixmap( _shadowTiles.pixmap( 2 ) ), createPixmap( _shadowTiles.pixmap( 5 ) ), createPixmap( _shadowTiles.pixmap( 8 ) ), createPixmap( _shadowTiles.pixmap( 7 ) ), createPixmap( _shadowTiles.pixmap( 6 ) ), createPixmap( _shadowTiles.pixmap( 3 ) ), createPixmap( _shadowTiles.pixmap( 0 ) ) }; } // return relevant list of pixmap handles return _pixmaps; } //______________________________________________ quint32 ShadowHelper::createPixmap( const QPixmap& source ) { // do nothing for invalid pixmaps if( source.isNull() ) return 0; if( !Helper::isX11() ) return 0; /* in some cases, pixmap handle is invalid. This is the case notably when Qt uses to RasterEngine. In this case, we create an X11 Pixmap explicitly and draw the source pixmap on it. */ #if BREEZE_HAVE_X11 const int width( source.width() ); const int height( source.height() ); // create X11 pixmap xcb_pixmap_t pixmap = xcb_generate_id( Helper::connection() ); xcb_create_pixmap( Helper::connection(), 32, pixmap, QX11Info::appRootWindow(), width, height ); // create gc if( !_gc ) { _gc = xcb_generate_id( Helper::connection() ); xcb_create_gc( Helper::connection(), _gc, pixmap, 0, nullptr ); } // create image from QPixmap and assign to pixmap QImage image( source.toImage() ); xcb_put_image( Helper::connection(), XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, image.width(), image.height(), 0, 0, 0, 32, image.byteCount(), image.constBits()); return pixmap; #else return 0; #endif } //_______________________________________________________ bool ShadowHelper::installShadows( QWidget* widget ) { if( !widget ) return false; /* From bespin code. Supposedly prevent playing with some 'pseudo-widgets' that have winId matching some other -random- window */ if( !(widget->testAttribute(Qt::WA_WState_Created) && widget->internalWinId() )) { return false; } // create shadow tiles if needed shadowTiles(); if( !_shadowTiles.isValid() ) return false; if( Helper::isX11() ) return installX11Shadows( widget ); if( Helper::isWayland() ) return installWaylandShadows( widget ); return false; } //_______________________________________________________ bool ShadowHelper::installX11Shadows( QWidget* widget ) { #if BREEZE_HAVE_X11 #ifndef QT_NO_XRENDER // create pixmap handles if needed QVector data( createPixmapHandles() ); if( data.size() != numPixmaps ) return false; const QMargins margins = shadowMargins( widget ); const quint32 topSize = margins.top(); const quint32 bottomSize = margins.bottom(); const quint32 leftSize( margins.left() ); const quint32 rightSize( margins.right() ); // assign to data and xcb property data << QVector{topSize, rightSize, bottomSize, leftSize}; xcb_change_property( Helper::connection(), XCB_PROP_MODE_REPLACE, widget->winId(), _atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); xcb_flush( Helper::connection() ); return true; #endif #endif return false; } //_______________________________________________________ bool ShadowHelper::installWaylandShadows( QWidget* widget ) { #if BREEZE_HAVE_KWAYLAND if( widget->windowHandle()->parent() ) return false; if( !_shadowManager || !_shmPool ) return false; // create shadow using namespace KWayland::Client; auto s = Surface::fromWindow( widget->windowHandle() ); if( !s ) return false; auto shadow = _shadowManager->createShadow( s, widget ); if( !shadow->isValid() ) return false; // add the shadow elements shadow->attachTop( _shmPool->createBuffer( _shadowTiles.pixmap( 1 ).toImage() ) ); shadow->attachTopRight( _shmPool->createBuffer( _shadowTiles.pixmap( 2 ).toImage() ) ); shadow->attachRight( _shmPool->createBuffer( _shadowTiles.pixmap( 5 ).toImage() ) ); shadow->attachBottomRight( _shmPool->createBuffer( _shadowTiles.pixmap( 8 ).toImage() ) ); shadow->attachBottom( _shmPool->createBuffer( _shadowTiles.pixmap( 7 ).toImage() ) ); shadow->attachBottomLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 6 ).toImage() ) ); shadow->attachLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 3 ).toImage() ) ); shadow->attachTopLeft( _shmPool->createBuffer( _shadowTiles.pixmap( 0 ).toImage() ) ); shadow->setOffsets( shadowMargins( widget ) ); shadow->commit(); s->commit( Surface::CommitFlag::None ); _widgetSurfaces.insert(widget, s); return true; #else Q_UNUSED( widget ); #endif return false; } //_______________________________________________________ QMargins ShadowHelper::shadowMargins( QWidget* widget ) const { const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); if (params.isNone()) { return QMargins(); } const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius) .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius)); const QSize shadowSize = BoxShadowRenderer::calculateMinimumShadowTextureSize(boxSize, params.shadow1.radius, params.shadow1.offset) .expandedTo(BoxShadowRenderer::calculateMinimumShadowTextureSize(boxSize, params.shadow2.radius, params.shadow2.offset)); const QRect shadowRect(QPoint(0, 0), shadowSize); QRect boxRect(QPoint(0, 0), boxSize); boxRect.moveCenter(shadowRect.center()); QMargins margins( boxRect.left() - shadowRect.left() - Metrics::Shadow_Overlap - params.offset.x(), boxRect.top() - shadowRect.top() - Metrics::Shadow_Overlap - params.offset.y(), shadowRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(), shadowRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y()); if (widget->inherits("QBalloonTip")) { // Balloon tip needs special margins to deal with the arrow. int top = 0; int bottom = 0; widget->getContentsMargins(nullptr, &top, nullptr, &bottom); // Need to decrement default size further due to extra hard coded round corner. #if BREEZE_USE_KDE4 margins.setLeft(margins.left() - 1); margins.setTop(margins.top() - 1); margins.setRight(margins.right() - 1); margins.setBottom(margins.bottom() - 1); #else margins -= 1; #endif // Arrow can be either to the top or the bottom. Adjust margins accordingly. const int diff = qAbs(top - bottom); if (top > bottom) { margins.setTop(margins.top() - diff); } else { margins.setBottom(margins.bottom() - diff); } } #if BREEZE_USE_KDE4 const qreal dpr = _helper.devicePixelRatio(_shadowTiles.pixmap(0)); margins.setLeft(margins.left() * dpr); margins.setTop(margins.top() * dpr); margins.setRight(margins.right() * dpr); margins.setBottom(margins.bottom() * dpr); #else margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); #endif return margins; } //_______________________________________________________ void ShadowHelper::uninstallShadows( QWidget* widget ) const { if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; if( Helper::isX11() ) uninstallX11Shadows( widget ); if( Helper::isWayland() ) uninstallWaylandShadows( widget ); } //_______________________________________________________ void ShadowHelper::uninstallX11Shadows( QWidget* widget ) const { #if BREEZE_HAVE_X11 xcb_delete_property( Helper::connection(), widget->winId(), _atom); #else Q_UNUSED( widget ) #endif } //_______________________________________________________ void ShadowHelper::uninstallWaylandShadows( QWidget* widget ) const { #if BREEZE_HAVE_KWAYLAND if( widget->windowHandle() && widget->windowHandle()->parent() ) return; if( !_shadowManager ) return; using namespace KWayland::Client; auto s = Surface::fromWindow( widget->windowHandle() ); if( !s ) return; _shadowManager->removeShadow( s ); s->commit( Surface::CommitFlag::None ); #else Q_UNUSED( widget ) #endif } } diff --git a/kstyle/breezeshadowhelper.h b/kstyle/breezeshadowhelper.h index 4d971e0c..f85612c5 100644 --- a/kstyle/breezeshadowhelper.h +++ b/kstyle/breezeshadowhelper.h @@ -1,228 +1,228 @@ #ifndef breezeshadowhelper_h #define breezeshadowhelper_h /************************************************************************* * Copyright (C) 2014 by Hugo Pereira Da Costa * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * *************************************************************************/ #include "breezetileset.h" #include "config-breeze.h" #include #include #include #include #if BREEZE_HAVE_X11 #include #endif #if BREEZE_HAVE_KWAYLAND namespace KWayland { namespace Client { class ShadowManager; class ShmPool; class Surface; } } #endif namespace Breeze { //* forward declaration class Helper; struct ShadowParams { ShadowParams() = default; ShadowParams(const QPoint &offset, int radius, qreal opacity): offset(offset), radius(radius), opacity(opacity) {} QPoint offset; int radius = 0; qreal opacity = 0; }; struct CompositeShadowParams { CompositeShadowParams() = default; CompositeShadowParams( const QPoint &offset, const ShadowParams &shadow1, const ShadowParams &shadow2) : offset(offset) , shadow1(shadow1) , shadow2(shadow2) {} bool isNone() const { return qMax(shadow1.radius, shadow2.radius) == 0; } QPoint offset; ShadowParams shadow1; ShadowParams shadow2; }; //* handle shadow pixmaps passed to window manager via X property class ShadowHelper: public QObject { Q_OBJECT public: //*@name property names //@{ static const char netWMShadowAtomName[]; //@} //* constructor ShadowHelper( QObject*, Helper& ); //* destructor ~ShadowHelper() override; //* shadow params from size enum static CompositeShadowParams lookupShadowParams( int shadowSizeEnum ); //* reset void reset(); //* load config void loadConfig(); //* register widget bool registerWidget( QWidget*, bool force = false ); //* unregister widget void unregisterWidget( QWidget* ); //* event filter bool eventFilter( QObject*, QEvent* ) override; //* shadow tiles /** is public because it is also needed for mdi windows */ TileSet shadowTiles(); protected Q_SLOTS: //* unregister widget void objectDeleted( QObject* ); //* initializes the Wayland specific parts void initializeWayland(); protected: //* true if widget is a menu bool isMenu( QWidget* ) const; //* true if widget is a tooltip bool isToolTip( QWidget* ) const; //* dock widget bool isDockWidget( QWidget* ) const; //* toolbar bool isToolBar( QWidget* ) const; //* accept widget bool acceptWidget( QWidget* ) const; // create pixmap handles from tileset const QVector& createPixmapHandles(); // create pixmap handle from pixmap quint32 createPixmap( const QPixmap& ); //* installs shadow on given widget in a platform independent way bool installShadows( QWidget * ); //* uninstalls shadow on given widget in a platform independent way void uninstallShadows( QWidget * ) const; //* install shadow X11 property on given widget /** shadow atom and property specification available at - http://community.kde.org/KWin/Shadow + https://community.kde.org/KWin/Shadow */ bool installX11Shadows( QWidget* ); //* uninstall shadow X11 property on given widget void uninstallX11Shadows( QWidget* ) const; //* install shadow on given widget for Wayland bool installWaylandShadows( QWidget * ); //* uninstall shadow on given widget for Wayland void uninstallWaylandShadows( QWidget* ) const; //* gets the shadow margins for the given widget QMargins shadowMargins( QWidget* ) const; private: //* helper Helper& _helper; //* registered widgets QMap _widgets; //* tileset TileSet _shadowTiles; //* number of pixmaps enum { numPixmaps = 8 }; //* pixmaps QVector _pixmaps; #if BREEZE_HAVE_X11 //* graphical context xcb_gcontext_t _gc = 0; //* shadow atom xcb_atom_t _atom = 0; #endif #if BREEZE_HAVE_KWAYLAND //* registered widgets to wayland surface mappings QMap _widgetSurfaces; //* The Wayland shadow manager to create Shadows for Surfaces (QWindow) QPointer _shadowManager; //* The Wayland Shared memory pool to share the shadow pixmaps with compositor QPointer _shmPool; #endif }; } #endif diff --git a/lookandfeel.dark/metadata.desktop b/lookandfeel.dark/metadata.desktop index b252128e..57225527 100644 --- a/lookandfeel.dark/metadata.desktop +++ b/lookandfeel.dark/metadata.desktop @@ -1,89 +1,89 @@ [Desktop Entry] Comment=Breeze Dark by the KDE VDG Comment[ca]=Brisa fosca pel VDG del KDE Comment[ca@valencia]=Brisa fosca per a VDG de KDE Comment[cs]=Breeze Dark od KDE VDG Comment[da]=Breeze Dark af KDE's visuelle designgruppe Comment[de]=Breeze-Dunkel von der KDE VDG Comment[en_GB]=Breeze Dark by the KDE VDG Comment[es]=Brisa oscuro por KDE VDG Comment[et]=Breeze tume KDE VDG-lt Comment[eu]=Breeze iluna, KDE VDGk egina Comment[fi]=Breeze Dark KDE VDG:ltä Comment[fr]=Breeze sombre, par KDE VDG Comment[gl]=Breeze escuro de KDE VDG Comment[hu]=Breeze Dark a KDE VDG-től Comment[id]=Breeze Gelap oleh KDE VDG Comment[it]=Brezza scuro a cura del VDG di KDE Comment[ko]=KDE VDG에서 만든 어두운 Breeze Comment[lt]=Breeze tamsus pagal KDE VDG Comment[nl]=Breeze Dark door de KDE VDG Comment[nn]=Breeze Dark frå KDE VDG Comment[pl]=Ciemna bryza autorstwa KDE VDG Comment[pt]=Brisa Escuro da VDG do KDE Comment[pt_BR]=Breeze Dark pelo KDE VDG Comment[ru]=Тёмный вариант Breeze от KDE VDG Comment[sk]=Téma Tmavý Vánok od dizajnovej skupiny KDE Visual Comment[sv]=Breeze mörk av KDE:s visuella designgrupp Comment[tg]=Насими торик аз KDE VDG Comment[uk]=Темна Breeze, автори — KDE VDG Comment[x-test]=xxBreeze Dark by the KDE VDGxx Comment[zh_CN]=暗色微风,由 KDE VDG 创作 Comment[zh_TW]=由 KDE VDG 製作的 Breeze Dark Name=Breeze Dark Name[ar]=نسيم داكن Name[bs]=Breeze tamna Name[ca]=Brisa fosca Name[ca@valencia]=Brisa fosca Name[cs]=Breeze Tmavé Name[da]=Breeze Dark Name[de]=Breeze-Dunkel Name[el]=Σκοτεινό Breeze Name[en_GB]=Breeze Dark Name[es]=Brisa oscuro Name[et]=Breeze tume Name[eu]=Breeze iluna Name[fi]=Breeze Dark Name[fr]=Brise sombre Name[gl]=Breeze Dark Name[he]=Breeze Dark Name[hu]=Breeze Dark Name[ia]=Brisa obscure Name[id]=Breeze Gelap Name[it]=Brezza scuro Name[ko]=어두운 Breeze Name[lt]=Breeze tamsus Name[nb]=Breeze mørk Name[nl]=Breeze Dark Name[nn]=Breeze mørk Name[pl]=Ciemna bryza Name[pt]=Brisa Escura Name[pt_BR]=Breeze Escuro Name[ro]=Briză Întunecat Name[ru]=Breeze, тёмный вариант Name[sk]=Tmavý vánok Name[sl]=Sapica (temna) Name[sr]=Поветарац тамни Name[sr@ijekavian]=Поветарац тамни Name[sr@ijekavianlatin]=Povetarac tamni Name[sr@latin]=Povetarac tamni Name[sv]=Breeze mörk Name[tg]=Насими торик Name[tr]=Koyu Esinti Name[uk]=Темна Breeze Name[x-test]=xxBreeze Darkxx Name[zh_CN]=暗色微风 Name[zh_TW]=Breeze Dark Type=Service X-KDE-ServiceTypes=Plasma/LookAndFeel X-KDE-ParentApp= X-KDE-PluginInfo-Author=KDE Visual Design Group X-KDE-PluginInfo-Category= X-KDE-PluginInfo-Email=plasma-devel@kde.org X-KDE-PluginInfo-License=GPL-2.0+ X-KDE-PluginInfo-Name=org.kde.breezedark.desktop X-KDE-PluginInfo-Version=2.0 -X-KDE-PluginInfo-Website=http://www.kde.org +X-KDE-PluginInfo-Website=https://www.kde.org X-Plasma-MainScript=defaults X-KDE-PluginInfo-License=GPLv2+