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