1 /*****************************************************************************
2  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
3  *                                                                           *
4  *   This program is free software; you can redistribute it and/or modify    *
5  *   it under the terms of the GNU Lesser General Public License as          *
6  *   published by the Free Software Foundation; either version 2.1 of the    *
7  *   License, or (at your option) version 3, or any later version accepted   *
8  *   by the membership of KDE e.V. (or its successor approved by the         *
9  *   membership of KDE e.V.), which shall act as a proxy defined in          *
10  *   Section 6 of version 3 of the license.                                  *
11  *                                                                           *
12  *   This program is distributed in the hope that it will be useful,         *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
15  *   Lesser General Public License for more details.                         *
16  *                                                                           *
17  *   You should have received a copy of the GNU Lesser General Public        *
18  *   License along with this library. If not,                                *
19  *   see <http://www.gnu.org/licenses/>.                                     *
20  *****************************************************************************/
21 
22 #include "config.h"
23 #include "argbhelper.h"
24 #include <QDesktopWidget>
25 #include <QApplication>
26 
27 #include <vector>
28 
29 // Copied from qt_x11_p.h.
30 // This is not part of the public API but should be stable enough to use
31 // because it had never changed since the first git commit of Qt.
32 struct QX11InfoData {
33     uint ref;
34     int screen;
35     int dpiX;
36     int dpiY;
37     int depth;
38     int cells;
39     unsigned long colormap;
40     void *visual;
41     bool defaultColormap;
42     bool defaultVisual;
43     int subpixel;
44 };
45 
46 namespace QtCurve {
47 bool QtcX11Info::creatingDummy = false;
48 
49 #ifdef Q_WS_X11
50 inline QtcX11Info*
getInfo(const QWidget * w)51 QtcX11Info::getInfo(const QWidget *w)
52 {
53     return static_cast<QtcX11Info*>(const_cast<QX11Info*>(&w->x11Info()));
54 }
55 
56 // Qt uses XCreateSimpleWindow when defaultVisual and defaultColormap
57 // are true. This confuses QGLWidget when recreating window caused by
58 // reparenting to a widget with different depth, result in a mismatch
59 // in x11info and native window.
60 inline void
fixVisual()61 QtcX11Info::fixVisual()
62 {
63     if (qtcUnlikely(!x11data))
64         setX11Data(getX11Data(true));
65     x11data->defaultVisual = false;
66     x11data->defaultColormap = false;
67 }
68 
69 inline void
setRgba()70 QtcX11Info::setRgba()
71 {
72 #if 1
73     setX11Data(getInfo(rgbaDummy())->x11data);
74 #else
75     // It seems that VirtualBox is doing something special to Qt so that
76     // a TranslucentBackground Widget will NOT have a related 32bit window.
77     // The following code enables translucent background in Virtualbox by
78     // setting rgba visual on the widget anyway. However, this breaks
79     // the display of the virtual machine. Since Gammaray does not work either
80     // on VirtualBox, it is hard to figure out what is wrong and which are
81     // the widgets need to be blacklist. Disable the code for now unless a
82     // workaround is found.
83     QX11InfoData *xd = getX11Data(true);
84     xd->visual = qtcX11RgbaVisual(&xd->colormap, &xd->cells, xd->screen);
85     xd->depth = 32;
86     xd->defaultVisual = false;
87     xd->defaultColormap = false;
88     setX11Data(xd);
89 #endif
90 }
91 
92 inline QWidget*
rgbaDummy()93 QtcX11Info::rgbaDummy()
94 {
95     QDesktopWidget *desktop = qApp->desktop();
96     static std::vector<QWidget*> dummies(desktop->screenCount(), nullptr);
97     int scrno = screen();
98     if (qtcUnlikely(!dummies[scrno])) {
99         creatingDummy = true;
100         dummies[scrno] = new QWidget(desktop->screen(scrno));
101         dummies[scrno]->setAttribute(Qt::WA_TranslucentBackground);
102         dummies[scrno]->setAttribute(Qt::WA_WState_Polished);
103         dummies[scrno]->winId();
104         creatingDummy = false;
105     }
106     return dummies[scrno];
107 }
108 
109 void
fixVisual(QWidget * widget)110 fixVisual(QWidget *widget)
111 {
112     // Don't use XCreateSimpleWindow
113     QtcX11Info::getInfo(widget)->fixVisual();
114 }
115 
116 void
addAlphaChannel(QWidget * widget)117 addAlphaChannel(QWidget *widget)
118 {
119     QtcX11Info::getInfo(widget)->setRgba();
120 }
121 #else
122 void
fixVisual(QWidget *)123 fixVisual(QWidget*)
124 {
125 }
126 
127 void
addAlphaChannel(QWidget *)128 addAlphaChannel(QWidget*)
129 {
130 }
131 #endif
132 
133 }
134