diff --git a/qt5/style/qtcurve_plugin.cpp b/qt5/style/qtcurve_plugin.cpp index b8c76ce7..8af8933c 100644 --- a/qt5/style/qtcurve_plugin.cpp +++ b/qt5/style/qtcurve_plugin.cpp @@ -1,189 +1,192 @@ /***************************************************************************** * Copyright 2013 - 2015 Yichao Yu * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 2.1 of the * * License, or (at your option) version 3, or any later version accepted * * by the membership of KDE e.V. (or its successor approved by the * * membership of KDE e.V.), which shall act as a proxy defined in * * Section 6 of version 3 of the license. * * * * 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library. If not, * * see . * *****************************************************************************/ #include "qtcurve_plugin.h" #include "qtcurve.h" #include "config-qt5.h" #include #include #include #include #include #ifdef Qt5X11Extras_FOUND # include # include #endif #ifdef QTC_QT5_ENABLE_QTQUICK2 # include # include #endif #include namespace QtCurve { // Using a `std::set` somehow result in a segfault in glibc (maybe realated to // this function being called in the exit handler?) so use a home made solution // instead... struct CleanupCallback { void (*func)(void*); void *data; CleanupCallback *next; CleanupCallback **prev; }; static CleanupCallback *cleanup_callbacks = nullptr; void* registerCleanup(void (*func)(void*), void *data) { auto cb = new CleanupCallback{func, data, cleanup_callbacks, &cleanup_callbacks}; if (cleanup_callbacks) cleanup_callbacks->prev = &cb->next; cleanup_callbacks = cb; return cb; } void unregisterCleanup(void *_cb) { auto cb = (CleanupCallback*)_cb; if (cb->next) cb->next->prev = cb->prev; *cb->prev = cb->next; delete cb; } static void runAllCleanups() { while (cleanup_callbacks) { auto func = cleanup_callbacks->func; auto data = cleanup_callbacks->data; func(data); } } __attribute__((hot)) static void polishQuickControl(QObject *obj) { #ifdef QTC_QT5_ENABLE_QTQUICK2 if (QQuickWindow *window = qobject_cast(obj)) { // QtQuickControl support // This is still VERY experimental. // Need a lot more testing and refactoring. if (Style *style = getStyle(qApp)) { if (window->inherits("QQuickPopupWindow")) { if (window->inherits("QQuickMenuPopupWindow")) { window->setColor(QColor(0, 0, 0, 0)); } qtcX11ShadowInstall(window->winId()); } else { QColor color = window->color(); int opacity = style->options().bgndOpacity; if (color.alpha() == 255 && opacity != 100) { qreal opacityF = opacity / 100.0; window->setColor(QColor::fromRgbF(color.redF() * opacityF, color.greenF() * opacityF, color.blueF() * opacityF, opacityF)); qtcX11BlurTrigger(window->winId(), true, 0, nullptr); } } } } else if (QQuickItem *item = qobject_cast(obj)) { if (QQuickWindow *window = item->window()) { if (getStyle(qApp)) { window->setColor(QColor(0, 0, 0, 0)); qtcX11BlurTrigger(window->winId(), true, 0, nullptr); } } } #else QTC_UNUSED(obj); #endif } __attribute__((hot)) static bool qtcEventCallback(void **cbdata) { QObject *receiver = (QObject*)cbdata[0]; QTC_RET_IF_FAIL(receiver, false); QEvent *event = (QEvent*)cbdata[1]; if (qtcUnlikely(event->type() == QEvent::DynamicPropertyChange)) { QDynamicPropertyChangeEvent *prop_event = static_cast(event); // eat the property change events from ourselves if (prop_event->propertyName() == QTC_PROP_NAME) { return true; } } QWidget *widget = qtcToWidget(receiver); if (qtcUnlikely(widget && !qtcGetWid(widget))) { if (Style *style = getStyle(widget)) { style->prePolish(widget); } } else if (widget && event->type() == QEvent::UpdateRequest) { QtcQWidgetProps props(widget); props->opacity = 100; } else { polishQuickControl(receiver); } return false; } QStyle* StylePlugin::create(const QString &key) { init(); return key.toLower() == "qtcurve" ? new Style : nullptr; } StylePlugin::~StylePlugin() { runAllCleanups(); - QInternal::unregisterCallback(QInternal::EventNotifyCallback, - qtcEventCallback); + if (m_eventNotifyCallbackInstalled) { + QInternal::unregisterCallback(QInternal::EventNotifyCallback, + qtcEventCallback); + } } void StylePlugin::init() { - std::call_once(m_ref_flag, [] { + std::call_once(m_ref_flag, [this] { QInternal::registerCallback(QInternal::EventNotifyCallback, qtcEventCallback); + m_eventNotifyCallbackInstalled = true; #ifdef QTC_QT5_ENABLE_QTQUICK2 QQuickWindow::setDefaultAlphaBuffer(true); #endif #ifdef Qt5X11Extras_FOUND if (qApp->platformName() == "xcb") { qtcX11InitXcb(QX11Info::connection(), QX11Info::appScreen()); } #endif }); } } diff --git a/qt5/style/qtcurve_plugin.h b/qt5/style/qtcurve_plugin.h index fc811077..1a0cf1d8 100644 --- a/qt5/style/qtcurve_plugin.h +++ b/qt5/style/qtcurve_plugin.h @@ -1,45 +1,46 @@ /***************************************************************************** * Copyright 2013 - 2015 Yichao Yu * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 2.1 of the * * License, or (at your option) version 3, or any later version accepted * * by the membership of KDE e.V. (or its successor approved by the * * membership of KDE e.V.), which shall act as a proxy defined in * * Section 6 of version 3 of the license. * * * * 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library. If not, * * see . * *****************************************************************************/ #ifndef __QTCURVE_PLUTIN_H__ #define __QTCURVE_PLUTIN_H__ #include #include namespace QtCurve { class StylePlugin: public QStylePlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QStyleFactoryInterface_iid FILE "qtcurvestyle.json") public: QStyle *create(const QString &key) override; ~StylePlugin(); private: void init(); + bool m_eventNotifyCallbackInstalled = false; std::once_flag m_ref_flag; }; void *registerCleanup(void (*func)(void*), void *data); void unregisterCleanup(void *handle); } #endif