/* 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 "base/platform/win/base_windows_winrt.h" #include "core/application.h" #include "core/core_settings.h" #include "core/sandbox.h" #include "lang/lang_keys.h" #include "platform/win/windows_app_user_model_id.h" #include "platform/win/tray_win.h" #include "platform/platform_integration.h" #include "platform/platform_specific.h" #include "tray.h" #include "styles/style_window.h" #include #include #include #include namespace Platform { void WindowsIntegration::init() { QCoreApplication::instance()->installNativeEventFilter(this); _taskbarCreatedMsgId = RegisterWindowMessage(L"TaskbarButtonCreated"); } ITaskbarList3 *WindowsIntegration::taskbarList() const { return _taskbarList.get(); } WindowsIntegration &WindowsIntegration::Instance() { return static_cast(Integration::Instance()); } bool WindowsIntegration::nativeEventFilter( const QByteArray &eventType, void *message, long *result) { return Core::Sandbox::Instance().customEnterFromEventLoop([&] { const auto msg = static_cast(message); return processEvent( msg->hwnd, msg->message, msg->wParam, msg->lParam, (LRESULT*)result); }); } void WindowsIntegration::createCustomJumpList() { _jumpList = base::WinRT::TryCreateInstance( CLSID_DestinationList); if (_jumpList) { refreshCustomJumpList(); } } void WindowsIntegration::refreshCustomJumpList() { auto added = false; auto maxSlots = UINT(); auto removed = (IObjectArray*)nullptr; auto hr = _jumpList->BeginList(&maxSlots, IID_PPV_ARGS(&removed)); if (!SUCCEEDED(hr)) { return; } const auto guard = gsl::finally([&] { if (added) { _jumpList->CommitList(); } else { _jumpList->AbortList(); } }); auto shellLink = base::WinRT::TryCreateInstance( CLSID_ShellLink); if (!shellLink) { return; } // Set the path to your application and the command-line argument for quitting const auto exe = QDir::toNativeSeparators(cExeDir() + cExeName()); const auto dir = QDir::toNativeSeparators(QDir(cWorkingDir()).absolutePath()); const auto icon = Tray::QuitJumpListIconPath(); shellLink->SetArguments(L"-quit"); shellLink->SetPath(exe.toStdWString().c_str()); shellLink->SetWorkingDirectory(dir.toStdWString().c_str()); shellLink->SetIconLocation(icon.toStdWString().c_str(), 0); if (const auto propertyStore = shellLink.try_as()) { auto appIdPropVar = PROPVARIANT(); hr = InitPropVariantFromString( AppUserModelId::Id().c_str(), &appIdPropVar); if (SUCCEEDED(hr)) { hr = propertyStore->SetValue( AppUserModelId::Key(), appIdPropVar); PropVariantClear(&appIdPropVar); } auto titlePropVar = PROPVARIANT(); hr = InitPropVariantFromString( tr::lng_quit_from_tray(tr::now).toStdWString().c_str(), &titlePropVar); if (SUCCEEDED(hr)) { hr = propertyStore->SetValue(PKEY_Title, titlePropVar); PropVariantClear(&titlePropVar); } propertyStore->Commit(); } auto collection = base::WinRT::TryCreateInstance( CLSID_EnumerableObjectCollection); if (!collection) { return; } collection->AddObject(shellLink.get()); _jumpList->AddUserTasks(collection.get()); added = true; } bool WindowsIntegration::processEvent( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result) { if (msg && msg == _taskbarCreatedMsgId && !_taskbarList) { _taskbarList = base::WinRT::TryCreateInstance( CLSID_TaskbarList, CLSCTX_ALL); if (_taskbarList) { createCustomJumpList(); } } switch (msg) { case WM_ENDSESSION: Core::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: RefreshTaskbarThemeValue(); #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) Core::App().settings().setSystemDarkMode(Platform::IsDarkMode()); #endif // Qt < 6.5.0 Core::App().tray().updateIconCounters(); if (_jumpList) { refreshCustomJumpList(); } break; } return false; } std::unique_ptr CreateIntegration() { return std::make_unique(); } } // namespace Platform