Blur behind the pretty OSD on Windows Vista and above
This commit is contained in:
parent
e9525e8ec3
commit
f151df00b0
|
@ -0,0 +1,9 @@
|
||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
|
||||||
|
set(QTWIN-SOURCES
|
||||||
|
qtwin.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
ADD_LIBRARY(qtwin STATIC
|
||||||
|
${QTWIN-SOURCES}
|
||||||
|
)
|
|
@ -0,0 +1,229 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Use, modification and distribution is allowed without limitation,
|
||||||
|
** warranty, liability or support of any kind.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qtwin.h"
|
||||||
|
#include <QLibrary>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QList>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
// Blur behind data structures
|
||||||
|
#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
|
||||||
|
#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified
|
||||||
|
#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified
|
||||||
|
#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message
|
||||||
|
|
||||||
|
typedef struct _DWM_BLURBEHIND
|
||||||
|
{
|
||||||
|
DWORD dwFlags;
|
||||||
|
BOOL fEnable;
|
||||||
|
HRGN hRgnBlur;
|
||||||
|
BOOL fTransitionOnMaximized;
|
||||||
|
} DWM_BLURBEHIND, *PDWM_BLURBEHIND;
|
||||||
|
|
||||||
|
typedef struct _MARGINS
|
||||||
|
{
|
||||||
|
int cxLeftWidth;
|
||||||
|
int cxRightWidth;
|
||||||
|
int cyTopHeight;
|
||||||
|
int cyBottomHeight;
|
||||||
|
} MARGINS, *PMARGINS;
|
||||||
|
|
||||||
|
typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
|
||||||
|
typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
|
||||||
|
typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
|
||||||
|
typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
|
||||||
|
|
||||||
|
static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
|
||||||
|
static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
|
||||||
|
static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
|
||||||
|
static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal helper class that notifies windows if the
|
||||||
|
* DWM compositing state changes and updates the widget
|
||||||
|
* flags correspondingly.
|
||||||
|
*/
|
||||||
|
class WindowNotifier : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WindowNotifier() { winId(); }
|
||||||
|
void addWidget(QWidget *widget) { widgets.append(widget); }
|
||||||
|
void removeWidget(QWidget *widget) { widgets.removeAll(widget); }
|
||||||
|
bool winEvent(MSG *message, long *result);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidgetList widgets;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool resolveLibs()
|
||||||
|
{
|
||||||
|
if (!pDwmIsCompositionEnabled) {
|
||||||
|
QLibrary dwmLib(QString::fromAscii("dwmapi"));
|
||||||
|
pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
|
||||||
|
pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
|
||||||
|
pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
|
||||||
|
pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
|
||||||
|
}
|
||||||
|
return pDwmIsCompositionEnabled != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Chekcs and returns true if Windows DWM composition
|
||||||
|
* is currently enabled on the system.
|
||||||
|
*
|
||||||
|
* To get live notification on the availability of
|
||||||
|
* this feature, you will currently have to
|
||||||
|
* reimplement winEvent() on your widget and listen
|
||||||
|
* for the WM_DWMCOMPOSITIONCHANGED event to occur.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool QtWin::isCompositionEnabled()
|
||||||
|
{
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if (resolveLibs()) {
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
BOOL isEnabled = false;
|
||||||
|
hr = pDwmIsCompositionEnabled(&isEnabled);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
return isEnabled;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enables Blur behind on a Widget.
|
||||||
|
*
|
||||||
|
* \a enable tells if the blur should be enabled or not
|
||||||
|
*/
|
||||||
|
bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable,
|
||||||
|
const QRegion ®ion)
|
||||||
|
{
|
||||||
|
Q_ASSERT(widget);
|
||||||
|
bool result = false;
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if (resolveLibs()) {
|
||||||
|
DWM_BLURBEHIND bb = {0};
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
bb.fEnable = enable;
|
||||||
|
bb.dwFlags = DWM_BB_ENABLE;
|
||||||
|
bb.hRgnBlur = NULL;
|
||||||
|
|
||||||
|
if (!region.isEmpty()) {
|
||||||
|
bb.dwFlags |= DWM_BB_BLURREGION;
|
||||||
|
bb.hRgnBlur = region.handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
widget->setAttribute(Qt::WA_TranslucentBackground, enable);
|
||||||
|
widget->setAttribute(Qt::WA_NoSystemBackground, enable);
|
||||||
|
hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
result = true;
|
||||||
|
windowNotifier()->addWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ExtendFrameIntoClientArea.
|
||||||
|
*
|
||||||
|
* This controls the rendering of the frame inside the window.
|
||||||
|
* Note that passing margins of -1 (the default value) will completely
|
||||||
|
* remove the frame from the window.
|
||||||
|
*
|
||||||
|
* \note you should not call enableBlurBehindWindow before calling
|
||||||
|
* this functions
|
||||||
|
*
|
||||||
|
* \a enable tells if the blur should be enabled or not
|
||||||
|
*/
|
||||||
|
bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
|
||||||
|
{
|
||||||
|
|
||||||
|
Q_ASSERT(widget);
|
||||||
|
Q_UNUSED(left);
|
||||||
|
Q_UNUSED(top);
|
||||||
|
Q_UNUSED(right);
|
||||||
|
Q_UNUSED(bottom);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if (resolveLibs()) {
|
||||||
|
QLibrary dwmLib(QString::fromAscii("dwmapi"));
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
MARGINS m = {left, top, right, bottom};
|
||||||
|
hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
result = true;
|
||||||
|
windowNotifier()->addWidget(widget);
|
||||||
|
}
|
||||||
|
widget->setAttribute(Qt::WA_TranslucentBackground, result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the current colorizationColor for the window.
|
||||||
|
*
|
||||||
|
* \a enable tells if the blur should be enabled or not
|
||||||
|
*/
|
||||||
|
QColor QtWin::colorizatinColor()
|
||||||
|
{
|
||||||
|
QColor resultColor = QApplication::palette().window().color();
|
||||||
|
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
if (resolveLibs()) {
|
||||||
|
DWORD color = 0;
|
||||||
|
BOOL opaque = FALSE;
|
||||||
|
QLibrary dwmLib(QString::fromAscii("dwmapi"));
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
hr = pDwmGetColorizationColor(&color, &opaque);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
resultColor = QColor(color);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return resultColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_WS_WIN
|
||||||
|
WindowNotifier *QtWin::windowNotifier()
|
||||||
|
{
|
||||||
|
static WindowNotifier *windowNotifierInstance = 0;
|
||||||
|
if (!windowNotifierInstance)
|
||||||
|
windowNotifierInstance = new WindowNotifier;
|
||||||
|
return windowNotifierInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Notify all enabled windows that the DWM state changed */
|
||||||
|
bool WindowNotifier::winEvent(MSG *message, long *result)
|
||||||
|
{
|
||||||
|
if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
|
||||||
|
bool compositionEnabled = QtWin::isCompositionEnabled();
|
||||||
|
foreach(QWidget * widget, widgets) {
|
||||||
|
if (widget) {
|
||||||
|
widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
|
||||||
|
}
|
||||||
|
widget->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QWidget::winEvent(message, result);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Use, modification and distribution is allowed without limitation,
|
||||||
|
** warranty, liability or support of any kind.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTWIN_H
|
||||||
|
#define QTWIN_H
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QWidget>
|
||||||
|
/**
|
||||||
|
* This is a helper class for using the Desktop Window Manager
|
||||||
|
* functionality on Windows 7 and Windows Vista. On other platforms
|
||||||
|
* these functions will simply not do anything.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class WindowNotifier;
|
||||||
|
|
||||||
|
class QtWin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool enableBlurBehindWindow(QWidget *widget, bool enable = true,
|
||||||
|
const QRegion& region = QRegion());
|
||||||
|
static bool extendFrameIntoClientArea(QWidget *widget,
|
||||||
|
int left = -1, int top = -1,
|
||||||
|
int right = -1, int bottom = -1);
|
||||||
|
static bool isCompositionEnabled();
|
||||||
|
static QColor colorizatinColor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static WindowNotifier *windowNotifier();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QTWIN_H
|
|
@ -156,6 +156,7 @@ add_subdirectory(src)
|
||||||
if (NOT APPLE)
|
if (NOT APPLE)
|
||||||
add_subdirectory(3rdparty/qxt)
|
add_subdirectory(3rdparty/qxt)
|
||||||
endif (NOT APPLE)
|
endif (NOT APPLE)
|
||||||
|
add_subdirectory(3rdparty/qtwin)
|
||||||
add_subdirectory(3rdparty/universalchardet)
|
add_subdirectory(3rdparty/universalchardet)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
add_subdirectory(dist)
|
add_subdirectory(dist)
|
||||||
|
|
|
@ -8,6 +8,7 @@ include_directories(${SPARKLE})
|
||||||
include_directories(../3rdparty/gmock/gtest/include)
|
include_directories(../3rdparty/gmock/gtest/include)
|
||||||
include_directories(../3rdparty/qtsingleapplication)
|
include_directories(../3rdparty/qtsingleapplication)
|
||||||
include_directories(../3rdparty/qtiocompressor)
|
include_directories(../3rdparty/qtiocompressor)
|
||||||
|
include_directories(../3rdparty/qtwin)
|
||||||
include_directories(../3rdparty/qxt)
|
include_directories(../3rdparty/qxt)
|
||||||
include_directories(../3rdparty/libprojectm)
|
include_directories(../3rdparty/libprojectm)
|
||||||
|
|
||||||
|
@ -516,6 +517,7 @@ add_dependencies(clementine_lib pot)
|
||||||
target_link_libraries(clementine_lib
|
target_link_libraries(clementine_lib
|
||||||
qtsingleapplication
|
qtsingleapplication
|
||||||
qtiocompressor
|
qtiocompressor
|
||||||
|
qtwin
|
||||||
chardet
|
chardet
|
||||||
${GOBJECT_LIBRARIES}
|
${GOBJECT_LIBRARIES}
|
||||||
${GLIB_LIBRARIES}
|
${GLIB_LIBRARIES}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "osdpretty.h"
|
#include "osdpretty.h"
|
||||||
#include "ui_osdpretty.h"
|
#include "ui_osdpretty.h"
|
||||||
|
|
||||||
|
#include "qtwin.h"
|
||||||
|
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
|
@ -278,11 +280,7 @@ void OSDPretty::Reposition() {
|
||||||
move(qBound(0, x, geometry.right() - width()),
|
move(qBound(0, x, geometry.right() - width()),
|
||||||
qBound(0, y, geometry.bottom() - height()));
|
qBound(0, y, geometry.bottom() - height()));
|
||||||
|
|
||||||
// If there's no compositing window manager running then we have to set an
|
// Create a mask for the actual area of the OSD
|
||||||
// XShape mask.
|
|
||||||
if (IsTransparencyAvailable())
|
|
||||||
clearMask();
|
|
||||||
else {
|
|
||||||
QBitmap mask(size());
|
QBitmap mask(size());
|
||||||
mask.clear();
|
mask.clear();
|
||||||
|
|
||||||
|
@ -291,8 +289,16 @@ void OSDPretty::Reposition() {
|
||||||
p.drawRoundedRect(BoxBorder().adjusted(-1, -1, 0, 0), kBorderRadius, kBorderRadius);
|
p.drawRoundedRect(BoxBorder().adjusted(-1, -1, 0, 0), kBorderRadius, kBorderRadius);
|
||||||
p.end();
|
p.end();
|
||||||
|
|
||||||
|
// If there's no compositing window manager running then we have to set an
|
||||||
|
// XShape mask.
|
||||||
|
if (IsTransparencyAvailable())
|
||||||
|
clearMask();
|
||||||
|
else {
|
||||||
setMask(mask);
|
setMask(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On windows, enable blurbehind on the masked area
|
||||||
|
QtWin::enableBlurBehindWindow(this, true, QRegion(mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSDPretty::enterEvent(QEvent *) {
|
void OSDPretty::enterEvent(QEvent *) {
|
||||||
|
|
Loading…
Reference in New Issue