defuze.me  Client
qtwin.cpp
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