source: tspsg/src/qtwin.cpp @ 197f54a2b9

appveyorimgbotreadme
Last change on this file since 197f54a2b9 was 197f54a2b9, checked in by Oleksii Serdiuk, 12 years ago

No QX11Info class in Qt 5.

Replaced all usage of QX11Info with direct access to X11 API. More
reliable detection of X11 in Qt 5 might be needed.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4**
5** Use, modification and distribution is allowed without limitation,
6** warranty, liability or support of any kind.
7**
8****************************************************************************/
9
10#include "qtwin.h"
11#include <QLibrary>
12#include <QApplication>
13#include <QWidget>
14#include <QList>
15#include <QPointer>
16
17//! \todo TODO: Detect X11 in Qt 5 more reliably
18// No Q_WS_X11 in Qt 5. Check if we're using X11 and define it.
19#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0)) && defined(Q_OS_UNIX) && !defined(Q_WS_X11)
20#   if !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(Q_WS_QPA)
21#       define Q_WS_X11
22#   endif
23#endif
24
25#ifdef Q_WS_X11
26#include <X11/Xlib.h>
27#endif // Q_WS_X11
28
29#ifdef Q_OS_WIN32
30
31#include <qt_windows.h>
32
33// Blur behind data structures
34#define DWM_BB_ENABLE                 0x00000001  // fEnable has been specified
35#define DWM_BB_BLURREGION             0x00000002  // hRgnBlur has been specified
36#define DWM_BB_TRANSITIONONMAXIMIZED  0x00000004  // fTransitionOnMaximized has been specified
37#define WM_DWMCOMPOSITIONCHANGED        0x031E    // Composition changed window message
38
39typedef struct _DWM_BLURBEHIND
40{
41    DWORD dwFlags;
42    BOOL fEnable;
43    HRGN hRgnBlur;
44    BOOL fTransitionOnMaximized;
45} DWM_BLURBEHIND, *PDWM_BLURBEHIND;
46
47typedef struct _MARGINS
48{
49    int cxLeftWidth;
50    int cxRightWidth;
51    int cyTopHeight;
52    int cyBottomHeight;
53} MARGINS, *PMARGINS;
54
55typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
56typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
57typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
58typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
59
60static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
61static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
62static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
63static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
64
65
66/*
67 * Internal helper class that notifies windows if the
68 * DWM compositing state changes and updates the widget
69 * flags correspondingly.
70 */
71class WindowNotifier : public QWidget
72{
73public:
74    WindowNotifier() { winId(); }
75    void addWidget(QWidget *widget) { widgets.append(widget); }
76    void removeWidget(QWidget *widget) { widgets.removeAll(widget); }
77    bool winEvent(MSG *message, long *result);
78
79private:
80    QWidgetList widgets;
81};
82
83static bool resolveLibs()
84{
85    if (!pDwmIsCompositionEnabled) {
86        QLibrary dwmLib(QString::fromAscii("dwmapi"));
87        pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
88        pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
89        pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
90        pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
91    }
92    return pDwmIsCompositionEnabled != 0;
93}
94
95#endif
96
97/*!
98  * Chekcs and returns true if Windows DWM composition
99  * is currently enabled on the system.
100  *
101  * To get live notification on the availability of
102  * this feature, you will currently have to
103  * reimplement winEvent() on your widget and listen
104  * for the WM_DWMCOMPOSITIONCHANGED event to occur.
105  *
106  */
107bool QtWin::isCompositionEnabled()
108{
109#ifdef Q_OS_WIN32
110    if (resolveLibs()) {
111        HRESULT hr = S_OK;
112        BOOL isEnabled = false;
113        hr = pDwmIsCompositionEnabled(&isEnabled);
114        if (SUCCEEDED(hr))
115            return isEnabled;
116    }
117    return false;
118#elif defined(Q_WS_X11)
119    Display *d = XOpenDisplay(NULL);
120    Atom _NET_WM_CM_S0 = XInternAtom(d, "_NET_WM_CM_S0", true);
121    bool result = (_NET_WM_CM_S0 != None);
122    if (result)
123        result = (XGetSelectionOwner(d, _NET_WM_CM_S0) != None);
124    XCloseDisplay(d);
125    return result;
126#else
127    //! \todo TODO: Check for trsnsparency support in other OSes.
128    return false;
129#endif
130}
131
132/*!
133  * Enables Blur behind on a Widget.
134  *
135  * \a enable tells if the blur should be enabled or not
136  */
137bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable)
138{
139    Q_ASSERT(widget);
140    bool result = false;
141#ifdef Q_OS_WIN32
142    if (resolveLibs()) {
143        DWM_BLURBEHIND bb = {0};
144        HRESULT hr = S_OK;
145        bb.fEnable = enable;
146        bb.dwFlags = DWM_BB_ENABLE;
147        bb.hRgnBlur = NULL;
148#endif
149        widget->setAttribute(Qt::WA_TranslucentBackground, enable);
150        widget->setAttribute(Qt::WA_NoSystemBackground, enable);
151#ifdef Q_OS_WIN32
152        hr = pDwmEnableBlurBehindWindow(HWND(widget->winId()), &bb);
153        if (SUCCEEDED(hr)) {
154            result = true;
155            windowNotifier()->addWidget(widget);
156        }
157    }
158#endif
159    return result;
160}
161
162/*!
163  * ExtendFrameIntoClientArea.
164  *
165  * This controls the rendering of the frame inside the window.
166  * Note that passing margins of -1 (the default value) will completely
167  * remove the frame from the window.
168  *
169  * \note you should not call enableBlurBehindWindow before calling
170  *       this functions
171  *
172  * \a enable tells if the blur should be enabled or not
173  */
174bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
175{
176
177    Q_ASSERT(widget);
178    Q_UNUSED(widget);
179    Q_UNUSED(left);
180    Q_UNUSED(top);
181    Q_UNUSED(right);
182    Q_UNUSED(bottom);
183
184    bool result = false;
185#ifdef Q_OS_WIN32
186    if (resolveLibs()) {
187        QLibrary dwmLib(QString::fromAscii("dwmapi"));
188        HRESULT hr = S_OK;
189        MARGINS m = {left, top, right, bottom};
190        hr = pDwmExtendFrameIntoClientArea(HWND(widget->winId()), &m);
191        if (SUCCEEDED(hr)) {
192            result = true;
193            windowNotifier()->addWidget(widget);
194        }
195        widget->setAttribute(Qt::WA_TranslucentBackground, result);
196    }
197#endif
198    return result;
199}
200
201/*!
202  * Returns the current colorizationColor for the window.
203  *
204  * \a enable tells if the blur should be enabled or not
205  */
206QColor QtWin::colorizatinColor()
207{
208    QColor resultColor = QApplication::palette().window().color();
209
210#ifdef Q_OS_WIN32
211    if (resolveLibs()) {
212        DWORD color = 0;
213        BOOL opaque = FALSE;
214        QLibrary dwmLib(QString::fromAscii("dwmapi"));
215        HRESULT hr = S_OK;
216        hr = pDwmGetColorizationColor(&color, &opaque);
217        if (SUCCEEDED(hr))
218            resultColor = QColor(color);
219    }
220#endif
221    return resultColor;
222}
223
224#ifdef Q_OS_WIN32
225WindowNotifier *QtWin::windowNotifier()
226{
227    static WindowNotifier *windowNotifierInstance = 0;
228    if (!windowNotifierInstance)
229        windowNotifierInstance = new WindowNotifier;
230    return windowNotifierInstance;
231}
232
233
234/* Notify all enabled windows that the DWM state changed */
235bool WindowNotifier::winEvent(MSG *message, long *result)
236{
237    if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
238        bool compositionEnabled = QtWin::isCompositionEnabled();
239        foreach(QWidget * widget, widgets) {
240            if (widget) {
241                widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
242            }
243            widget->update();
244        }
245    }
246    return QWidget::winEvent(message, result);
247}
248#endif
Note: See TracBrowser for help on using the repository browser.