defuze.me
Client
|
00001 /**************************************************************************** 00002 ** 00003 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 00004 ** 00005 ** Use, modification and distribution is allowed without limitation, 00006 ** warranty, liability or support of any kind. 00007 ** 00008 ****************************************************************************/ 00009 00010 #include "qtwin.h" 00011 #include <QLibrary> 00012 #include <QApplication> 00013 #include <QWidget> 00014 #include <QList> 00015 #include <QPointer> 00016 00017 #ifdef Q_WS_WIN 00018 00019 #include <qt_windows.h> 00020 00021 // Blur behind data structures 00022 #define DWM_BB_ENABLE 0x00000001 // fEnable has been specified 00023 #define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified 00024 #define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified 00025 #define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message 00026 00027 typedef struct _DWM_BLURBEHIND 00028 { 00029 DWORD dwFlags; 00030 BOOL fEnable; 00031 HRGN hRgnBlur; 00032 BOOL fTransitionOnMaximized; 00033 } DWM_BLURBEHIND, *PDWM_BLURBEHIND; 00034 00035 typedef struct _MARGINS 00036 { 00037 int cxLeftWidth; 00038 int cxRightWidth; 00039 int cyTopHeight; 00040 int cyBottomHeight; 00041 } MARGINS, *PMARGINS; 00042 00043 typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled); 00044 typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset); 00045 typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind); 00046 typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); 00047 00048 static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; 00049 static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; 00050 static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; 00051 static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; 00052 00053 00054 /* 00055 * Internal helper class that notifies windows if the 00056 * DWM compositing state changes and updates the widget 00057 * flags correspondingly. 00058 */ 00059 class WindowNotifier : public QWidget 00060 { 00061 public: 00062 WindowNotifier() { winId(); } 00063 void addWidget(QWidget *widget) { widgets.append(widget); } 00064 void removeWidget(QWidget *widget) { widgets.removeAll(widget); } 00065 bool winEvent(MSG *message, long *result); 00066 00067 private: 00068 QWidgetList widgets; 00069 }; 00070 00071 static bool resolveLibs() 00072 { 00073 if (!pDwmIsCompositionEnabled) { 00074 QLibrary dwmLib(QString::fromAscii("dwmapi")); 00075 pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); 00076 pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); 00077 pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); 00078 pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); 00079 } 00080 return pDwmIsCompositionEnabled != 0; 00081 } 00082 00083 #endif 00084 00095 bool QtWin::isCompositionEnabled() 00096 { 00097 #ifdef Q_WS_WIN 00098 if (resolveLibs()) { 00099 HRESULT hr = S_OK; 00100 BOOL isEnabled = false; 00101 hr = pDwmIsCompositionEnabled(&isEnabled); 00102 if (SUCCEEDED(hr)) 00103 return isEnabled; 00104 } 00105 #endif 00106 return false; 00107 } 00108 00114 bool QtWin::enableBlurBehindWindow(QWidget *widget, bool __attribute__((unused)) enable) 00115 { 00116 Q_ASSERT(widget); 00117 bool result = false; 00118 #ifdef Q_WS_WIN 00119 if (resolveLibs()) { 00120 DWM_BLURBEHIND bb = {0}; 00121 HRESULT hr = S_OK; 00122 bb.fEnable = enable; 00123 bb.dwFlags = DWM_BB_ENABLE; 00124 bb.hRgnBlur = NULL; 00125 widget->setAttribute(Qt::WA_TranslucentBackground, enable); 00126 widget->setAttribute(Qt::WA_NoSystemBackground, enable); 00127 hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); 00128 if (SUCCEEDED(hr)) { 00129 result = true; 00130 windowNotifier()->addWidget(widget); 00131 } 00132 } 00133 #endif 00134 return result; 00135 } 00136 00149 bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) 00150 { 00151 00152 Q_ASSERT(widget); 00153 Q_UNUSED(left); 00154 Q_UNUSED(top); 00155 Q_UNUSED(right); 00156 Q_UNUSED(bottom); 00157 00158 bool result = false; 00159 #ifdef Q_WS_WIN 00160 if (resolveLibs()) { 00161 QLibrary dwmLib(QString::fromAscii("dwmapi")); 00162 HRESULT hr = S_OK; 00163 MARGINS m = {left, top, right, bottom}; 00164 hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); 00165 if (SUCCEEDED(hr)) { 00166 result = true; 00167 windowNotifier()->addWidget(widget); 00168 } 00169 widget->setAttribute(Qt::WA_TranslucentBackground, result); 00170 } 00171 #endif 00172 return result; 00173 } 00174 00180 QColor QtWin::colorizatinColor() 00181 { 00182 QColor resultColor = QApplication::palette().window().color(); 00183 00184 #ifdef Q_WS_WIN 00185 if (resolveLibs()) { 00186 DWORD color = 0; 00187 BOOL opaque = FALSE; 00188 QLibrary dwmLib(QString::fromAscii("dwmapi")); 00189 HRESULT hr = S_OK; 00190 hr = pDwmGetColorizationColor(&color, &opaque); 00191 if (SUCCEEDED(hr)) 00192 resultColor = QColor(color); 00193 } 00194 #endif 00195 return resultColor; 00196 } 00197 00198 #ifdef Q_WS_WIN 00199 WindowNotifier *QtWin::windowNotifier() 00200 { 00201 static WindowNotifier *windowNotifierInstance = 0; 00202 if (!windowNotifierInstance) 00203 windowNotifierInstance = new WindowNotifier; 00204 return windowNotifierInstance; 00205 } 00206 00207 00208 /* Notify all enabled windows that the DWM state changed */ 00209 bool WindowNotifier::winEvent(MSG *message, long *result) 00210 { 00211 if (message && message->message == WM_DWMCOMPOSITIONCHANGED) { 00212 bool compositionEnabled = QtWin::isCompositionEnabled(); 00213 foreach(QWidget * widget, widgets) { 00214 if (widget) { 00215 widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); 00216 } 00217 widget->update(); 00218 } 00219 } 00220 return QWidget::winEvent(message, result); 00221 } 00222 #endif