source: tspsg/src/qtwin.cpp

appveyor
Last change on this file was a7998257bc, checked in by paulcdejean <paulcdejean@…>, 9 years ago

Changes I had to make to get this to build on windows.

  • Property mode set to 100644
File size: 7.7 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::fromLatin1("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;
144        HRESULT hr = S_OK;
145        bb.dwFlags = 0;
146        bb.fEnable = enable;
147        bb.dwFlags = DWM_BB_ENABLE;
148        bb.hRgnBlur = NULL;
149#endif
150        widget->setAttribute(Qt::WA_TranslucentBackground, enable);
151#ifdef Q_WS_X11
152        widget->setAttribute(Qt::WA_NoSystemBackground, false);
153        QPalette p = widget->palette();
154        QColor c = p.color(QPalette::Window);
155        if (enable)
156            c.setAlpha(160);
157        else
158            c.setAlpha(255);
159        p.setColor(QPalette::Window, c);
160        widget->setPalette(p);
161        result = true;
162#endif
163#ifdef Q_OS_WIN32
164        hr = pDwmEnableBlurBehindWindow(HWND(widget->winId()), &bb);
165        if (SUCCEEDED(hr)) {
166            result = true;
167            windowNotifier()->addWidget(widget);
168        }
169    }
170#endif
171    return result;
172}
173
174/*!
175  * ExtendFrameIntoClientArea.
176  *
177  * This controls the rendering of the frame inside the window.
178  * Note that passing margins of -1 (the default value) will completely
179  * remove the frame from the window.
180  *
181  * \note you should not call enableBlurBehindWindow before calling
182  *       this functions
183  *
184  * \a enable tells if the blur should be enabled or not
185  */
186bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
187{
188
189    Q_ASSERT(widget);
190    Q_UNUSED(widget);
191    Q_UNUSED(left);
192    Q_UNUSED(top);
193    Q_UNUSED(right);
194    Q_UNUSED(bottom);
195
196    bool result = false;
197#ifdef Q_OS_WIN32
198    if (resolveLibs()) {
199        QLibrary dwmLib(QString::fromLatin1("dwmapi"));
200        HRESULT hr = S_OK;
201        MARGINS m = {left, top, right, bottom};
202        hr = pDwmExtendFrameIntoClientArea(HWND(widget->winId()), &m);
203        if (SUCCEEDED(hr)) {
204            result = true;
205            windowNotifier()->addWidget(widget);
206        }
207        widget->setAttribute(Qt::WA_TranslucentBackground, result);
208    }
209#endif
210    return result;
211}
212
213/*!
214  * Returns the current colorizationColor for the window.
215  *
216  * \a enable tells if the blur should be enabled or not
217  */
218QColor QtWin::colorizatinColor()
219{
220    QColor resultColor = QApplication::palette().window().color();
221
222#ifdef Q_OS_WIN32
223    if (resolveLibs()) {
224        DWORD color = 0;
225        BOOL opaque = FALSE;
226        QLibrary dwmLib(QString::fromLatin1("dwmapi"));
227        HRESULT hr = S_OK;
228        hr = pDwmGetColorizationColor(&color, &opaque);
229        if (SUCCEEDED(hr))
230            resultColor = QColor(color);
231    }
232#endif
233    return resultColor;
234}
235
236#ifdef Q_OS_WIN32
237WindowNotifier *QtWin::windowNotifier()
238{
239    static WindowNotifier *windowNotifierInstance = 0;
240    if (!windowNotifierInstance)
241        windowNotifierInstance = new WindowNotifier;
242    return windowNotifierInstance;
243}
244
245
246/* Notify all enabled windows that the DWM state changed */
247bool WindowNotifier::winEvent(MSG *message, long *result)
248{
249    if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
250        bool compositionEnabled = QtWin::isCompositionEnabled();
251        foreach(QWidget * widget, widgets) {
252            if (widget) {
253                widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
254            }
255            widget->update();
256        }
257    }
258#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
259    return QWidget::winEvent(message, result);
260#else
261    return QWidget::nativeEvent("windows_generic_MSG", message, result);
262#endif
263}
264#endif
Note: See TracBrowser for help on using the repository browser.