bb029bba245b643f621ca9ce330724a9062a28f0
[novacoin.git] / src / qt / qtwin.cpp
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
27 typedef struct _DWM_BLURBEHIND
28 {
29     DWORD dwFlags;
30     BOOL fEnable;
31     HRGN hRgnBlur;
32     BOOL fTransitionOnMaximized;
33 } DWM_BLURBEHIND, *PDWM_BLURBEHIND;
34
35 typedef struct _MARGINS
36 {
37     int cxLeftWidth;
38     int cxRightWidth;
39     int cyTopHeight;
40     int cyBottomHeight;
41 } MARGINS, *PMARGINS;
42
43 typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
44 typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
45 typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
46 typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
47
48 static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
49 static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
50 static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
51 static 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  */
59 class WindowNotifier : public QWidget
60 {
61 public:
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
67 private:
68     QWidgetList widgets;
69 };
70
71 static 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   */
95 bool 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 #endif
106     return false;
107 }
108
109 /*!
110   * Enables Blur behind on a Widget.
111   *
112   * \a enable tells if the blur should be enabled or not
113   */
114 bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable)
115 {
116     Q_ASSERT(widget);
117     bool result = false;
118 #ifdef Q_WS_WIN
119     if (resolveLibs()) {
120         DWM_BLURBEHIND bb = {0};
121         HRESULT hr = S_OK;
122         bb.fEnable = enable;
123         bb.dwFlags = DWM_BB_ENABLE;
124         bb.hRgnBlur = NULL;
125         widget->setAttribute(Qt::WA_TranslucentBackground, enable);
126         widget->setAttribute(Qt::WA_NoSystemBackground, enable);
127         hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb);
128         if (SUCCEEDED(hr)) {
129             result = true;
130             windowNotifier()->addWidget(widget);
131         }
132     }
133 #endif
134     return result;
135 }
136
137 /*!
138   * ExtendFrameIntoClientArea.
139   *
140   * This controls the rendering of the frame inside the window.
141   * Note that passing margins of -1 (the default value) will completely
142   * remove the frame from the window.
143   *
144   * \note you should not call enableBlurBehindWindow before calling
145   *       this functions
146   *
147   * \a enable tells if the blur should be enabled or not
148   */
149 bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
150 {
151
152     Q_ASSERT(widget);
153     Q_UNUSED(left);
154     Q_UNUSED(top);
155     Q_UNUSED(right);
156     Q_UNUSED(bottom);
157
158     bool result = false;
159 #ifdef Q_WS_WIN
160     if (resolveLibs()) {
161         QLibrary dwmLib(QString::fromAscii("dwmapi"));
162         HRESULT hr = S_OK;
163         MARGINS m = {left, top, right, bottom};
164         hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
165         if (SUCCEEDED(hr)) {
166             result = true;
167             windowNotifier()->addWidget(widget);
168         }
169         widget->setAttribute(Qt::WA_TranslucentBackground, result);
170     }
171 #endif
172     return result;
173 }
174
175 /*!
176   * Returns the current colorizationColor for the window.
177   *
178   * \a enable tells if the blur should be enabled or not
179   */
180 QColor QtWin::colorizatinColor()
181 {
182     QColor resultColor = QApplication::palette().window().color();
183
184 #ifdef Q_WS_WIN
185     if (resolveLibs()) {
186         DWORD color = 0;
187         BOOL opaque = FALSE;
188         QLibrary dwmLib(QString::fromAscii("dwmapi"));
189         HRESULT hr = S_OK;
190         hr = pDwmGetColorizationColor(&color, &opaque);
191         if (SUCCEEDED(hr))
192             resultColor = QColor(color);
193     }
194 #endif
195     return resultColor;
196 }
197
198 #ifdef Q_WS_WIN
199 WindowNotifier *QtWin::windowNotifier()
200 {
201     static WindowNotifier *windowNotifierInstance = 0;
202     if (!windowNotifierInstance)
203         windowNotifierInstance = new WindowNotifier;
204     return windowNotifierInstance;
205 }
206
207
208 /* Notify all enabled windows that the DWM state changed */
209 bool WindowNotifier::winEvent(MSG *message, long *result)
210 {
211     if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
212         bool compositionEnabled = QtWin::isCompositionEnabled();
213         foreach(QWidget * widget, widgets) {
214             if (widget) {
215                 widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
216             }
217             widget->update();
218         }
219     }
220     return QWidget::winEvent(message, result);
221 }
222 #endif