File indexing completed on 2024-04-28 17:04:21

0001 /*****************************************************************************
0002  *   Copyright 2010 Craig Drummond <craig.p.drummond@gmail.com>              *
0003  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0004  *                                                                           *
0005  *   This program is free software; you can redistribute it and/or modify    *
0006  *   it under the terms of the GNU Lesser General Public License as          *
0007  *   published by the Free Software Foundation; either version 2.1 of the    *
0008  *   License, or (at your option) version 3, or any later version accepted   *
0009  *   by the membership of KDE e.V. (or its successor approved by the         *
0010  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0011  *   Section 6 of version 3 of the license.                                  *
0012  *                                                                           *
0013  *   This program is distributed in the hope that it will be useful,         *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0016  *   Lesser General Public License for more details.                         *
0017  *                                                                           *
0018  *   You should have received a copy of the GNU Lesser General Public        *
0019  *   License along with this library. If not,                                *
0020  *   see <http://www.gnu.org/licenses/>.                                     *
0021  *****************************************************************************/
0022 
0023 //////////////////////////////////////////////////////////////////////////////
0024 // blurhelper.cpp
0025 // handle regions passed to kwin for blurring
0026 // -------------------
0027 //
0028 // Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
0029 //
0030 // Loosely inspired (and largely rewritten) from BeSpin style
0031 // Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
0032 //
0033 // Permission is hereby granted, free of charge, to any person obtaining a copy
0034 // of this software and associated documentation files (the "Software"), to
0035 // deal in the Software without restriction, including without limitation the
0036 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
0037 // sell copies of the Software, and to permit persons to whom the Software is
0038 // furnished to do so, subject to the following conditions:
0039 //
0040 // The above copyright notice and this permission notice shall be included in
0041 // all copies or substantial portions of the Software.
0042 //
0043 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0044 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0045 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0046 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0047 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0048 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0049 // IN THE SOFTWARE.
0050 //////////////////////////////////////////////////////////////////////////////
0051 
0052 #include <config.h>
0053 #include "blurhelper.h"
0054 
0055 #include <QEvent>
0056 #include <QVector>
0057 #include <QDockWidget>
0058 #include <QMenu>
0059 #include <QProgressBar>
0060 #include <QPushButton>
0061 #include <QToolBar>
0062 
0063 #include <qtcurve-utils/qtutils.h>
0064 #include <qtcurve-utils/x11blur.h>
0065 
0066 namespace QtCurve {
0067 BlurHelper::BlurHelper(QObject *parent):
0068     QObject(parent),
0069     _enabled(false)
0070 {
0071 }
0072 
0073 void
0074 BlurHelper::registerWidget(QWidget* widget)
0075 {
0076     widget->installEventFilter(this);
0077 }
0078 
0079 void
0080 BlurHelper::unregisterWidget(QWidget *widget)
0081 {
0082     widget->removeEventFilter(this);
0083     if (isTransparent(widget)) {
0084         clear(qtcGetWid(widget));
0085     }
0086 }
0087 
0088 bool
0089 BlurHelper::eventFilter(QObject *object, QEvent *event)
0090 {
0091     // do nothing if not enabled
0092     if (!enabled())
0093         return false;
0094     switch (event->type()) {
0095     case QEvent::Hide: {
0096         QWidget *widget = qtcToWidget(object);
0097         if (widget && isOpaque(widget)) {
0098             QWidget *window(widget->window());
0099             if (window && isTransparent(window) &&
0100                 !_pendingWidgets.contains(window)) {
0101                 _pendingWidgets.insert(window, window);
0102                 delayedUpdate();
0103             }
0104         }
0105         break;
0106     }
0107     case QEvent::Show:
0108     case QEvent::Resize: {
0109         // cast to widget and check
0110         QWidget *widget = qtcToWidget(object);
0111         if (!widget)
0112             break;
0113         if (isTransparent(widget)) {
0114             _pendingWidgets.insert(widget, widget);
0115             delayedUpdate();
0116         } else if (isOpaque(widget)) {
0117             QWidget* window(widget->window());
0118             if (isTransparent(window)) {
0119                 _pendingWidgets.insert(window, window);
0120                 delayedUpdate();
0121             }
0122         }
0123         break;
0124     }
0125     default:
0126         break;
0127     }
0128     // never eat events
0129     return false;
0130 }
0131 
0132 QRegion
0133 BlurHelper::blurRegion(QWidget *widget) const
0134 {
0135     if (!widget->isVisible())
0136         return QRegion();
0137     // get main region
0138     QRegion region = widget->mask().isEmpty() ? widget->rect() : widget->mask();
0139     // trim blur region to remove unnecessary areas
0140     trimBlurRegion(widget, widget, region);
0141     return region;
0142 }
0143 
0144 void
0145 BlurHelper::trimBlurRegion(QWidget *parent, QWidget *widget,
0146                            QRegion &region) const
0147 {
0148     // TODO:
0149     //     Maybe we should clip children with parent? In case we hit this[1] kind
0150     //     of bugs again.
0151     //     [1] https://bugs.kde.org/show_bug.cgi?id=306631
0152     // loop over children
0153     foreach (QObject *childObject, widget->children()) {
0154         QWidget *child = qtcToWidget(childObject);
0155         if (!(child && child->isVisible()))
0156             continue;
0157         if (isOpaque(child)) {
0158             const QPoint offset(child->mapTo(parent, QPoint(0, 0)));
0159             if (child->mask().isEmpty()) {
0160                 region -= child->rect().translated(offset);
0161             } else {
0162                 region -= child->mask().translated(offset);
0163             }
0164         } else {
0165             trimBlurRegion(parent, child, region);
0166         }
0167     }
0168     return;
0169 }
0170 
0171 void
0172 BlurHelper::update(QWidget *widget) const
0173 {
0174     // DO NOT condition compile on QTC_ENABLE_X11.
0175     // There's no direct linkage on X11 and the following code will just do
0176     // nothing if X11 is not enabled (either at compile time or at run time).
0177     QTC_RET_IF_FAIL(qtcX11Enabled());
0178     // Do not create native window if there isn't one yet.
0179     WId wid = qtcGetWid(widget);
0180     if (!wid) {
0181         return;
0182     }
0183     const QRegion region(blurRegion(widget));
0184     if (region.isEmpty()) {
0185         clear(wid);
0186     } else {
0187         QVector<uint32_t> data;
0188         foreach (const QRect &rect, region.rects()) {
0189             data << rect.x() << rect.y() << rect.width() << rect.height();
0190         }
0191         qtcX11BlurTrigger(wid, true, data.size(), data.constData());
0192     }
0193     // force update
0194     if (widget->isVisible()) {
0195         widget->update();
0196     }
0197 }
0198 
0199 void
0200 BlurHelper::clear(WId wid) const
0201 {
0202     // DO NOT condition compile on QTC_ENABLE_X11.
0203     // There's no direct linkage on X11 and the following code will just do
0204     // nothing if X11 is not enabled (either at compile time or at run time).
0205     QTC_RET_IF_FAIL(qtcX11Enabled());
0206     qtcX11BlurTrigger(wid, false, 0, 0);
0207 }
0208 }