From 40e90af76df92ad761232c66b0596b43ce16a226 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 16 Jan 2021 16:33:09 +0400 Subject: [PATCH] Detect tablet mode on Windows 10. --- Telegram/CMakeLists.txt | 1 - .../platform/win/main_window_win.cpp | 68 +++++++++++++++-- .../platform/win/main_window_win.h | 12 ++- .../win/notifications_manager_win.cpp | 74 +++---------------- .../SourceFiles/platform/win/windows_dlls.cpp | 10 --- .../SourceFiles/platform/win/windows_dlls.h | 19 ----- .../platform/win/windows_event_filter.cpp | 5 +- .../platform/win/wrapper_wrl_implements_h.h | 14 ---- Telegram/SourceFiles/window/main_window.cpp | 4 + Telegram/SourceFiles/window/main_window.h | 4 + 10 files changed, 89 insertions(+), 122 deletions(-) delete mode 100644 Telegram/SourceFiles/platform/win/wrapper_wrl_implements_h.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 7810cb2055..fccf3ddcde 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -902,7 +902,6 @@ PRIVATE platform/win/windows_dlls.h platform/win/windows_event_filter.cpp platform/win/windows_event_filter.h - platform/win/wrapper_wrl_implements_h.h platform/platform_audio.h platform/platform_file_utilities.h platform/platform_launcher.h diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index c93530ba49..24e3a0f2df 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/notifications_manager.h" #include "mainwindow.h" #include "base/crc32hash.h" +#include "base/platform/win/base_windows_wrl.h" #include "core/application.h" #include "lang/lang_keys.h" #include "storage/localstorage.h" @@ -27,24 +28,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include #include #include #include #include -#include -#include +#include +#include #include #include HICON qt_pixmapToWinHICON(const QPixmap &); -using namespace Microsoft::WRL; - Q_DECLARE_METATYPE(QMargins); +namespace ViewManagement = ABI::Windows::UI::ViewManagement; + namespace Platform { namespace { @@ -55,6 +57,8 @@ namespace { // icon click (both left or right button) was made from the active app. constexpr auto kKeepActiveForTrayIcon = crl::time(500); +using namespace Microsoft::WRL; + HICON createHIconFromQIcon(const QIcon &icon, int xSize, int ySize) { if (!icon.isNull()) { const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize))); @@ -99,21 +103,24 @@ HWND createTaskbarHider() { } ComPtr taskbarList; - bool handleSessionNotification = false; +uint32 kTaskbarCreatedMsgId = 0; } // namespace -UINT MainWindow::_taskbarCreatedMsgId = 0; +struct MainWindow::Private { + ComPtr viewSettings; +}; MainWindow::MainWindow(not_null controller) : Window::MainWindow(controller) +, _private(std::make_unique()) , ps_tbHider_hWnd(createTaskbarHider()) { QCoreApplication::instance()->installNativeEventFilter( EventFilter::CreateInstance(this)); - if (!_taskbarCreatedMsgId) { - _taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); + if (!kTaskbarCreatedMsgId) { + kTaskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); } subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { if (_shadow && update.paletteChanged()) { @@ -168,6 +175,10 @@ 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)) { @@ -291,6 +302,32 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { } } +bool MainWindow::hasTabletView() const { + if (!_private->viewSettings) { + return false; + } + auto mode = ViewManagement::UserInteractionMode(); + _private->viewSettings->get_UserInteractionMode(&mode); + return (mode == ViewManagement::UserInteractionMode_Touch); +} + +bool MainWindow::initSizeFromSystem() { + if (!hasTabletView()) { + return false; + } + const auto screen = [&] { + if (const auto result = windowHandle()->screen()) { + return result; + } + return QGuiApplication::primaryScreen(); + }(); + if (!screen) { + return false; + } + setGeometry(screen->geometry()); + return true; +} + void MainWindow::updateWindowIcon() { updateIconCounters(); } @@ -362,6 +399,20 @@ void MainWindow::initHook() { Dlls::WTSRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION); } + using namespace base::Platform; + auto factory = ComPtr(); + if (SupportsWRL()) { + GetActivationFactory( + StringReferenceWrapper( + RuntimeClass_Windows_UI_ViewManagement_UIViewSettings).Get(), + &factory); + if (factory) { + factory->GetForWindow( + ps_hWnd, + IID_PPV_ARGS(&_private->viewSettings)); + } + } + psInitSysMenu(); } @@ -662,6 +713,7 @@ MainWindow::~MainWindow() { if (handleSessionNotification) { Dlls::WTSUnRegisterSessionNotification(ps_hWnd); } + _private->viewSettings.Reset(); if (taskbarList) { taskbarList.Reset(); } diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index 61042afcd0..a60f2b9415 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -40,9 +40,7 @@ public: virtual QImage iconWithCounter(int size, int count, style::color bg, style::color fg, bool smallIcon) = 0; - static UINT TaskbarCreatedMsgId() { - return _taskbarCreatedMsgId; - } + [[nodiscard]] static uint32 TaskbarCreatedMsgId(); static void TaskbarCreated(); // Custom shadows. @@ -59,6 +57,8 @@ public: return _deltaTop; } + [[nodiscard]] bool hasTabletView() const; + void psShowTrayMenu(); ~MainWindow(); @@ -87,9 +87,13 @@ protected: void workmodeUpdated(DBIWorkMode mode) override; + bool initSizeFromSystem() override; + QTimer psUpdatedPositionTimer; private: + struct Private; + void setupNativeWindowFrame(); void updateIconCounters(); QMargins computeCustomMargins(); @@ -97,7 +101,7 @@ private: void psDestroyIcons(); void fixMaximizedWindow(); - static UINT _taskbarCreatedMsgId; + const std::unique_ptr _private; std::optional _shadow; diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp index fe0b73b729..c4ac40370e 100644 --- a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp +++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/win/notifications_manager_win.h" #include "window/notifications_utilities.h" +#include "base/platform/win/base_windows_wrl.h" +#include "base/platform/base_platform_info.h" #include "platform/win/windows_app_user_model_id.h" #include "platform/win/windows_event_filter.h" #include "platform/win/windows_dlls.h" @@ -20,16 +22,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include -#include -#include - #ifndef __MINGW32__ -#include "platform/win/wrapper_wrl_implements_h.h" +#include "base/platform/win/wrl/wrl_implements_h.h" #include -#include -#include - HICON qt_pixmapToWinHICON(const QPixmap &); using namespace Microsoft::WRL; @@ -44,68 +40,16 @@ namespace Notifications { #ifndef __MINGW32__ namespace { -class StringReferenceWrapper { -public: - StringReferenceWrapper(_In_reads_(length) PCWSTR stringRef, _In_ UINT32 length) throw() { - HRESULT hr = Dlls::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); - if (!SUCCEEDED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } - } - - ~StringReferenceWrapper() { - Dlls::WindowsDeleteString(_hstring); - } - - template - StringReferenceWrapper(_In_reads_(N) wchar_t const (&stringRef)[N]) throw() { - UINT32 length = N - 1; - HRESULT hr = Dlls::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); - if (!SUCCEEDED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } - } - - template - StringReferenceWrapper(_In_reads_(_) wchar_t(&stringRef)[_]) throw() { - UINT32 length; - HRESULT hr = SizeTToUInt32(wcslen(stringRef), &length); - if (!SUCCEEDED(hr)) { - RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); - } - - Dlls::WindowsCreateStringReference(stringRef, length, &_header, &_hstring); - } - - HSTRING Get() const throw() { - return _hstring; - } - -private: - HSTRING _hstring; - HSTRING_HEADER _header; - -}; - -template -_Check_return_ __inline HRESULT _1_GetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ T** factory) { - return Dlls::RoGetActivationFactory(activatableClassId, IID_INS_ARGS(factory)); -} - -template -inline HRESULT wrap_GetActivationFactory(_In_ HSTRING activatableClassId, _Inout_ Details::ComPtrRef factory) throw() { - return _1_GetActivationFactory(activatableClassId, factory.ReleaseAndGetAddressOf()); -} +using base::Platform::GetActivationFactory; +using base::Platform::StringReferenceWrapper; bool init() { - if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8) { + if (!IsWindows8OrGreater()) { return false; } if ((Dlls::SetCurrentProcessExplicitAppUserModelID == nullptr) || (Dlls::PropVariantToString == nullptr) - || (Dlls::RoGetActivationFactory == nullptr) - || (Dlls::WindowsCreateStringReference == nullptr) - || (Dlls::WindowsDeleteString == nullptr)) { + || !base::Platform::SupportsWRL()) { return false; } @@ -395,7 +339,7 @@ Manager::Private::Private(Manager *instance, Type type) } bool Manager::Private::init() { - if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &_notificationManager))) { + if (!SUCCEEDED(GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(), &_notificationManager))) { return false; } @@ -404,7 +348,7 @@ bool Manager::Private::init() { return false; } - if (!SUCCEEDED(wrap_GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &_notificationFactory))) { + if (!SUCCEEDED(GetActivationFactory(StringReferenceWrapper(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(), &_notificationFactory))) { return false; } return true; diff --git a/Telegram/SourceFiles/platform/win/windows_dlls.cpp b/Telegram/SourceFiles/platform/win/windows_dlls.cpp index bac70f7381..e88fad4094 100644 --- a/Telegram/SourceFiles/platform/win/windows_dlls.cpp +++ b/Telegram/SourceFiles/platform/win/windows_dlls.cpp @@ -63,9 +63,6 @@ f_WTSUnRegisterSessionNotification WTSUnRegisterSessionNotification; f_SHQueryUserNotificationState SHQueryUserNotificationState; f_SHChangeNotify SHChangeNotify; f_SetCurrentProcessExplicitAppUserModelID SetCurrentProcessExplicitAppUserModelID; -f_RoGetActivationFactory RoGetActivationFactory; -f_WindowsCreateStringReference WindowsCreateStringReference; -f_WindowsDeleteString WindowsDeleteString; f_PropVariantToString PropVariantToString; f_PSStringFromPropertyKey PSStringFromPropertyKey; f_DwmIsCompositionEnabled DwmIsCompositionEnabled; @@ -112,13 +109,6 @@ void start() { LoadMethod(LibPropSys, "PropVariantToString", PropVariantToString); LoadMethod(LibPropSys, "PSStringFromPropertyKey", PSStringFromPropertyKey); - if (IsWindows8OrGreater()) { - const auto LibComBase = SafeLoadLibrary(u"combase.dll"_q); - LoadMethod(LibComBase, "RoGetActivationFactory", RoGetActivationFactory); - LoadMethod(LibComBase, "WindowsCreateStringReference", WindowsCreateStringReference); - LoadMethod(LibComBase, "WindowsDeleteString", WindowsDeleteString); - } - const auto LibDwmApi = SafeLoadLibrary(u"dwmapi.dll"_q); LoadMethod(LibDwmApi, "DwmIsCompositionEnabled", DwmIsCompositionEnabled); LoadMethod(LibDwmApi, "DwmSetWindowAttribute", DwmSetWindowAttribute); diff --git a/Telegram/SourceFiles/platform/win/windows_dlls.h b/Telegram/SourceFiles/platform/win/windows_dlls.h index b01fbd9b49..7f34e59e42 100644 --- a/Telegram/SourceFiles/platform/win/windows_dlls.h +++ b/Telegram/SourceFiles/platform/win/windows_dlls.h @@ -126,25 +126,6 @@ using f_PSStringFromPropertyKey = HRESULT(FAR STDAPICALLTYPE*)( _In_ UINT cch); extern f_PSStringFromPropertyKey PSStringFromPropertyKey; -// COMBASE.DLL - -using f_RoGetActivationFactory = HRESULT(FAR STDAPICALLTYPE*)( - _In_ HSTRING activatableClassId, - _In_ REFIID iid, - _COM_Outptr_ void ** factory); -extern f_RoGetActivationFactory RoGetActivationFactory; - -using f_WindowsCreateStringReference = HRESULT(FAR STDAPICALLTYPE*)( - _In_reads_opt_(length + 1) PCWSTR sourceString, - UINT32 length, - _Out_ HSTRING_HEADER * hstringHeader, - _Outptr_result_maybenull_ _Result_nullonfailure_ HSTRING * string); -extern f_WindowsCreateStringReference WindowsCreateStringReference; - -using f_WindowsDeleteString = HRESULT(FAR STDAPICALLTYPE*)( - _In_opt_ HSTRING string); -extern f_WindowsDeleteString WindowsDeleteString; - // DWMAPI.DLL using f_DwmIsCompositionEnabled = HRESULT(FAR STDAPICALLTYPE*)( diff --git a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp index bdd55b9579..3e1b9e7995 100644 --- a/Telegram/SourceFiles/platform/win/windows_event_filter.cpp +++ b/Telegram/SourceFiles/platform/win/windows_event_filter.cpp @@ -268,7 +268,10 @@ bool EventFilter::mainWindowEvent( case WM_WINDOWPOSCHANGED: { WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); - if (GetWindowPlacement(hWnd, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) { + if (_window->hasTabletView() + || (GetWindowPlacement(hWnd, &wp) + && (wp.showCmd == SW_SHOWMAXIMIZED + || wp.showCmd == SW_SHOWMINIMIZED))) { _window->shadowsUpdate(Change::Hidden); } else { _window->shadowsUpdate(Change::Moved | Change::Resized, (WINDOWPOS*)lParam); diff --git a/Telegram/SourceFiles/platform/win/wrapper_wrl_implements_h.h b/Telegram/SourceFiles/platform/win/wrapper_wrl_implements_h.h deleted file mode 100644 index 4f7ccd7f7d..0000000000 --- a/Telegram/SourceFiles/platform/win/wrapper_wrl_implements_h.h +++ /dev/null @@ -1,14 +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 - -#pragma warning(push) -// class has virtual functions, but destructor is not virtual -#pragma warning(disable:4265) -#include -#pragma warning(pop) diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 4760636a93..9bbbdadafc 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -420,6 +420,10 @@ void MainWindow::recountGeometryConstraints() { void MainWindow::initSize() { updateMinimumSize(); + if (initSizeFromSystem()) { + return; + } + auto position = cWindowPos(); DEBUG_LOG(("Window Pos: Initializing first %1, %2, %3, %4 (maximized %5)").arg(position.x).arg(position.y).arg(position.w).arg(position.h).arg(Logs::b(position.maximized))); diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index c209138af5..a6ab3749e0 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -186,6 +186,10 @@ protected: virtual void firstShadowsUpdate() { } + virtual bool initSizeFromSystem() { + return false; + } + // This one is overriden in Windows for historical reasons. virtual int32 screenNameChecksum(const QString &name) const;