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

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