Query Focus Assist state on Windows.
This commit is contained in:
parent
3a28be1e16
commit
2730ab1596
|
@ -37,6 +37,11 @@ include(cmake/td_scheme.cmake)
|
||||||
include(cmake/td_ui.cmake)
|
include(cmake/td_ui.cmake)
|
||||||
include(cmake/generate_appdata_changelog.cmake)
|
include(cmake/generate_appdata_changelog.cmake)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
include(cmake/generate_midl.cmake)
|
||||||
|
generate_midl(Telegram ${src_loc}/platform/win/windows_quiethours.idl)
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)
|
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)
|
||||||
|
|
||||||
target_link_libraries(Telegram
|
target_link_libraries(Telegram
|
||||||
|
|
|
@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/core_settings.h"
|
#include "core/core_settings.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "windows_quiethours_h.h"
|
||||||
|
|
||||||
#include <Shobjidl.h>
|
#include <Shobjidl.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
@ -632,27 +633,30 @@ namespace {
|
||||||
bool QuietHoursEnabled = false;
|
bool QuietHoursEnabled = false;
|
||||||
DWORD QuietHoursValue = 0;
|
DWORD QuietHoursValue = 0;
|
||||||
|
|
||||||
bool useQuietHoursRegistryEntry() {
|
[[nodiscard]] bool UseQuietHoursRegistryEntry() {
|
||||||
// Taken from QSysInfo.
|
static const bool result = [] {
|
||||||
OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0,{ '\0' } };
|
// Taken from QSysInfo.
|
||||||
if (const auto library = GetModuleHandle(L"ntdll.dll")) {
|
OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0,{ '\0' } };
|
||||||
using RtlGetVersionFunction = NTSTATUS(NTAPI*)(LPOSVERSIONINFO);
|
if (const auto library = GetModuleHandle(L"ntdll.dll")) {
|
||||||
const auto RtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
|
using RtlGetVersionFunction = NTSTATUS(NTAPI*)(LPOSVERSIONINFO);
|
||||||
GetProcAddress(library, "RtlGetVersion"));
|
const auto RtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
|
||||||
if (RtlGetVersion) {
|
GetProcAddress(library, "RtlGetVersion"));
|
||||||
RtlGetVersion(&result);
|
if (RtlGetVersion) {
|
||||||
|
RtlGetVersion(&result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
// At build 17134 (Redstone 4) the "Quiet hours" was replaced
|
||||||
// At build 17134 (Redstone 4) the "Quiet hours" was replaced
|
// by "Focus assist" and it looks like it doesn't use registry.
|
||||||
// by "Focus assist" and it looks like it doesn't use registry.
|
return (result.dwMajorVersion == 10
|
||||||
return (result.dwMajorVersion == 10
|
&& result.dwMinorVersion == 0
|
||||||
&& result.dwMinorVersion == 0
|
&& result.dwBuildNumber < 17134);
|
||||||
&& result.dwBuildNumber < 17134);
|
}();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thanks https://stackoverflow.com/questions/35600128/get-windows-quiet-hours-from-win32-or-c-sharp-api
|
// Thanks https://stackoverflow.com/questions/35600128/get-windows-quiet-hours-from-win32-or-c-sharp-api
|
||||||
void queryQuietHours() {
|
void QueryQuietHours() {
|
||||||
if (!useQuietHoursRegistryEntry()) {
|
if (!UseQuietHoursRegistryEntry()) {
|
||||||
// There are quiet hours in Windows starting from Windows 8.1
|
// There are quiet hours in Windows starting from Windows 8.1
|
||||||
// But there were several reports about the notifications being shut
|
// But there were several reports about the notifications being shut
|
||||||
// down according to the registry while no quiet hours were enabled.
|
// down according to the registry while no quiet hours were enabled.
|
||||||
|
@ -683,9 +687,82 @@ void queryQuietHours() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FocusAssistBlocks = false;
|
||||||
|
|
||||||
|
void QueryFocusAssist() {
|
||||||
|
ComPtr<IQuietHoursSettings> quietHoursSettings;
|
||||||
|
auto hr = CoCreateInstance(
|
||||||
|
CLSID_QuietHoursSettings,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_LOCAL_SERVER,
|
||||||
|
IID_PPV_ARGS(&quietHoursSettings));
|
||||||
|
if (!SUCCEEDED(hr) || !quietHoursSettings) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto profileId = LPWSTR{};
|
||||||
|
const auto guardProfileId = gsl::finally([&] {
|
||||||
|
if (profileId) CoTaskMemFree(profileId);
|
||||||
|
});
|
||||||
|
hr = quietHoursSettings->get_UserSelectedProfile(&profileId);
|
||||||
|
if (!SUCCEEDED(hr) || !profileId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto profileName = QString::fromWCharArray(profileId);
|
||||||
|
if (profileName.endsWith(".unrestricted", Qt::CaseInsensitive)) {
|
||||||
|
if (FocusAssistBlocks) {
|
||||||
|
LOG(("Focus Assist: Unrestricted."));
|
||||||
|
FocusAssistBlocks = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (profileName.endsWith(".alarmsonly", Qt::CaseInsensitive)) {
|
||||||
|
if (!FocusAssistBlocks) {
|
||||||
|
LOG(("Focus Assist: Alarms Only."));
|
||||||
|
FocusAssistBlocks = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto appUserModelId = std::wstring(AppUserModelId::getId());
|
||||||
|
auto blocked = true;
|
||||||
|
const auto guard = gsl::finally([&] {
|
||||||
|
if (FocusAssistBlocks != blocked) {
|
||||||
|
LOG(("Focus Assist: %1, AppUserModelId: %2, Blocks: %3"
|
||||||
|
).arg(profileName
|
||||||
|
).arg(QString::fromStdWString(appUserModelId)
|
||||||
|
).arg(Logs::b(blocked)));
|
||||||
|
FocusAssistBlocks = blocked;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ComPtr<IQuietHoursProfile> profile;
|
||||||
|
hr = quietHoursSettings->GetProfile(profileId, &profile);
|
||||||
|
if (!SUCCEEDED(hr) || !profile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 count = 0;
|
||||||
|
auto apps = (LPWSTR*)nullptr;
|
||||||
|
const auto guardApps = gsl::finally([&] {
|
||||||
|
if (apps) CoTaskMemFree(apps);
|
||||||
|
});
|
||||||
|
hr = profile->GetAllowedApps(&count, &apps);
|
||||||
|
if (!SUCCEEDED(hr) || !apps) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (UINT32 i = 0; i < count; i++) {
|
||||||
|
auto app = apps[i];
|
||||||
|
const auto guardApp = gsl::finally([&] {
|
||||||
|
if (app) CoTaskMemFree(app);
|
||||||
|
});
|
||||||
|
if (app == appUserModelId) {
|
||||||
|
blocked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QUERY_USER_NOTIFICATION_STATE UserNotificationState = QUNS_ACCEPTS_NOTIFICATIONS;
|
QUERY_USER_NOTIFICATION_STATE UserNotificationState = QUNS_ACCEPTS_NOTIFICATIONS;
|
||||||
|
|
||||||
void queryUserNotificationState() {
|
void QueryUserNotificationState() {
|
||||||
if (Dlls::SHQueryUserNotificationState != nullptr) {
|
if (Dlls::SHQueryUserNotificationState != nullptr) {
|
||||||
QUERY_USER_NOTIFICATION_STATE state;
|
QUERY_USER_NOTIFICATION_STATE state;
|
||||||
if (SUCCEEDED(Dlls::SHQueryUserNotificationState(&state))) {
|
if (SUCCEEDED(Dlls::SHQueryUserNotificationState(&state))) {
|
||||||
|
@ -697,24 +774,26 @@ void queryUserNotificationState() {
|
||||||
static constexpr auto kQuerySettingsEachMs = 1000;
|
static constexpr auto kQuerySettingsEachMs = 1000;
|
||||||
crl::time LastSettingsQueryMs = 0;
|
crl::time LastSettingsQueryMs = 0;
|
||||||
|
|
||||||
void querySystemNotificationSettings() {
|
void QuerySystemNotificationSettings() {
|
||||||
auto ms = crl::now();
|
auto ms = crl::now();
|
||||||
if (LastSettingsQueryMs > 0 && ms <= LastSettingsQueryMs + kQuerySettingsEachMs) {
|
if (LastSettingsQueryMs > 0 && ms <= LastSettingsQueryMs + kQuerySettingsEachMs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LastSettingsQueryMs = ms;
|
LastSettingsQueryMs = ms;
|
||||||
queryQuietHours();
|
QueryQuietHours();
|
||||||
queryUserNotificationState();
|
QueryFocusAssist();
|
||||||
|
QueryUserNotificationState();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool SkipAudio() {
|
bool SkipAudio() {
|
||||||
querySystemNotificationSettings();
|
QuerySystemNotificationSettings();
|
||||||
|
|
||||||
if (UserNotificationState == QUNS_NOT_PRESENT
|
if (UserNotificationState == QUNS_NOT_PRESENT
|
||||||
|| UserNotificationState == QUNS_PRESENTATION_MODE
|
|| UserNotificationState == QUNS_PRESENTATION_MODE
|
||||||
|| QuietHoursEnabled) {
|
|| QuietHoursEnabled
|
||||||
|
|| FocusAssistBlocks) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (const auto filter = EventFilter::GetInstance()) {
|
if (const auto filter = EventFilter::GetInstance()) {
|
||||||
|
@ -726,12 +805,13 @@ bool SkipAudio() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkipToast() {
|
bool SkipToast() {
|
||||||
querySystemNotificationSettings();
|
QuerySystemNotificationSettings();
|
||||||
|
|
||||||
if (UserNotificationState == QUNS_PRESENTATION_MODE
|
if (UserNotificationState == QUNS_PRESENTATION_MODE
|
||||||
|| UserNotificationState == QUNS_RUNNING_D3D_FULL_SCREEN
|
|| UserNotificationState == QUNS_RUNNING_D3D_FULL_SCREEN
|
||||||
//|| UserNotificationState == QUNS_BUSY
|
//|| UserNotificationState == QUNS_BUSY
|
||||||
|| QuietHoursEnabled) {
|
|| QuietHoursEnabled
|
||||||
|
|| FocusAssistBlocks) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
// © Rafael Rivera
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
|
import "oaidl.idl";
|
||||||
|
|
||||||
|
[uuid(e0b5ef8b-a9b4-497a-8f71-08dd5c8ab2bf)]
|
||||||
|
library QuietHours
|
||||||
|
{
|
||||||
|
[uuid(f53321fa-34f8-4b7f-b9a3-361877cb94cf)]
|
||||||
|
coclass QuietHoursSettings
|
||||||
|
{
|
||||||
|
[default] interface IQuietHoursSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
[uuid(af86e2e0-b12d-4c6a-9c5a-d7aa65101e90)]
|
||||||
|
interface IQuietMoment : IUnknown
|
||||||
|
{
|
||||||
|
// Incomplete
|
||||||
|
}
|
||||||
|
|
||||||
|
[uuid(e813fe81-62b6-417d-b951-9d2e08486ac1)]
|
||||||
|
interface IQuietHoursProfile : IUnknown
|
||||||
|
{
|
||||||
|
[propget] HRESULT DisplayName([out, string, retval] LPWSTR* displayName);
|
||||||
|
[propget] HRESULT ProfileId([out, string, retval] LPWSTR* profileId);
|
||||||
|
HRESULT GetSetting(int setting, [out, retval] int* value);
|
||||||
|
HRESULT PutSetting(int setting, int value);
|
||||||
|
[propget] HRESULT IsCustomizable([out, retval] BOOL* result);
|
||||||
|
HRESULT GetAllowedContacts([out] UINT32* count, [out, retval] LPWSTR* allowedContacts);
|
||||||
|
HRESULT AddAllowedContact([in, string] LPWSTR allowedContact);
|
||||||
|
HRESULT RemoveAllowedContact([in, string] LPWSTR allowedContact);
|
||||||
|
HRESULT GetAllowedApps([out] UINT32* count, [out, retval] LPWSTR** allowedApps);
|
||||||
|
HRESULT AddAllowedApp([in, string] LPWSTR allowedApp);
|
||||||
|
HRESULT RemoveAllowedApp([in, string] LPWSTR allowedApp);
|
||||||
|
[propget] HRESULT Description([out, string, retval] LPWSTR* description);
|
||||||
|
[propget] HRESULT CustomizeLinkText([out, string, retval] LPWSTR* linkText);
|
||||||
|
[propget] HRESULT RestrictiveLevel([out, string, retval] LPWSTR* restrictiveLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[uuid(cd86a976-8ea9-404b-a197-42e73dbaa901)]
|
||||||
|
interface IQuietHoursPinnedContactManager : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT GetPinnedContactList([out] UINT32* count, [out, string, retval] LPWSTR* pinnedContacts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[uuid(b0217783-87b7-422c-b902-5c148c14f150)]
|
||||||
|
interface IQuietMomentsManager : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT GetAllQuietMomentModes([out] UINT32* count, [out, retval] UINT32** quietMomentModes);
|
||||||
|
HRESULT GetQuietMoment([in] UINT32 quietMomentId, [out, retval] IQuietMoment** quietMoment);
|
||||||
|
HRESULT TurnOffCurrentlyActiveQuietMoment();
|
||||||
|
HRESULT GetActiveQuietMoment([out, retval] UINT32* quietMomentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _QH_PROFILE_DATA
|
||||||
|
{
|
||||||
|
char do_not_use__incomplete; // Incomplete
|
||||||
|
} QH_PROFILE_DATA;
|
||||||
|
|
||||||
|
[uuid(6bff4732-81ec-4ffb-ae67-b6c1bc29631f)]
|
||||||
|
interface IQuietHoursSettings : IUnknown
|
||||||
|
{
|
||||||
|
[propget] HRESULT UserSelectedProfile([out, string, retval] LPWSTR* profileId);
|
||||||
|
[propput] HRESULT UserSelectedProfile([in] LPWSTR profileId);
|
||||||
|
HRESULT GetProfile([in, string] LPWSTR profileId, [out, retval] IQuietHoursProfile**);
|
||||||
|
HRESULT GetAllProfileData(UINT32* count, QH_PROFILE_DATA*);
|
||||||
|
HRESULT GetDisplayNameForProfile([in, string] LPWSTR profileId, [out, string, retval] LPWSTR* displayName);
|
||||||
|
[propget] HRESULT QuietMomentsManager([out, retval] IQuietMomentsManager**);
|
||||||
|
[propget] HRESULT OffProfileId([out, string, retval] LPWSTR* profileId);
|
||||||
|
[propget] HRESULT ActiveQuietMomentProfile([out, string, retval] LPWSTR* profileId);
|
||||||
|
[propput] HRESULT ActiveQuietMomentProfile([in] LPWSTR profileId);
|
||||||
|
[propget] HRESULT ActiveProfile([out, string, retval] LPWSTR* profileId);
|
||||||
|
[propget] HRESULT QuietHoursPinnedContactManager([out, retval] IQuietHoursPinnedContactManager**);
|
||||||
|
[propput] HRESULT QuietMomentsShowSummaryEnabled([out, retval] BOOL* isEnabled);
|
||||||
|
HRESULT GetAlwaysAllowedApps([out] UINT32* count, [out, string, retval] LPWSTR** allowedApps);
|
||||||
|
HRESULT StartProcessing();
|
||||||
|
HRESULT StopProcessing();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
function(generate_midl target_name idl_file)
|
||||||
|
set(gen_dst ${CMAKE_CURRENT_BINARY_DIR}/gen)
|
||||||
|
file(MAKE_DIRECTORY ${gen_dst})
|
||||||
|
|
||||||
|
get_filename_component(idl_file_name ${idl_file} NAME_WLE)
|
||||||
|
|
||||||
|
set(gen_timestamp ${gen_dst}/midl_${idl_file_name}.timestamp)
|
||||||
|
set(gen_files
|
||||||
|
${gen_dst}/${idl_file_name}_i.c
|
||||||
|
${gen_dst}/${idl_file_name}_h.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if (build_win64)
|
||||||
|
set(env x64)
|
||||||
|
else()
|
||||||
|
set(env win32)
|
||||||
|
endif()
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT
|
||||||
|
${gen_timestamp}
|
||||||
|
BYPRODUCTS
|
||||||
|
${gen_files}
|
||||||
|
COMMAND
|
||||||
|
midl
|
||||||
|
/out ${gen_dst}
|
||||||
|
/h ${idl_file_name}_h.h
|
||||||
|
/env ${env}
|
||||||
|
/notlb
|
||||||
|
${idl_file}
|
||||||
|
COMMAND
|
||||||
|
echo 1> ${gen_timestamp}
|
||||||
|
COMMENT "Generating header from IDL (${target_name})"
|
||||||
|
DEPENDS
|
||||||
|
${idl_file}
|
||||||
|
)
|
||||||
|
generate_target(${target_name} midl ${gen_timestamp} "${gen_files}" ${gen_dst})
|
||||||
|
endfunction()
|
|
@ -1 +1 @@
|
||||||
Subproject commit 053ab218dfb65e9cbd7c7a1d9594fa886ba27f0b
|
Subproject commit 3d256df61ebf4b92b79bf9eba39a33f7a885b1d3
|
Loading…
Reference in New Issue