Linux multi-monitor fullscreen support
[ryzomcore.git] / studio / src / plugins / core / qtwin.cpp
blob115203dedce47e8ebb2431d1619f9224e4ee54b4
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 ****************************************************************************/
10 #include "qtwin.h"
11 #include <QLibrary>
12 #include <QApplication>
13 #include <QWidget>
14 #include <QList>
15 #include <QPointer>
17 #ifdef Q_WS_WIN
19 #include <qt_windows.h>
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
27 typedef struct _DWM_BLURBEHIND
29 DWORD dwFlags;
30 BOOL fEnable;
31 HRGN hRgnBlur;
32 BOOL fTransitionOnMaximized;
33 } DWM_BLURBEHIND, *PDWM_BLURBEHIND;
35 typedef struct _MARGINS
37 int cxLeftWidth;
38 int cxRightWidth;
39 int cyTopHeight;
40 int cyBottomHeight;
41 } MARGINS, *PMARGINS;
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);
48 static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
49 static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
50 static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
51 static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
55 * Internal helper class that notifies windows if the
56 * DWM compositing state changes and updates the widget
57 * flags correspondingly.
59 class WindowNotifier : public QWidget
61 public:
62 WindowNotifier()
64 winId();
66 void addWidget(QWidget *widget)
68 widgets.append(widget);
70 void removeWidget(QWidget *widget)
72 widgets.removeAll(widget);
74 bool winEvent(MSG *message, long *result);
76 private:
77 QWidgetList widgets;
80 static bool resolveLibs()
82 if (!pDwmIsCompositionEnabled)
84 QLibrary dwmLib(QString::fromAscii("dwmapi"));
85 pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
86 pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
87 pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
88 pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
90 return pDwmIsCompositionEnabled != 0;
93 #endif
95 /*!
96 * Chekcs and returns true if Windows DWM composition
97 * is currently enabled on the system.
99 * To get live notification on the availability of
100 * this feature, you will currently have to
101 * reimplement winEvent() on your widget and listen
102 * for the WM_DWMCOMPOSITIONCHANGED event to occur.
105 bool QtWin::isCompositionEnabled()
107 #ifdef Q_WS_WIN
108 if (resolveLibs())
110 HRESULT hr = S_OK;
111 BOOL isEnabled = false;
112 hr = pDwmIsCompositionEnabled(&isEnabled);
113 if (SUCCEEDED(hr))
114 return isEnabled;
116 #endif
117 return false;
121 * Enables Blur behind on a Widget.
123 * \a enable tells if the blur should be enabled or not
125 bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable)
127 Q_ASSERT(widget);
128 bool result = false;
129 #ifdef Q_WS_WIN
130 if (resolveLibs())
132 DWM_BLURBEHIND bb = {0};
133 HRESULT hr = S_OK;
134 bb.fEnable = enable;
135 bb.dwFlags = DWM_BB_ENABLE;
136 bb.hRgnBlur = NULL;
137 widget->setAttribute(Qt::WA_TranslucentBackground, enable);
138 widget->setAttribute(Qt::WA_NoSystemBackground, enable);
139 hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb);
140 if (SUCCEEDED(hr))
142 result = true;
143 windowNotifier()->addWidget(widget);
146 #endif
147 return result;
151 * ExtendFrameIntoClientArea.
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.
157 * \note you should not call enableBlurBehindWindow before calling
158 * this functions
160 * \a enable tells if the blur should be enabled or not
162 bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
165 Q_ASSERT(widget);
166 Q_UNUSED(left);
167 Q_UNUSED(top);
168 Q_UNUSED(right);
169 Q_UNUSED(bottom);
171 bool result = false;
172 #ifdef Q_WS_WIN
173 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))
181 result = true;
182 windowNotifier()->addWidget(widget);
184 widget->setAttribute(Qt::WA_TranslucentBackground, result);
186 #endif
187 return result;
191 * Returns the current colorizationColor for the window.
193 * \a enable tells if the blur should be enabled or not
195 QColor QtWin::colorizatinColor()
197 QColor resultColor = QApplication::palette().window().color();
199 #ifdef Q_WS_WIN
200 if (resolveLibs())
202 DWORD color = 0;
203 BOOL opaque = FALSE;
204 QLibrary dwmLib(QString::fromAscii("dwmapi"));
205 HRESULT hr = S_OK;
206 hr = pDwmGetColorizationColor(&color, &opaque);
207 if (SUCCEEDED(hr))
208 resultColor = QColor(color);
210 #endif
211 return resultColor;
214 #ifdef Q_WS_WIN
215 WindowNotifier *QtWin::windowNotifier()
217 static WindowNotifier *windowNotifierInstance = 0;
218 if (!windowNotifierInstance)
219 windowNotifierInstance = new WindowNotifier;
220 return windowNotifierInstance;
224 /* Notify all enabled windows that the DWM state changed */
225 bool WindowNotifier::winEvent(MSG *message, long *result)
227 if (message && message->message == WM_DWMCOMPOSITIONCHANGED)
229 bool compositionEnabled = QtWin::isCompositionEnabled();
230 Q_FOREACH(QWidget * widget, widgets)
232 if (widget)
234 widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
236 widget->update();
239 return QWidget::winEvent(message, result);
241 #endif