Move global event filter to Platform::Integration on Windows.

This commit is contained in:
John Preston 2022-01-04 15:29:40 +03:00
parent 20411be9bd
commit 8b0725650d
22 changed files with 410 additions and 262 deletions

View File

@ -948,6 +948,8 @@ PRIVATE
platform/linux/file_utilities_linux.h
platform/linux/launcher_linux.cpp
platform/linux/launcher_linux.h
platform/linux/integration_linux.cpp
platform/linux/integration_linux.h
platform/linux/main_window_linux.cpp
platform/linux/main_window_linux.h
platform/linux/notifications_manager_linux_dummy.cpp
@ -959,6 +961,8 @@ PRIVATE
platform/mac/file_utilities_mac.h
platform/mac/launcher_mac.mm
platform/mac/launcher_mac.h
platform/mac/integration_mac.mm
platform/mac/integration_mac.h
platform/mac/mac_iconv_helper.c
platform/mac/main_window_mac.mm
platform/mac/main_window_mac.h
@ -993,6 +997,8 @@ PRIVATE
platform/win/file_utilities_win.h
platform/win/launcher_win.cpp
platform/win/launcher_win.h
platform/win/integration_win.cpp
platform/win/integration_win.h
platform/win/main_window_win.cpp
platform/win/main_window_win.h
platform/win/notifications_manager_win.cpp
@ -1003,8 +1009,6 @@ PRIVATE
platform/win/windows_app_user_model_id.h
platform/win/windows_dlls.cpp
platform/win/windows_dlls.h
platform/win/windows_event_filter.cpp
platform/win/windows_event_filter.h
platform/win/windows_autostart_task.cpp
platform/win/windows_autostart_task.h
platform/win/windows_toast_activator.cpp
@ -1012,6 +1016,8 @@ PRIVATE
platform/platform_audio.h
platform/platform_file_utilities.h
platform/platform_launcher.h
platform/platform_integration.cpp
platform/platform_integration.h
platform/platform_main_window.h
platform/platform_notifications_manager.h
platform/platform_specific.h

View File

@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/base_platform_last_input.h"
#include "base/platform/base_platform_info.h"
#include "platform/platform_specific.h"
#include "platform/platform_integration.h"
#include "mainwindow.h"
#include "dialogs/dialogs_entry.h"
#include "history/history.h"
@ -130,6 +131,7 @@ Application::Application(not_null<Launcher*> launcher)
: QObject()
, _launcher(launcher)
, _private(std::make_unique<Private>())
, _platformIntegration(Platform::Integration::Create())
, _databases(std::make_unique<Storage::Databases>())
, _animationsManager(std::make_unique<Ui::Animations::Manager>())
, _clearEmojiImageLoaderTimer([=] { clearEmojiSourceImages(); })
@ -145,6 +147,8 @@ Application::Application(not_null<Launcher*> launcher)
, _autoLockTimer([=] { checkAutoLock(); }) {
Ui::Integration::Set(&_private->uiIntegration);
_platformIntegration->init();
passcodeLockChanges(
) | rpl::start_with_next([=] {
_shouldLockAt = 0;

View File

@ -17,6 +17,10 @@ class MainWidget;
class FileUploader;
class Translator;
namespace Platform {
class Integration;
} // namespace Platform
namespace Storage {
class Databases;
} // namespace Storage
@ -115,8 +119,11 @@ public:
Application &operator=(const Application &other) = delete;
~Application();
[[nodiscard]] not_null<Launcher*> launcher() const {
return _launcher;
[[nodiscard]] Launcher &launcher() const {
return *_launcher;
}
[[nodiscard]] Platform::Integration &platformIntegration() const {
return *_platformIntegration;
}
void run();
@ -317,13 +324,13 @@ private:
};
InstanceSetter _setter = { this };
not_null<Launcher*> _launcher;
const not_null<Launcher*> _launcher;
rpl::event_stream<ProxyChange> _proxyChanges;
// Some fields are just moved from the declaration.
struct Private;
const std::unique_ptr<Private> _private;
Settings _settings;
const std::unique_ptr<Platform::Integration> _platformIntegration;
const std::unique_ptr<Storage::Databases> _databases;
const std::unique_ptr<Ui::Animations::Manager> _animationsManager;

View File

@ -0,0 +1,9 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/linux/integration_linux.h"

View File

@ -0,0 +1,9 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once

View File

@ -0,0 +1,9 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once

View File

@ -0,0 +1,9 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/mac/integration_mac.h"

View File

@ -0,0 +1,43 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/platform_integration.h"
#ifdef Q_OS_MAC
#include "platform/mac/integration_mac.h"
#elif defined Q_OS_UNIX // Q_OS_MAC
#include "platform/linux/integration_linux.h"
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
#include "platform/win/integration_win.h"
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN
namespace Platform {
namespace {
Integration *GlobalInstance/* = nullptr*/;
} // namespace
Integration::~Integration() {
GlobalInstance = nullptr;
}
std::unique_ptr<Integration> Integration::Create() {
Expects(GlobalInstance == nullptr);
auto result = CreateIntegration();
GlobalInstance = result.get();
return result;
}
Integration &Integration::Instance() {
Expects(GlobalInstance != nullptr);
return *GlobalInstance;
};
} // namespace Platform

View File

@ -0,0 +1,23 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Platform {
class Integration {
public:
virtual void init() {
}
virtual ~Integration();
[[nodiscard]] static std::unique_ptr<Integration> Create();
[[nodiscard]] static Integration &Instance();
};
} // namespace Platform

View File

@ -0,0 +1,99 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/win/integration_win.h"
#include "platform/platform_integration.h"
#include "platform/platform_specific.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "app.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QAbstractNativeEventFilter>
namespace Platform {
namespace {
class WindowsIntegration final
: public Integration
, public QAbstractNativeEventFilter {
public:
void init() override;
private:
bool nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) override;
bool processEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result);
};
void WindowsIntegration::init() {
QCoreApplication::instance()->installNativeEventFilter(this);
}
bool WindowsIntegration::nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) {
return Core::Sandbox::Instance().customEnterFromEventLoop([&] {
const auto msg = static_cast<MSG*>(message);
return processEvent(
msg->hwnd,
msg->message,
msg->wParam,
msg->lParam,
(LRESULT*)result);
});
}
bool WindowsIntegration::processEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result) {
switch (msg) {
case WM_ENDSESSION:
App::quit();
break;
case WM_TIMECHANGE:
Core::App().checkAutoLockIn(100);
break;
case WM_WTSSESSION_CHANGE:
if (wParam == WTS_SESSION_LOGOFF
|| wParam == WTS_SESSION_LOCK) {
Core::App().setScreenIsLocked(true);
} else if (wParam == WTS_SESSION_LOGON
|| wParam == WTS_SESSION_UNLOCK) {
Core::App().setScreenIsLocked(false);
}
break;
case WM_SETTINGCHANGE:
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode());
break;
}
return false;
}
} // namespace
std::unique_ptr<Integration> CreateIntegration() {
return std::make_unique<WindowsIntegration>();
}
} // namespace Platform

View File

@ -0,0 +1,16 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Platform {
class Integration;
[[nodiscard]] std::unique_ptr<Integration> CreateIntegration();
} // namespace Platform

View File

@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_specific.h"
#include "platform/platform_notifications_manager.h"
#include "platform/win/windows_dlls.h"
#include "platform/win/windows_event_filter.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "mainwindow.h"
@ -20,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/win/base_windows_wrl.h"
#include "base/platform/base_platform_info.h"
#include "core/application.h"
#include "core/sandbox.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "ui/widgets/popup_menu.h"
@ -58,8 +58,33 @@ namespace {
// icon click (both left or right button) was made from the active app.
constexpr auto kKeepActiveForTrayIcon = crl::time(500);
class EventFilter final : public QAbstractNativeEventFilter {
public:
explicit EventFilter(not_null<MainWindow*> window);
private:
bool nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) override;
bool mainWindowEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result);
const not_null<MainWindow*> _window;
};
using namespace Microsoft::WRL;
ComPtr<ITaskbarList3> taskbarList;
bool handleSessionNotification = false;
uint32 kTaskbarCreatedMsgId = 0;
[[nodiscard]] HICON NativeIcon(const QIcon &icon, QSize size) {
if (!icon.isNull()) {
const auto pixmap = icon.pixmap(icon.actualSize(size));
@ -133,22 +158,88 @@ using namespace Microsoft::WRL;
return result;
}
ComPtr<ITaskbarList3> taskbarList;
bool handleSessionNotification = false;
uint32 kTaskbarCreatedMsgId = 0;
EventFilter::EventFilter(not_null<MainWindow*> window) : _window(window) {
}
bool EventFilter::nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) {
return Core::Sandbox::Instance().customEnterFromEventLoop([&] {
const auto msg = static_cast<MSG*>(message);
if (msg->hwnd == _window->psHwnd()
|| msg->hwnd && !_window->psHwnd()) {
return mainWindowEvent(
msg->hwnd,
msg->message,
msg->wParam,
msg->lParam,
(LRESULT*)result);
}
return false;
});
}
bool EventFilter::mainWindowEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result) {
if (const auto tbCreatedMsgId = kTaskbarCreatedMsgId) {
if (msg == tbCreatedMsgId) {
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&taskbarList));
if (!SUCCEEDED(hr)) {
taskbarList.Reset();
}
}
}
switch (msg) {
case WM_DESTROY: {
_window->destroyedFromSystem();
} return false;
case WM_ACTIVATE: {
if (LOWORD(wParam) != WA_INACTIVE) {
_window->shadowsActivate();
} else {
_window->shadowsDeactivate();
}
} return false;
case WM_SIZE: {
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) {
if (wParam == SIZE_RESTORED && _window->windowState() == Qt::WindowNoState) {
_window->positionUpdated();
}
}
} return false;
case WM_MOVE: {
_window->positionUpdated();
} return false;
}
return false;
}
} // namespace
struct MainWindow::Private {
explicit Private(not_null<MainWindow*> window) : filter(window) {
}
EventFilter filter;
ComPtr<ViewManagement::IUIViewSettings> viewSettings;
};
MainWindow::MainWindow(not_null<Window::Controller*> controller)
: Window::MainWindow(controller)
, _private(std::make_unique<Private>())
, _private(std::make_unique<Private>(this))
, _taskbarHiderWindow(std::make_unique<QWindow>()) {
QCoreApplication::instance()->installNativeEventFilter(
EventFilter::CreateInstance(this));
qApp->installNativeEventFilter(&_private->filter);
if (!kTaskbarCreatedMsgId) {
kTaskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated");
@ -178,17 +269,6 @@ void MainWindow::setupNativeWindowFrame() {
}, lifetime());
}
uint32 MainWindow::TaskbarCreatedMsgId() {
return kTaskbarCreatedMsgId;
}
void MainWindow::TaskbarCreated() {
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&taskbarList));
if (!SUCCEEDED(hr)) {
taskbarList.Reset();
}
}
void MainWindow::shadowsActivate() {
_hasActiveFrame = true;
}
@ -201,6 +281,10 @@ void MainWindow::psShowTrayMenu() {
trayIconMenu->popup(QCursor::pos());
}
void MainWindow::destroyedFromSystem() {
App::quit();
}
int32 MainWindow::screenNameChecksum(const QString &name) const {
constexpr int DeviceNameSize = base::array_size(MONITORINFOEX().szDevice);
wchar_t buffer[DeviceNameSize] = { 0 };
@ -212,7 +296,7 @@ int32 MainWindow::screenNameChecksum(const QString &name) const {
return base::crc32(buffer, sizeof(buffer));
}
void MainWindow::psRefreshTaskbarIcon() {
void MainWindow::forceIconRefresh() {
const auto refresher = std::make_unique<QWidget>(this);
refresher->setWindowFlags(static_cast<Qt::WindowFlags>(Qt::Tool) | Qt::FramelessWindowHint);
refresher->setGeometry(x() + 1, y() + 1, 1, 1);
@ -267,20 +351,20 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) {
switch (mode) {
case WorkMode::WindowAndTray: {
psSetupTrayIcon();
HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
HWND psOwner = (HWND)GetWindowLongPtr(_hWnd, GWLP_HWNDPARENT);
if (psOwner) {
SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, 0);
SetWindowLongPtr(_hWnd, GWLP_HWNDPARENT, 0);
windowHandle()->setTransientParent(nullptr);
psRefreshTaskbarIcon();
forceIconRefresh();
}
} break;
case WorkMode::TrayOnly: {
psSetupTrayIcon();
HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
HWND psOwner = (HWND)GetWindowLongPtr(_hWnd, GWLP_HWNDPARENT);
if (!psOwner) {
const auto hwnd = _taskbarHiderWindow->winId();
SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, (LONG_PTR)hwnd);
SetWindowLongPtr(_hWnd, GWLP_HWNDPARENT, (LONG_PTR)hwnd);
windowHandle()->setTransientParent(_taskbarHiderWindow.get());
}
} break;
@ -292,11 +376,11 @@ void MainWindow::workmodeUpdated(Core::Settings::WorkMode mode) {
}
trayIcon = 0;
HWND psOwner = (HWND)GetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT);
HWND psOwner = (HWND)GetWindowLongPtr(_hWnd, GWLP_HWNDPARENT);
if (psOwner) {
SetWindowLongPtr(ps_hWnd, GWLP_HWNDPARENT, 0);
SetWindowLongPtr(_hWnd, GWLP_HWNDPARENT, 0);
windowHandle()->setTransientParent(nullptr);
psRefreshTaskbarIcon();
forceIconRefresh();
}
} break;
}
@ -403,11 +487,11 @@ void MainWindow::updateIconCounters() {
trayIcon->setIcon(forTrayIcon);
}
psDestroyIcons();
ps_iconSmall = NativeIcon(iconSmall, iconSizeSmall);
ps_iconBig = NativeIcon(iconBig, iconSizeBig);
SendMessage(ps_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)ps_iconSmall);
SendMessage(ps_hWnd, WM_SETICON, ICON_BIG, (LPARAM)(ps_iconBig ? ps_iconBig : ps_iconSmall));
destroyCachedIcons();
_iconSmall = NativeIcon(iconSmall, iconSizeSmall);
_iconBig = NativeIcon(iconBig, iconSizeBig);
SendMessage(_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)_iconSmall);
SendMessage(_hWnd, WM_SETICON, ICON_BIG, (LPARAM)(_iconBig ? _iconBig : _iconSmall));
if (taskbarList) {
if (counter > 0) {
const auto pixmap = [&](int size) {
@ -417,27 +501,23 @@ void MainWindow::updateIconCounters() {
QIcon iconOverlay;
iconOverlay.addPixmap(pixmap(16));
iconOverlay.addPixmap(pixmap(32));
ps_iconOverlay = NativeIcon(iconOverlay, iconSizeSmall);
_iconOverlay = NativeIcon(iconOverlay, iconSizeSmall);
}
const auto description = (counter > 0)
? tr::lng_unread_bar(tr::now, lt_count, counter).toStdWString()
: std::wstring();
taskbarList->SetOverlayIcon(ps_hWnd, ps_iconOverlay, description.c_str());
taskbarList->SetOverlayIcon(_hWnd, _iconOverlay, description.c_str());
}
SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
SetWindowPos(_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
void MainWindow::initHook() {
ps_hWnd = reinterpret_cast<HWND>(winId());
if (!ps_hWnd) {
_hWnd = reinterpret_cast<HWND>(winId());
if (!_hWnd) {
return;
}
handleSessionNotification = (Dlls::WTSRegisterSessionNotification != nullptr)
&& (Dlls::WTSUnRegisterSessionNotification != nullptr);
if (handleSessionNotification) {
Dlls::WTSRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION);
}
WTSRegisterSessionNotification(_hWnd, NOTIFY_FOR_THIS_SESSION);
using namespace base::Platform;
auto factory = ComPtr<IUIViewSettingsInterop>();
@ -449,7 +529,7 @@ void MainWindow::initHook() {
if (factory) {
// NB! No such method (or IUIViewSettingsInterop) in C++/WinRT :(
factory->GetForWindow(
ps_hWnd,
_hWnd,
IID_PPV_ARGS(&_private->viewSettings));
}
}
@ -462,7 +542,7 @@ void MainWindow::initHook() {
void MainWindow::validateWindowTheme(bool native, bool night) {
if (!IsWindows8OrGreater()) {
const auto empty = native ? nullptr : L" ";
SetWindowTheme(ps_hWnd, empty, empty);
SetWindowTheme(_hWnd, empty, empty);
QApplication::setStyle(QStyleFactory::create(u"Windows"_q));
#if 0
} else if (!Platform::IsDarkModeSupported()/*
@ -473,7 +553,7 @@ void MainWindow::validateWindowTheme(bool native, bool night) {
return;
#endif
} else if (!native) {
SetWindowTheme(ps_hWnd, nullptr, nullptr);
SetWindowTheme(_hWnd, nullptr, nullptr);
return;
}
@ -491,13 +571,13 @@ void MainWindow::validateWindowTheme(bool native, bool night) {
&darkValue,
sizeof(darkValue)
};
Dlls::SetWindowCompositionAttribute(ps_hWnd, &data);
Dlls::SetWindowCompositionAttribute(_hWnd, &data);
} else if (kSystemVersion.microVersion() >= 17763) {
static const auto kDWMWA_USE_IMMERSIVE_DARK_MODE = (kSystemVersion.microVersion() >= 18985)
? DWORD(20)
: DWORD(19);
DwmSetWindowAttribute(
ps_hWnd,
_hWnd,
kDWMWA_USE_IMMERSIVE_DARK_MODE,
&darkValue,
sizeof(darkValue));
@ -514,7 +594,7 @@ void MainWindow::validateWindowTheme(bool native, bool night) {
//const auto updateWindowTheme = [&] {
// const auto set = [&](LPCWSTR name) {
// return SetWindowTheme(ps_hWnd, name, nullptr);
// return SetWindowTheme(_hWnd, name, nullptr);
// };
// if (!night || FAILED(set(L"DarkMode_Explorer"))) {
// set(L"Explorer");
@ -527,14 +607,14 @@ void MainWindow::validateWindowTheme(bool native, bool night) {
// } else {
// Dlls::AllowDarkModeForApp(TRUE);
// }
// Dlls::AllowDarkModeForWindow(ps_hWnd, TRUE);
// Dlls::AllowDarkModeForWindow(_hWnd, TRUE);
// updateWindowTheme();
// updateStyle();
// Dlls::FlushMenuThemes();
// Dlls::RefreshImmersiveColorPolicyState();
//} else {
// updateWindowTheme();
// Dlls::AllowDarkModeForWindow(ps_hWnd, FALSE);
// Dlls::AllowDarkModeForWindow(_hWnd, FALSE);
// updateStyle();
// Dlls::FlushMenuThemes();
// Dlls::RefreshImmersiveColorPolicyState();
@ -546,8 +626,8 @@ void MainWindow::validateWindowTheme(bool native, bool night) {
//}
// Didn't find any other way to definitely repaint with the new style.
SendMessage(ps_hWnd, WM_NCACTIVATE, _hasActiveFrame ? 0 : 1, 0);
SendMessage(ps_hWnd, WM_NCACTIVATE, _hasActiveFrame ? 1 : 0, 0);
SendMessage(_hWnd, WM_NCACTIVATE, _hasActiveFrame ? 0 : 1, 0);
SendMessage(_hWnd, WM_NCACTIVATE, _hasActiveFrame ? 1 : 0, 0);
}
void MainWindow::showFromTrayMenu() {
@ -562,36 +642,28 @@ void MainWindow::showFromTrayMenu() {
}
HWND MainWindow::psHwnd() const {
return ps_hWnd;
return _hWnd;
}
void MainWindow::psDestroyIcons() {
if (ps_iconBig) {
DestroyIcon(ps_iconBig);
ps_iconBig = 0;
}
if (ps_iconSmall) {
DestroyIcon(ps_iconSmall);
ps_iconSmall = 0;
}
if (ps_iconOverlay) {
DestroyIcon(ps_iconOverlay);
ps_iconOverlay = 0;
}
void MainWindow::destroyCachedIcons() {
const auto destroy = [](HICON &icon) {
if (icon) {
DestroyIcon(icon);
icon = nullptr;
}
};
destroy(_iconBig);
destroy(_iconSmall);
destroy(_iconOverlay);
}
MainWindow::~MainWindow() {
if (handleSessionNotification) {
Dlls::WTSUnRegisterSessionNotification(ps_hWnd);
}
WTSUnRegisterSessionNotification(_hWnd);
_private->viewSettings.Reset();
if (taskbarList) {
taskbarList.Reset();
}
psDestroyIcons();
EventFilter::Destroy();
destroyCachedIcons();
}
} // namespace Platform

View File

@ -28,11 +28,6 @@ public:
void updateWindowIcon() override;
bool isActiveForTrayMenu() override;
void psRefreshTaskbarIcon();
[[nodiscard]] static uint32 TaskbarCreatedMsgId();
static void TaskbarCreated();
// Custom shadows.
void shadowsActivate();
void shadowsDeactivate();
@ -41,6 +36,8 @@ public:
void psShowTrayMenu();
void destroyedFromSystem();
~MainWindow();
protected:
@ -72,22 +69,23 @@ private:
void setupNativeWindowFrame();
void updateIconCounters();
void validateWindowTheme(bool native, bool night);
void psDestroyIcons();
void forceIconRefresh();
void destroyCachedIcons();
const std::unique_ptr<Private> _private;
const std::unique_ptr<QWindow> _taskbarHiderWindow;
bool _hasActiveFrame = false;
HWND _hWnd = nullptr;
HICON _iconBig = nullptr;
HICON _iconSmall = nullptr;
HICON _iconOverlay = nullptr;
// Workarounds for activation from tray icon.
crl::time _lastDeactivateTime = 0;
rpl::lifetime _showFromTrayLifetime;
HWND ps_hWnd = nullptr;
HICON ps_iconBig = nullptr;
HICON ps_iconSmall = nullptr;
HICON ps_iconOverlay = nullptr;
const std::unique_ptr<QWindow> _taskbarHiderWindow;
bool _hasActiveFrame = false;
};

View File

@ -16,7 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/qthelp_url.h"
#include "platform/win/windows_app_user_model_id.h"
#include "platform/win/windows_toast_activator.h"
#include "platform/win/windows_event_filter.h"
#include "platform/win/windows_dlls.h"
#include "platform/win/specific_win.h"
#include "history/history.h"

View File

@ -53,10 +53,6 @@ SafeIniter::SafeIniter() {
// }
//}
const auto LibWtsApi32 = LoadLibrary(L"wtsapi32.dll");
LOAD_SYMBOL(LibWtsApi32, WTSRegisterSessionNotification);
LOAD_SYMBOL(LibWtsApi32, WTSUnRegisterSessionNotification);
const auto LibPropSys = LoadLibrary(L"propsys.dll");
LOAD_SYMBOL(LibPropSys, PSStringFromPropertyKey);

View File

@ -68,14 +68,6 @@ inline void(__stdcall *SHChangeNotify)(
inline HRESULT(__stdcall *SetCurrentProcessExplicitAppUserModelID)(
__in PCWSTR AppID);
// WTSAPI32.DLL
inline BOOL(__stdcall *WTSRegisterSessionNotification)(
HWND hWnd,
DWORD dwFlags);
inline BOOL(__stdcall *WTSUnRegisterSessionNotification)(
HWND hWnd);
// PROPSYS.DLL
inline HRESULT(__stdcall *PSStringFromPropertyKey)(

View File

@ -1,123 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/win/windows_event_filter.h"
#include "platform/win/specific_win.h"
#include "core/sandbox.h"
#include "core/core_settings.h"
#include "core/application.h"
#include "mainwindow.h"
#include "app.h"
#include <QtGui/QWindow>
namespace Platform {
namespace {
EventFilter *instance = nullptr;
} // namespace
EventFilter *EventFilter::CreateInstance(not_null<MainWindow*> window) {
Expects(instance == nullptr);
return (instance = new EventFilter(window));
}
void EventFilter::Destroy() {
Expects(instance != nullptr);
delete instance;
instance = nullptr;
}
EventFilter::EventFilter(not_null<MainWindow*> window) : _window(window) {
}
bool EventFilter::nativeEventFilter(
const QByteArray &eventType,
void *message,
long *result) {
return Core::Sandbox::Instance().customEnterFromEventLoop([&] {
const auto msg = static_cast<MSG*>(message);
if (msg->message == WM_ENDSESSION) {
App::quit();
return false;
}
if (msg->hwnd == _window->psHwnd()
|| msg->hwnd && !_window->psHwnd()) {
return mainWindowEvent(
msg->hwnd,
msg->message,
msg->wParam,
msg->lParam,
(LRESULT*)result);
}
return false;
});
}
bool EventFilter::mainWindowEvent(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
LRESULT *result) {
if (const auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) {
if (msg == tbCreatedMsgId) {
Platform::MainWindow::TaskbarCreated();
}
}
switch (msg) {
case WM_TIMECHANGE: {
Core::App().checkAutoLockIn(100);
} return false;
case WM_WTSSESSION_CHANGE: {
if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) {
Core::App().setScreenIsLocked(true);
} else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) {
Core::App().setScreenIsLocked(false);
}
} return false;
case WM_DESTROY: {
App::quit();
} return false;
case WM_ACTIVATE: {
if (LOWORD(wParam) != WA_INACTIVE) {
_window->shadowsActivate();
} else {
_window->shadowsDeactivate();
}
} return false;
case WM_SIZE: {
if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) {
if (wParam == SIZE_RESTORED && _window->windowState() == Qt::WindowNoState) {
_window->positionUpdated();
}
}
} return false;
case WM_MOVE: {
_window->positionUpdated();
} return false;
case WM_SETTINGCHANGE: {
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode());
} return false;
}
return false;
}
} // namespace Platform

View File

@ -1,33 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/platform/win/base_windows_h.h"
#include <QtCore/QAbstractNativeEventFilter>
namespace Platform {
class MainWindow;
class EventFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
bool mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result);
static EventFilter *CreateInstance(not_null<MainWindow*> window);
static void Destroy();
private:
explicit EventFilter(not_null<MainWindow*> window);
not_null<MainWindow*> _window;
};
} // namespace Platform

View File

@ -340,6 +340,14 @@ Main::Account &MainWindow::account() const {
return _controller->account();
}
PeerData *MainWindow::singlePeer() const {
return _controller->singlePeer();
}
bool MainWindow::isPrimary() const {
return _controller->isPrimary();
}
Window::SessionController *MainWindow::sessionController() const {
return _controller->sessionController();
}

View File

@ -62,6 +62,8 @@ public:
[[nodiscard]] Window::Controller &controller() const {
return *_controller;
}
[[nodiscard]] PeerData *singlePeer() const;
[[nodiscard]] bool isPrimary() const;
[[nodiscard]] Main::Account &account() const;
[[nodiscard]] Window::SessionController *sessionController() const;

View File

@ -63,7 +63,7 @@ Controller::~Controller() {
}
void Controller::showAccount(not_null<Main::Account*> account) {
Expects(!_singlePeer || &_singlePeer->account() == account);
Expects(isPrimary() || &_singlePeer->account() == account);
const auto prevSessionUniqueId = (_account && _account->sessionExists())
? _account->session().uniqueId()

View File

@ -32,6 +32,9 @@ public:
void showAccount(not_null<Main::Account*> account);
[[nodiscard]] PeerData *singlePeer() const;
[[nodiscard]] bool isPrimary() const {
return (singlePeer() == nullptr);
}
[[nodiscard]] not_null<::MainWindow*> widget() {
return &_widget;