1
mirror of https://invent.kde.org/network/falkon.git synced 2024-09-23 02:32:10 +02:00
falkonOfficial/src/3rdparty/qtwin.cpp

380 lines
13 KiB
C++
Raw Normal View History

/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2011 David Rosca
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
2011-03-02 16:57:41 +01:00
/****************************************************************************
**
** 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>
#include "historymodel.h"
#include "mainapplication.h"
2011-03-02 16:57:41 +01:00
#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;
2011-03-02 16:57:41 +01:00
/*
* 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;
}
2011-03-02 16:57:41 +01:00
#endif
/*!
* Chekcs and returns true if Windows version
* currently running is Windows 7
*
* This function is useful when you are using
* Windows7 new TaskBar API
*
*/
bool QtWin::isRunningWindows7()
{
2011-03-17 17:03:04 +01:00
#ifdef Q_WS_WIN
2011-05-01 22:07:57 +02:00
return QSysInfo::windowsVersion() == QSysInfo::WV_WINDOWS7;
2011-03-17 17:03:04 +01:00
#endif
return false;
}
/*!
* Checks and returns true if Windows DWM composition
2011-03-02 16:57:41 +01:00
* 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;
}
2011-03-02 16:57:41 +01:00
#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)
{
Q_UNUSED(enable);
Q_UNUSED(widget);
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;
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);
}
2011-03-02 16:57:41 +01:00
}
#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)
{
2011-03-02 16:57:41 +01:00
Q_ASSERT(widget);
Q_UNUSED(left);
Q_UNUSED(top);
Q_UNUSED(right);
Q_UNUSED(bottom);
Q_UNUSED(widget);
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);
2011-03-02 16:57:41 +01:00
}
#endif
return result;
}
/*!
* Returns the current colorizationColor for the window.
*
* \a enable tells if the blur should be enabled or not
*/
QColor QtWin::colorizationColor()
2011-03-02 16:57:41 +01:00
{
QColor resultColor = QApplication::palette().window().color();
2011-03-02 16:57:41 +01:00
#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);
}
2011-03-02 16:57:41 +01:00
#endif
return resultColor;
}
#ifdef Q_WS_WIN
2011-03-02 16:57:41 +01:00
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();
2011-03-02 16:57:41 +01:00
}
}
}
return QWidget::winEvent(message, result);
}
2011-05-01 22:07:57 +02:00
#ifdef W7API
2011-05-01 22:07:57 +02:00
IShellLink* QtWin::CreateShellLink(const QString &title, const QString &description,
const QString &app_path, const QString &app_args,
const QString &icon_path, int app_index) {
const wchar_t* _title = reinterpret_cast<const wchar_t*>(title.utf16());
const wchar_t* _description = reinterpret_cast<const wchar_t*>(description.utf16());
const wchar_t* _app_path = reinterpret_cast<const wchar_t*>(app_path.utf16());
const wchar_t* _icon_path = reinterpret_cast<const wchar_t*>(icon_path.utf16());
const wchar_t* _app_args = reinterpret_cast<const wchar_t*>(app_args.utf16());
IShellLink* shell_link = NULL;
IPropertyStore* prop_store = NULL;
bool is_not_separator = (app_path.length() > 0);
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
reinterpret_cast<void**> (&(shell_link)));
if(SUCCEEDED(hr)) {
if (is_not_separator) {
shell_link->SetPath(_app_path);
shell_link->SetArguments(_app_args);
shell_link->SetIconLocation(_icon_path, app_index);
shell_link->SetDescription(_description);
}
hr = shell_link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void**> (&(prop_store)));
if (SUCCEEDED(hr)) {
PROPVARIANT pv;
if (is_not_separator) {
hr = InitPropVariantFromString(_title, &pv);
if (SUCCEEDED(hr)) {
hr = prop_store->SetValue(PKEY_Title, pv);
}
} else {
hr = InitPropVariantFromBoolean(TRUE, &pv);
if (SUCCEEDED(hr)) {
hr = prop_store->SetValue(PKEY_AppUserModel_IsDestListSeparator, pv);
}
}
//Save the changes we made to the property store
prop_store->Commit();
prop_store->Release();
PropVariantClear(&pv);
}
}
return shell_link;
}
void QtWin::populateFrequentSites(IObjectCollection* collection, const QString &appPath)
{
HistoryModel* historyModel = mApp->history();
QList<HistoryModel::HistoryEntry> mostList = historyModel->mostVisited(6);
foreach (HistoryModel::HistoryEntry entry, mostList)
collection->AddObject(CreateShellLink(entry.title, entry.url.toString(), appPath, " "+entry.url.toEncoded(), appPath, 1));
collection->AddObject(CreateShellLink("", "", "", "", "", 0)); //Spacer
}
2011-05-01 22:07:57 +02:00
void QtWin::AddTasksToList(ICustomDestinationList* destinationList) {
IObjectArray* object_array;
IObjectCollection* obj_collection;
CoCreateInstance(CLSID_EnumerableObjectCollection, NULL,
CLSCTX_INPROC, IID_IObjectCollection, reinterpret_cast<void**> (&(obj_collection)));
obj_collection->QueryInterface(IID_IObjectArray, reinterpret_cast<void**> (&(object_array)));
QString icons_source = qApp->applicationFilePath();
QString app_path = qApp->applicationFilePath();
populateFrequentSites(obj_collection, icons_source);
2011-05-01 22:07:57 +02:00
obj_collection->AddObject(CreateShellLink(tr("Open new tab"), tr("Opens a new tab if browser is running"),
app_path, "--new-tab",
icons_source, 0));
obj_collection->AddObject(CreateShellLink(tr("Open new window"), tr("Opens a new window if browser is running"),
app_path, "--new-window",
icons_source, 0));
obj_collection->AddObject(CreateShellLink(tr("Open download manager"), tr("Opens a download manager if browser is running"),
app_path, "--download-manager",
icons_source, 0));
destinationList->AddUserTasks(object_array);
object_array->Release();
obj_collection->Release();
}
#endif //W7API
#endif //Q_WS_WIN
2011-05-01 22:07:57 +02:00
void QtWin::setupJumpList() {
#ifdef W7API
2011-05-01 22:07:57 +02:00
if (!isRunningWindows7())
return;
UINT max_count = 0;
IObjectArray* objectArray;
ICustomDestinationList* destinationList;
//create the custom jump list object
CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList,
reinterpret_cast<void**> (&(destinationList)));
//initialize list
destinationList->BeginList(&max_count, IID_IObjectArray, reinterpret_cast<void**> (&(objectArray)));
AddTasksToList(destinationList);
//commit list
destinationList->CommitList();
objectArray->Release();
destinationList->Release();
#endif
}