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
RevLine 
[2bbe924ad8]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
[197f54a2b9]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
[142cff4d3d]25#ifdef Q_WS_X11
[197f54a2b9]26#include <X11/Xlib.h>
[142cff4d3d]27#endif // Q_WS_X11
28
[89e5214692]29#ifdef Q_OS_WIN32
[2bbe924ad8]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{
[89e5214692]109#ifdef Q_OS_WIN32
[2bbe924ad8]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;
[142cff4d3d]118#elif defined(Q_WS_X11)
[197f54a2b9]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;
[b8a2a118c4]126#else
[142cff4d3d]127    //! \todo TODO: Check for trsnsparency support in other OSes.
[b8a2a118c4]128    return false;
129#endif
[2bbe924ad8]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;
[89e5214692]141#ifdef Q_OS_WIN32
[2bbe924ad8]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;
[b8a2a118c4]148#endif
[2bbe924ad8]149        widget->setAttribute(Qt::WA_TranslucentBackground, enable);
150        widget->setAttribute(Qt::WA_NoSystemBackground, enable);
[89e5214692]151#ifdef Q_OS_WIN32
152        hr = pDwmEnableBlurBehindWindow(HWND(widget->winId()), &bb);
[2bbe924ad8]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;
[89e5214692]185#ifdef Q_OS_WIN32
[2bbe924ad8]186    if (resolveLibs()) {
187        QLibrary dwmLib(QString::fromAscii("dwmapi"));
188        HRESULT hr = S_OK;
189        MARGINS m = {left, top, right, bottom};
[89e5214692]190        hr = pDwmExtendFrameIntoClientArea(HWND(widget->winId()), &m);
[2bbe924ad8]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
[89e5214692]210#ifdef Q_OS_WIN32
[2bbe924ad8]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
[89e5214692]224#ifdef Q_OS_WIN32
[2bbe924ad8]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.