source: tspsg-svn/trunk/src/qtwin.cpp @ 170

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