Skip to content

Commit

Permalink
feat: 缩放前自动修复触控支持
Browse files Browse the repository at this point in the history
  • Loading branch information
Blinue committed May 8, 2024
1 parent 2b73385 commit 6eae9b7
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 80 deletions.
46 changes: 5 additions & 41 deletions src/Magpie.App/HomeViewModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "StrUtils.h"
#include "UpdateService.h"
#include "CommonSharedConstants.h"
#include "Logger.h"
#include "TouchHelper.h"

namespace winrt::Magpie::App::implementation {

Expand Down Expand Up @@ -187,33 +187,12 @@ void HomeViewModel::RemindMeLater() {
}

bool HomeViewModel::IsTouchSupportEnabled() const noexcept {
wil::unique_cotaskmem_string system32Dir;
HRESULT hr = SHGetKnownFolderPath(
FOLDERID_System, KF_FLAG_DEFAULT, NULL, system32Dir.put());
if (FAILED(hr)) {
Logger::Get().ComError("SHGetKnownFolderPath 失败", hr);
return false;
}

std::wstring path = StrUtils::Concat(system32Dir.get(),
L"\\Magpie\\", CommonSharedConstants::TOUCH_HELPER_EXE_NAME);
if (!Win32Utils::FileExists(path.c_str())) {
return false;
}

path += L".ver";

std::vector<uint8_t> version;
if (!Win32Utils::ReadFile(path.c_str(), version) || version.size() != 4) {
Logger::Get().Error("读取版本号失败");
return false;
}

return *(uint32_t*)version.data() == CommonSharedConstants::TOUCH_HELPER_VERSION;
// 不检查版本号是否匹配
return TouchHelper::IsTouchSupportEnabled();
}

fire_and_forget HomeViewModel::IsTouchSupportEnabled(bool value) {
if (IsTouchSupportEnabled() == value) {
if (TouchHelper::IsTouchSupportEnabled() == value) {
co_return;
}

Expand All @@ -224,22 +203,7 @@ fire_and_forget HomeViewModel::IsTouchSupportEnabled(bool value) {
// 见 https://github.com/microsoft/microsoft-ui-xaml/issues/4952
co_await resume_background();

SHELLEXECUTEINFO execInfo{
.cbSize = sizeof(execInfo),
.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS,
.lpVerb = L"runas",
.lpFile = Win32Utils::GetExePath().c_str(),
.lpParameters = value ? L" -r" : L" -ur"
};

if (ShellExecuteEx(&execInfo)) {
wil::unique_process_handle hProcess(execInfo.hProcess);
if (hProcess) {
wil::handle_wait(hProcess.get());
}
} else if (GetLastError() != ERROR_CANCELLED) {
Logger::Get().Win32Error("ShellExecuteEx 失败");
}
TouchHelper::IsTouchSupportEnabled(value);

co_await dispatcher;

Expand Down
2 changes: 1 addition & 1 deletion src/Magpie.App/Resources.language-en-US.resw
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@
<data name="Home_TouchSupport.Header" xml:space="preserve">
<value>Touch support</value>
</data>
<data name="Home_TouchSupport_InfoBar.Message" xml:space="preserve">
<data name="Home_TouchSupport_InfoBar.Title" xml:space="preserve">
<value>If touch support fails, Magpie may request administrator privileges before scaling to perform repairs.</value>
</data>
</root>
2 changes: 1 addition & 1 deletion src/Magpie.App/Resources.language-zh-Hans.resw
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@
<data name="Home_TouchSupport.Header" xml:space="preserve">
<value>触控支持</value>
</data>
<data name="Home_TouchSupport_InfoBar.Message" xml:space="preserve">
<data name="Home_TouchSupport_InfoBar.Title" xml:space="preserve">
<value>如果触控支持失效,Magpie 可能会在缩放前请求管理员权限以执行修复。</value>
</data>
</root>
38 changes: 2 additions & 36 deletions src/Magpie.App/ScalingService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
#include "Logger.h"
#include "EffectsService.h"
#include <Magpie.Core.h>
#include "CommonSharedConstants.h"
#include "StrUtils.h"
#include "TouchHelper.h"

using namespace ::Magpie::Core;
using namespace winrt;
Expand Down Expand Up @@ -224,39 +223,6 @@ fire_and_forget ScalingService::_ScalingRuntime_IsRunningChanged(bool isRunning)
IsRunningChanged.Invoke(isRunning);
}

static void TryLaunchTouchHelper() noexcept {
wil::unique_cotaskmem_string system32Dir;
HRESULT hr = SHGetKnownFolderPath(
FOLDERID_System, KF_FLAG_DEFAULT, NULL, system32Dir.put());
if (FAILED(hr)) {
Logger::Get().ComError("SHGetKnownFolderPath 失败", hr);
return;
}

std::wstring path = StrUtils::Concat(system32Dir.get(),
L"\\Magpie\\", CommonSharedConstants::TOUCH_HELPER_EXE_NAME);
if (!Win32Utils::FileExists(path.c_str())) {
// 未启用触控支持
return;
}

wil::unique_mutex_nothrow hSingleInstanceMutex;

bool alreadyExists = false;
if (hSingleInstanceMutex.try_create(
CommonSharedConstants::TOUCH_HELPER_SINGLE_INSTANCE_MUTEX_NAME,
CREATE_MUTEX_INITIAL_OWNER,
MUTEX_ALL_ACCESS,
nullptr,
&alreadyExists
) && !alreadyExists) {
hSingleInstanceMutex.ReleaseMutex();

// TouchHelper 未在运行则启动它
Win32Utils::ShellOpen(path.c_str());
}
}

bool ScalingService::_StartScale(HWND hWnd, const Profile& profile) {
if (profile.scalingMode < 0) {
return false;
Expand All @@ -275,7 +241,7 @@ bool ScalingService::_StartScale(HWND hWnd, const Profile& profile) {
}
}

TryLaunchTouchHelper();
TouchHelper::TryLaunchTouchHelper();

options.graphicsCard = profile.graphicsCard;
options.captureMethod = profile.captureMethod;
Expand Down
96 changes: 95 additions & 1 deletion src/Magpie.App/TouchHelper.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,107 @@
#include "pch.h"
#include "TouchHelper.h"
#include "Logger.h"
#include "StrUtils.h"
#include "Win32Utils.h"
#include "CommonSharedConstants.h"

namespace winrt::Magpie::App {

static std::wstring GetTouchHelperPath() noexcept {
wil::unique_cotaskmem_string system32Dir;
HRESULT hr = SHGetKnownFolderPath(
FOLDERID_System, KF_FLAG_DEFAULT, NULL, system32Dir.put());
if (FAILED(hr)) {
Logger::Get().ComError("SHGetKnownFolderPath 失败", hr);
return {};
}

return StrUtils::Concat(system32Dir.get(),
L"\\Magpie\\", CommonSharedConstants::TOUCH_HELPER_EXE_NAME);
}

bool TouchHelper::IsTouchSupportEnabled() noexcept {
return false;
// 不检查版本号
return Win32Utils::FileExists(GetTouchHelperPath().c_str());
}

void TouchHelper::IsTouchSupportEnabled(bool value) noexcept {
SHELLEXECUTEINFO execInfo{
.cbSize = sizeof(execInfo),
.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS,
.lpVerb = L"runas",
.lpFile = Win32Utils::GetExePath().c_str(),
.lpParameters = value ? L" -r" : L" -ur"
};

if (ShellExecuteEx(&execInfo)) {
wil::unique_process_handle hProcess(execInfo.hProcess);
if (hProcess) {
wil::handle_wait(hProcess.get());
}
} else if (GetLastError() != ERROR_CANCELLED) {
Logger::Get().Win32Error("ShellExecuteEx 失败");
}
}

static bool CheckAndFixTouchHelper(std::wstring& path) noexcept {
// 检查版本号
path += L".ver";

std::vector<uint8_t> versionData;

const auto checkVersion = [&]() {
if (!Win32Utils::ReadFile(path.c_str(), versionData)) {
Logger::Get().Error("读取版本号失败");
}

return versionData.size() == 4 &&
*(uint32_t*)versionData.data() == CommonSharedConstants::TOUCH_HELPER_VERSION;
};

if (!checkVersion()) {
// 版本号不匹配,尝试修复,这会请求管理员权限
TouchHelper::IsTouchSupportEnabled(true);

if (!checkVersion()) {
// 修复失败
return false;
}
}

path.erase(path.size() - 4);
return true;
}

void TouchHelper::TryLaunchTouchHelper() noexcept {
std::wstring path = GetTouchHelperPath();
if (!Win32Utils::FileExists(path.c_str())) {
// 未启用触控支持
return;
}

wil::unique_mutex_nothrow hSingleInstanceMutex;

bool alreadyExists = false;
if (hSingleInstanceMutex.try_create(
CommonSharedConstants::TOUCH_HELPER_SINGLE_INSTANCE_MUTEX_NAME,
CREATE_MUTEX_INITIAL_OWNER,
MUTEX_ALL_ACCESS,
nullptr,
&alreadyExists
) && !alreadyExists) {
hSingleInstanceMutex.ReleaseMutex();

// TouchHelper 未在运行则启动它

// 检查版本是否匹配并尝试修复
if (!CheckAndFixTouchHelper(path)) {
// 修复失败
return;
}

Win32Utils::ShellOpen(path.c_str());
}
}

}
1 change: 1 addition & 0 deletions src/Magpie.App/TouchHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace winrt::Magpie::App {
struct TouchHelper {
static bool IsTouchSupportEnabled() noexcept;
static void IsTouchSupportEnabled(bool value) noexcept;
static void TryLaunchTouchHelper() noexcept;
};

}

0 comments on commit 6eae9b7

Please sign in to comment.