Detect tablet mode on Windows 10.
This commit is contained in:
parent
7fa342b487
commit
40e90af76d
|
@ -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
|
||||
|
|
|
@ -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 <QtWidgets/QStyleFactory>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QScreen>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include <Shobjidl.h>
|
||||
#include <shellapi.h>
|
||||
#include <WtsApi32.h>
|
||||
|
||||
#include <roapi.h>
|
||||
#include <wrl/client.h>
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
#include <UIViewSettingsInterop.h>
|
||||
|
||||
#include <Windowsx.h>
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
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<ITaskbarList3> taskbarList;
|
||||
|
||||
bool handleSessionNotification = false;
|
||||
uint32 kTaskbarCreatedMsgId = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
UINT MainWindow::_taskbarCreatedMsgId = 0;
|
||||
struct MainWindow::Private {
|
||||
ComPtr<ViewManagement::IUIViewSettings> viewSettings;
|
||||
};
|
||||
|
||||
MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||
: Window::MainWindow(controller)
|
||||
, _private(std::make_unique<Private>())
|
||||
, 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<IUIViewSettingsInterop>();
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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> _private;
|
||||
|
||||
std::optional<Ui::Platform::WindowShadow> _shadow;
|
||||
|
||||
|
|
|
@ -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 <Shobjidl.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <roapi.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#include "platform/win/wrapper_wrl_implements_h.h"
|
||||
#include "base/platform/win/wrl/wrl_implements_h.h"
|
||||
#include <windows.ui.notifications.h>
|
||||
|
||||
#include <strsafe.h>
|
||||
#include <intsafe.h>
|
||||
|
||||
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<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
~StringReferenceWrapper() {
|
||||
Dlls::WindowsDeleteString(_hstring);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
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<DWORD>(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t _>
|
||||
StringReferenceWrapper(_In_reads_(_) wchar_t(&stringRef)[_]) throw() {
|
||||
UINT32 length;
|
||||
HRESULT hr = SizeTToUInt32(wcslen(stringRef), &length);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
RaiseException(static_cast<DWORD>(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<class T>
|
||||
_Check_return_ __inline HRESULT _1_GetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ T** factory) {
|
||||
return Dlls::RoGetActivationFactory(activatableClassId, IID_INS_ARGS(factory));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline HRESULT wrap_GetActivationFactory(_In_ HSTRING activatableClassId, _Inout_ Details::ComPtrRef<T> 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*)(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <wrl/implements.h>
|
||||
#pragma warning(pop)
|
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user