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 ®ion) 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 }