mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Show just logo in Dwm Preview when passcoded.
This commit is contained in:
parent
c7b3c95dc6
commit
88f3aeca5b
2 changed files with 234 additions and 3 deletions
|
@ -47,7 +47,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <Windowsx.h>
|
#include <Windowsx.h>
|
||||||
#include <VersionHelpers.h>
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
|
// Taken from qtbase/src/gui/image/qpixmap_win.cpp
|
||||||
HICON qt_pixmapToWinHICON(const QPixmap &);
|
HICON qt_pixmapToWinHICON(const QPixmap &);
|
||||||
|
HBITMAP qt_imageToWinHBITMAP(const QImage &, int hbitmapFormat);
|
||||||
|
|
||||||
namespace ViewManagement = ABI::Windows::UI::ViewManagement;
|
namespace ViewManagement = ABI::Windows::UI::ViewManagement;
|
||||||
|
|
||||||
|
@ -61,6 +63,15 @@ namespace {
|
||||||
// icon click (both left or right button) was made from the active app.
|
// icon click (both left or right button) was made from the active app.
|
||||||
constexpr auto kKeepActiveForTrayIcon = crl::time(500);
|
constexpr auto kKeepActiveForTrayIcon = crl::time(500);
|
||||||
|
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
|
// Taken from qtbase/src/gui/image/qpixmap_win.cpp
|
||||||
|
enum HBitmapFormat {
|
||||||
|
HBitmapNoAlpha,
|
||||||
|
HBitmapPremultipliedAlpha,
|
||||||
|
HBitmapAlpha
|
||||||
|
};
|
||||||
|
|
||||||
class EventFilter final : public QAbstractNativeEventFilter {
|
class EventFilter final : public QAbstractNativeEventFilter {
|
||||||
public:
|
public:
|
||||||
explicit EventFilter(not_null<MainWindow*> window);
|
explicit EventFilter(not_null<MainWindow*> window);
|
||||||
|
@ -82,9 +93,6 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using namespace Microsoft::WRL;
|
|
||||||
|
|
||||||
bool handleSessionNotification = false;
|
|
||||||
|
|
||||||
[[nodiscard]] HICON NativeIcon(const QIcon &icon, QSize size) {
|
[[nodiscard]] HICON NativeIcon(const QIcon &icon, QSize size) {
|
||||||
if (!icon.isNull()) {
|
if (!icon.isNull()) {
|
||||||
|
@ -96,6 +104,67 @@ bool handleSessionNotification = false;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RealSize {
|
||||||
|
QSize value;
|
||||||
|
bool maximized = false;
|
||||||
|
};
|
||||||
|
[[nodiscard]] RealSize DetectRealSize(HWND hwnd) {
|
||||||
|
auto result = RECT();
|
||||||
|
auto placement = WINDOWPLACEMENT();
|
||||||
|
if (!GetWindowPlacement(hwnd, &placement)) {
|
||||||
|
return {};
|
||||||
|
} else if (placement.flags & WPF_RESTORETOMAXIMIZED) {
|
||||||
|
const auto monitor = MonitorFromRect(
|
||||||
|
&placement.rcNormalPosition,
|
||||||
|
MONITOR_DEFAULTTONULL);
|
||||||
|
if (!monitor) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto info = MONITORINFO{ .cbSize = sizeof(MONITORINFO) };
|
||||||
|
if (!GetMonitorInfo(monitor, &info)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
result = info.rcWork;
|
||||||
|
} else {
|
||||||
|
CopyRect(&result, &placement.rcNormalPosition);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
{ int(result.right - result.left), int(result.bottom - result.top) },
|
||||||
|
((placement.flags & WPF_RESTORETOMAXIMIZED) != 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] QImage PrepareLogoPreview(
|
||||||
|
QSize size,
|
||||||
|
QImage::Format format,
|
||||||
|
int radius = 0) {
|
||||||
|
auto result = QImage(size, QImage::Format_RGB32);
|
||||||
|
result.fill(st::windowBg->c);
|
||||||
|
|
||||||
|
const auto logo = Window::Logo();
|
||||||
|
const auto width = size.width();
|
||||||
|
const auto height = size.height();
|
||||||
|
const auto side = logo.width();
|
||||||
|
const auto skip = width / 8;
|
||||||
|
const auto use = std::min({ width - skip, height - skip, side });
|
||||||
|
auto p = QPainter(&result);
|
||||||
|
if (use == side) {
|
||||||
|
p.drawImage((width - side) / 2, (height - side) / 2, logo);
|
||||||
|
} else {
|
||||||
|
const auto scaled = logo.scaled(
|
||||||
|
use,
|
||||||
|
use,
|
||||||
|
Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
p.drawImage((width - use) / 2, (height - use) / 2, scaled);
|
||||||
|
}
|
||||||
|
p.end();
|
||||||
|
|
||||||
|
return radius
|
||||||
|
? Images::Round(std::move(result), Images::CornersMask(radius))
|
||||||
|
: result;
|
||||||
|
}
|
||||||
|
|
||||||
EventFilter::EventFilter(not_null<MainWindow*> window) : _window(window) {
|
EventFilter::EventFilter(not_null<MainWindow*> window) : _window(window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +219,23 @@ bool EventFilter::mainWindowEvent(
|
||||||
_window->positionUpdated();
|
_window->positionUpdated();
|
||||||
} return false;
|
} return false;
|
||||||
|
|
||||||
|
case WM_DWMSENDICONICTHUMBNAIL: {
|
||||||
|
if (!Core::App().passcodeLocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto size = QSize(int(HIWORD(lParam)), int(LOWORD(lParam)));
|
||||||
|
return _window->setDwmThumbnail(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_DWMSENDICONICLIVEPREVIEWBITMAP: {
|
||||||
|
if (!Core::App().passcodeLocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto size = DetectRealSize(hWnd);
|
||||||
|
const auto radius = size.maximized ? 0 : style::ConvertScale(8);
|
||||||
|
return _window->setDwmPreview(size.value, radius);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +250,46 @@ struct MainWindow::Private {
|
||||||
ComPtr<ViewManagement::IUIViewSettings> viewSettings;
|
ComPtr<ViewManagement::IUIViewSettings> viewSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MainWindow::BitmapPointer::BitmapPointer(HBITMAP value) : _value(value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::BitmapPointer::BitmapPointer(BitmapPointer &&other)
|
||||||
|
: _value(base::take(other._value)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::BitmapPointer &MainWindow::BitmapPointer::operator=(
|
||||||
|
BitmapPointer &&other) {
|
||||||
|
if (_value != other._value) {
|
||||||
|
reset();
|
||||||
|
_value = base::take(other._value);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::BitmapPointer::~BitmapPointer() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
HBITMAP MainWindow::BitmapPointer::get() const {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::BitmapPointer::operator bool() const {
|
||||||
|
return _value != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::BitmapPointer::release() {
|
||||||
|
_value = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::BitmapPointer::reset(HBITMAP value) {
|
||||||
|
if (_value != value) {
|
||||||
|
if (const auto old = std::exchange(_value, value)) {
|
||||||
|
DeleteObject(old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||||
: Window::MainWindow(controller)
|
: Window::MainWindow(controller)
|
||||||
, _private(std::make_unique<Private>(this))
|
, _private(std::make_unique<Private>(this))
|
||||||
|
@ -180,6 +306,27 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||||
) | rpl::filter(_1) | rpl::start_with_next([=] {
|
) | rpl::filter(_1) | rpl::start_with_next([=] {
|
||||||
_lastDeactivateTime = crl::now();
|
_lastDeactivateTime = crl::now();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
setupPreviewPasscodeLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setupPreviewPasscodeLock() {
|
||||||
|
Core::App().passcodeLockValue(
|
||||||
|
) | rpl::start_with_next([=](bool locked) {
|
||||||
|
// Use iconic bitmap instead of the window content if passcoded.
|
||||||
|
BOOL fForceIconic = locked ? TRUE : FALSE;
|
||||||
|
BOOL fHasIconicBitmap = fForceIconic;
|
||||||
|
DwmSetWindowAttribute(
|
||||||
|
_hWnd,
|
||||||
|
DWMWA_FORCE_ICONIC_REPRESENTATION,
|
||||||
|
&fForceIconic,
|
||||||
|
sizeof(fForceIconic));
|
||||||
|
DwmSetWindowAttribute(
|
||||||
|
_hWnd,
|
||||||
|
DWMWA_HAS_ICONIC_BITMAP,
|
||||||
|
&fHasIconicBitmap,
|
||||||
|
sizeof(fHasIconicBitmap));
|
||||||
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setupNativeWindowFrame() {
|
void MainWindow::setupNativeWindowFrame() {
|
||||||
|
@ -211,6 +358,60 @@ void MainWindow::destroyedFromSystem() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::setDwmThumbnail(QSize size) {
|
||||||
|
validateDwmPreviewColors();
|
||||||
|
if (size.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
} else if (!_dwmThumbnail || _dwmThumbnailSize != size) {
|
||||||
|
const auto result = PrepareLogoPreview(size, QImage::Format_RGB32);
|
||||||
|
const auto bitmap = qt_imageToWinHBITMAP(result, HBitmapNoAlpha);
|
||||||
|
if (!bitmap) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_dwmThumbnail.reset(bitmap);
|
||||||
|
_dwmThumbnailSize = size;
|
||||||
|
}
|
||||||
|
DwmSetIconicThumbnail(_hWnd, _dwmThumbnail.get(), NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::setDwmPreview(QSize size, int radius) {
|
||||||
|
Expects(radius >= 0);
|
||||||
|
|
||||||
|
validateDwmPreviewColors();
|
||||||
|
if (size.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
} else if (!_dwmPreview
|
||||||
|
|| _dwmPreviewSize != size
|
||||||
|
|| _dwmPreviewRadius != radius) {
|
||||||
|
const auto format = (radius > 0)
|
||||||
|
? QImage::Format_ARGB32_Premultiplied
|
||||||
|
: QImage::Format_RGB32;
|
||||||
|
const auto result = PrepareLogoPreview(size, format, radius);
|
||||||
|
const auto bitmap = qt_imageToWinHBITMAP(
|
||||||
|
result,
|
||||||
|
(radius > 0) ? HBitmapPremultipliedAlpha : HBitmapNoAlpha);
|
||||||
|
if (!bitmap) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_dwmPreview.reset(bitmap);
|
||||||
|
_dwmPreviewRadius = radius;
|
||||||
|
_dwmPreviewSize = size;
|
||||||
|
}
|
||||||
|
const auto flags = 0;
|
||||||
|
DwmSetIconicLivePreviewBitmap(_hWnd, _dwmPreview.get(), NULL, flags);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::validateDwmPreviewColors() {
|
||||||
|
if (_dwmBackground == st::windowBg->c) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_dwmBackground = st::windowBg->c;
|
||||||
|
_dwmThumbnail.reset();
|
||||||
|
_dwmPreview.reset();
|
||||||
|
}
|
||||||
|
|
||||||
int32 MainWindow::screenNameChecksum(const QString &name) const {
|
int32 MainWindow::screenNameChecksum(const QString &name) const {
|
||||||
constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice);
|
constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice);
|
||||||
wchar_t buffer[DeviceNameSize] = { 0 };
|
wchar_t buffer[DeviceNameSize] = { 0 };
|
||||||
|
|
|
@ -34,6 +34,9 @@ public:
|
||||||
|
|
||||||
void destroyedFromSystem();
|
void destroyedFromSystem();
|
||||||
|
|
||||||
|
bool setDwmThumbnail(QSize size);
|
||||||
|
bool setDwmPreview(QSize size, int radius);
|
||||||
|
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -50,12 +53,32 @@ protected:
|
||||||
private:
|
private:
|
||||||
struct Private;
|
struct Private;
|
||||||
|
|
||||||
|
class BitmapPointer {
|
||||||
|
public:
|
||||||
|
BitmapPointer(HBITMAP value = nullptr);
|
||||||
|
BitmapPointer(BitmapPointer &&other);
|
||||||
|
BitmapPointer& operator=(BitmapPointer &&other);
|
||||||
|
~BitmapPointer();
|
||||||
|
|
||||||
|
[[nodiscard]] HBITMAP get() const;
|
||||||
|
[[nodiscard]] explicit operator bool() const;
|
||||||
|
|
||||||
|
void release();
|
||||||
|
void reset(HBITMAP value = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HBITMAP _value = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
void setupNativeWindowFrame();
|
void setupNativeWindowFrame();
|
||||||
|
void setupPreviewPasscodeLock();
|
||||||
void updateTaskbarAndIconCounters();
|
void updateTaskbarAndIconCounters();
|
||||||
void validateWindowTheme(bool native, bool night);
|
void validateWindowTheme(bool native, bool night);
|
||||||
|
|
||||||
void forceIconRefresh();
|
void forceIconRefresh();
|
||||||
void destroyCachedIcons();
|
void destroyCachedIcons();
|
||||||
|
void validateDwmPreviewColors();
|
||||||
|
|
||||||
const std::unique_ptr<Private> _private;
|
const std::unique_ptr<Private> _private;
|
||||||
const std::unique_ptr<QWindow> _taskbarHiderWindow;
|
const std::unique_ptr<QWindow> _taskbarHiderWindow;
|
||||||
|
@ -65,6 +88,13 @@ private:
|
||||||
HICON _iconSmall = nullptr;
|
HICON _iconSmall = nullptr;
|
||||||
HICON _iconOverlay = nullptr;
|
HICON _iconOverlay = nullptr;
|
||||||
|
|
||||||
|
BitmapPointer _dwmThumbnail;
|
||||||
|
BitmapPointer _dwmPreview;
|
||||||
|
QSize _dwmThumbnailSize;
|
||||||
|
QSize _dwmPreviewSize;
|
||||||
|
QColor _dwmBackground;
|
||||||
|
int _dwmPreviewRadius = 0;
|
||||||
|
|
||||||
// Workarounds for activation from tray icon.
|
// Workarounds for activation from tray icon.
|
||||||
crl::time _lastDeactivateTime = 0;
|
crl::time _lastDeactivateTime = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue