File indexing completed on 2024-04-28 05:47:26

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 // shadowhelper.h
0025 // handle shadow _pixmaps passed to window manager via X property
0026 // -------------------
0027 //
0028 // Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
0029 //
0030 // Permission is hereby granted, free of charge, to any person obtaining a copy
0031 // of this software and associated documentation files (the "Software"), to
0032 // deal in the Software without restriction, including without limitation the
0033 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
0034 // sell copies of the Software, and to permit persons to whom the Software is
0035 // furnished to do so, subject to the following conditions:
0036 //
0037 // The above copyright notice and this permission notice shall be included in
0038 // all copies or substantial portions of the Software.
0039 //
0040 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0041 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0042 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0043 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0044 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0045 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0046 // IN THE SOFTWARE.
0047 //////////////////////////////////////////////////////////////////////////////
0048 
0049 #include "shadowhelper.h"
0050 #include "utils.h"
0051 
0052 #include <QDockWidget>
0053 #include <QMenu>
0054 #include <QPainter>
0055 #include <QToolBar>
0056 #include <QEvent>
0057 
0058 #include <qtcurve-utils/x11shadow.h>
0059 #include <qtcurve-utils/qtprops.h>
0060 
0061 namespace QtCurve {
0062 const char *const ShadowHelper::netWMForceShadowPropertyName =
0063     "_KDE_NET_WM_FORCE_SHADOW";
0064 const char *const ShadowHelper::netWMSkipShadowPropertyName =
0065     "_KDE_NET_WM_SKIP_SHADOW";
0066 
0067 bool
0068 ShadowHelper::registerWidget(QWidget *widget, bool force)
0069 {
0070     QtcQWidgetProps props(widget);
0071     // make sure widget is not already registered
0072     if (props->shadowRegistered)
0073         return false;
0074     // check if widget qualifies
0075     if (!(force || acceptWidget(widget)))
0076         return false;
0077     props->shadowRegistered = true;
0078     // WinIdChange Event, should not happen though
0079     widget->installEventFilter(this);
0080     installX11Shadows(widget);
0081     return true;
0082 }
0083 
0084 void
0085 ShadowHelper::unregisterWidget(QWidget *widget)
0086 {
0087     QtcQWidgetProps props(widget);
0088     if (props->shadowRegistered) {
0089         uninstallX11Shadows(widget);
0090         props->shadowRegistered = false;
0091     }
0092 }
0093 
0094 bool
0095 ShadowHelper::eventFilter(QObject *object, QEvent *event)
0096 {
0097     if (event->type() == QEvent::WinIdChange)
0098         installX11Shadows(static_cast<QWidget*>(object));
0099     return false;
0100 }
0101 
0102 bool
0103 ShadowHelper::acceptWidget(QWidget *widget) const
0104 {
0105     if (widget->property(netWMSkipShadowPropertyName).toBool())
0106         return false;
0107     if (widget->property(netWMForceShadowPropertyName).toBool())
0108         return true;
0109 
0110     // menus
0111     if (qobject_cast<QMenu*>(widget))
0112         return true;
0113 
0114     // combobox dropdown lists
0115     if (widget->inherits("QComboBoxPrivateContainer"))
0116         return true;
0117 
0118     // tooltips
0119     if ((widget->windowType() == Qt::ToolTip ||
0120          widget->inherits("QTipLabel")) && !widget->inherits("Plasma::ToolTip"))
0121         return true;
0122 
0123     // detached widgets
0124     if (qobject_cast<QToolBar*>(widget) || qobject_cast<QDockWidget*>(widget))
0125         return true;
0126 
0127     // reject
0128     return false;
0129 }
0130 
0131 bool
0132 ShadowHelper::installX11Shadows(QWidget *widget)
0133 {
0134     // DO NOT condition compile on QTC_ENABLE_X11.
0135     // There's no direct linkage on X11 and the following code will just do
0136     // nothing if X11 is not enabled (either at compile time or at run time).
0137     QTC_RET_IF_FAIL(qtcX11Enabled(), false);
0138     if (WId wid = qtcGetWid(widget)) {
0139         if (widget->windowType() == Qt::ToolTip &&
0140             widget->inherits("QBalloonTip")) {
0141             bool atTop = true;
0142             int margin = qtcGetBalloonMargin(widget, &atTop);
0143             int margins[4] = {0, 0, 0, 0};
0144             // KWin's shadows margin order is top, right, bottom, left..
0145             margins[atTop ? 0 : 2] = margin;
0146             qtcX11ShadowInstall(wid, margins);
0147         } else {
0148             qtcX11ShadowInstall(wid);
0149         }
0150         return true;
0151     }
0152     return false;
0153 }
0154 
0155 void
0156 ShadowHelper::uninstallX11Shadows(QWidget *widget) const
0157 {
0158     // DO NOT condition compile on QTC_ENABLE_X11.
0159     // There's no direct linkage on X11 and the following code will just do
0160     // nothing if X11 is not enabled (either at compile time or at run time).
0161     QTC_RET_IF_FAIL(qtcX11Enabled());
0162     if (WId wid = qtcGetWid(widget)) {
0163         qtcX11ShadowUninstall(wid);
0164     }
0165 }
0166 }