Skip to content

Commit

Permalink
support multiple applications in a profile
Browse files Browse the repository at this point in the history
support junctions

show process list on UI

support adding/removing applications on UI

support reordering applications

add a shortcut for 3d game mode
  • Loading branch information
eriforce committed May 15, 2023
1 parent fc40308 commit a585ab4
Show file tree
Hide file tree
Showing 39 changed files with 1,711 additions and 1,124 deletions.
4 changes: 3 additions & 1 deletion src/Magpie.App/App.idl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
#include "ProfileViewModel.idl"
#include "SettingsViewModel.idl"
#include "CandidateWindowItem.idl"
#include "NewProfileViewModel.idl"
#include "NewApplicationViewModel.idl"
#include "ProfileApplicationItem.idl"
#include "AboutViewModel.idl"
#include "MainPage.idl"
#include "AboutPage.idl"
Expand All @@ -31,6 +32,7 @@ namespace Magpie.App {
enum ShortcutAction {
Scale,
Overlay,
Is3DGameMode,
COUNT_OR_NONE
};

Expand Down
151 changes: 122 additions & 29 deletions src/Magpie.App/AppSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,23 @@ static void WriteProfile(rapidjson::PrettyWriter<rapidjson::StringBuffer>& write
if (!profile.name.empty()) {
writer.Key("name");
writer.String(StrUtils::UTF16ToUTF8(profile.name).c_str());
writer.Key("packaged");
writer.Bool(profile.isPackaged);
writer.Key("pathRule");
writer.String(StrUtils::UTF16ToUTF8(profile.pathRule).c_str());
writer.Key("classNameRule");
writer.String(StrUtils::UTF16ToUTF8(profile.classNameRule).c_str());
writer.Key("applications");
writer.StartArray();
for (const ProfileApplication& application : profile.applications) {
writer.StartObject();
writer.Key("packaged");
writer.Bool(application.isPackaged);
writer.Key("pathRule");
writer.String(StrUtils::UTF16ToUTF8(application.pathRule).c_str());
writer.Key("classNameRule");
writer.String(StrUtils::UTF16ToUTF8(application.classNameRule).c_str());
writer.Key("launchParameters");
writer.String(StrUtils::UTF16ToUTF8(application.launchParameters).c_str());
writer.EndObject();
}
writer.EndArray();
writer.Key("autoScale");
writer.Bool(profile.isAutoScale);
writer.Key("launchParameters");
writer.String(StrUtils::UTF16ToUTF8(profile.launchParameters).c_str());
}

writer.Key("scalingMode");
Expand Down Expand Up @@ -168,7 +175,7 @@ static void ShowErrorMessage(const wchar_t* mainInstruction, const wchar_t* cont
tdc.pszContent = content;
tdc.pfCallback = TaskDialogCallback;
tdc.cButtons = 1;
TASKDIALOG_BUTTON button{ IDCANCEL, exitStr.c_str()};
TASKDIALOG_BUTTON button{ IDCANCEL, exitStr.c_str() };
tdc.pButtons = &button;

TaskDialogIndirect(&tdc, nullptr, nullptr, nullptr);
Expand Down Expand Up @@ -221,7 +228,7 @@ bool AppSettings::Initialize() {
}

// 此时 ResourceLoader 使用“首选语言”

std::string configText;
if (!Win32Utils::ReadTextFile(_configPath.c_str(), configText)) {
logger.Error("读取配置文件失败");
Expand Down Expand Up @@ -279,7 +286,7 @@ bool AppSettings::Initialize() {
L"AppSettings_PortableModeUnkownConfiguration_Exit");
if (!ShowOkCancelWarningMessage(nullptr,
contentStr.c_str(), continueStr.c_str(), exitStr.c_str())
) {
) {
return false;
}
} else {
Expand All @@ -291,7 +298,7 @@ bool AppSettings::Initialize() {
L"AppSettings_UnkownConfiguration_EnablePortableMode");
if (!ShowOkCancelWarningMessage(nullptr,
contentStr.c_str(), continueStr.c_str(), enablePortableModeStr.c_str())
) {
) {
IsPortableMode(true);
_SetDefaultScalingModes();
_SetDefaultShortcuts();
Expand Down Expand Up @@ -488,6 +495,8 @@ bool AppSettings::_Save(const _AppSettingsData& data) noexcept {
writer.Uint(EncodeShortcut(data._shortcuts[(size_t)ShortcutAction::Scale]));
writer.Key("overlay");
writer.Uint(EncodeShortcut(data._shortcuts[(size_t)ShortcutAction::Overlay]));
writer.Key("3DGameMode");
writer.Uint(EncodeShortcut(data._shortcuts[(size_t)ShortcutAction::Is3DGameMode]));
writer.EndObject();

writer.Key("autoRestore");
Expand Down Expand Up @@ -612,7 +621,7 @@ void AppSettings::_LoadSettings(const rapidjson::GenericObject<true, rapidjson::
auto shortcutsNode = root.FindMember("shortcuts");
if (shortcutsNode == root.MemberEnd()) {
// v0.10.0-preview1 使用 hotkeys
shortcutsNode= root.FindMember("hotkeys");
shortcutsNode = root.FindMember("hotkeys");
}
if (shortcutsNode != root.MemberEnd() && shortcutsNode->value.IsObject()) {
const auto& shortcutsObj = shortcutsNode->value.GetObj();
Expand All @@ -626,6 +635,11 @@ void AppSettings::_LoadSettings(const rapidjson::GenericObject<true, rapidjson::
if (overlayNode != shortcutsObj.MemberEnd() && overlayNode->value.IsUint()) {
DecodeShortcut(overlayNode->value.GetUint(), _shortcuts[(size_t)ShortcutAction::Overlay]);
}

auto is3DGameModeNode = shortcutsObj.FindMember("3DGameMode");
if (is3DGameModeNode != shortcutsObj.MemberEnd() && is3DGameModeNode->value.IsUint()) {
DecodeShortcut(is3DGameModeNode->value.GetUint(), _shortcuts[(size_t)ShortcutAction::Is3DGameMode]);
}
}

JsonHelper::ReadBool(root, "autoRestore", _isAutoRestore);
Expand Down Expand Up @@ -733,22 +747,35 @@ bool AppSettings::_LoadProfile(
}
}

if (!JsonHelper::ReadBool(profileObj, "packaged", profile.isPackaged, true)) {
return false;
}
auto applicationsNode = profileObj.FindMember("applications");
if (applicationsNode != profileObj.MemberEnd() && applicationsNode->value.IsArray()) {
const auto& applicationsArray = applicationsNode->value.GetArray();

if (!JsonHelper::ReadString(profileObj, "pathRule", profile.pathRule, true)
|| profile.pathRule.empty()) {
return false;
}
const rapidjson::SizeType size = applicationsArray.Size();
if (size > 0) {
profile.applications.reserve((size_t)size);
for (rapidjson::SizeType i = 0; i < size; ++i) {
if (!applicationsArray[i].IsObject()) {
continue;
}

if (!JsonHelper::ReadString(profileObj, "classNameRule", profile.classNameRule, true)
|| profile.classNameRule.empty()) {
return false;
ProfileApplication& application = profile.applications.emplace_back();
if (!_LoadProfileApplication(applicationsArray[i].GetObj(), application)) {
profile.applications.pop_back();
continue;
}
}
}
} else {
// v0.10.0 的程序配置直接在Profile下
ProfileApplication& application = profile.applications.emplace_back();

if (!_LoadProfileApplication(profileObj, application)) {
return false;
}
}

JsonHelper::ReadBool(profileObj, "autoScale", profile.isAutoScale);
JsonHelper::ReadString(profileObj, "launchParameters", profile.launchParameters);
}

JsonHelper::ReadInt(profileObj, "scalingMode", profile.scalingMode);
Expand All @@ -762,7 +789,7 @@ bool AppSettings::_LoadProfile(
// v0.10.0-preview1 使用 captureMode
JsonHelper::ReadUInt(profileObj, "captureMode", captureMethod);
}

if (captureMethod > 3) {
captureMethod = (uint32_t)CaptureMethod::GraphicsCapture;
} else if (captureMethod == (uint32_t)CaptureMethod::DesktopDuplication) {
Expand All @@ -782,7 +809,7 @@ bool AppSettings::_LoadProfile(
}
profile.multiMonitorUsage = (MultiMonitorUsage)multiMonitorUsage;
}

if (!JsonHelper::ReadInt(profileObj, "graphicsCard", profile.graphicsCard, true)) {
// v0.10.0-preview1 使用 graphicsAdapter
uint32_t graphicsAdater = 0;
Expand All @@ -791,7 +818,6 @@ bool AppSettings::_LoadProfile(
}

JsonHelper::ReadBoolFlag(profileObj, "disableWindowResizing", MagFlags::DisableWindowResizing, profile.flags);
JsonHelper::ReadBoolFlag(profileObj, "3DGameMode", MagFlags::Is3DGameMode, profile.flags);
JsonHelper::ReadBoolFlag(profileObj, "showFPS", MagFlags::ShowFPS, profile.flags);
JsonHelper::ReadBoolFlag(profileObj, "VSync", MagFlags::VSync, profile.flags);
JsonHelper::ReadBoolFlag(profileObj, "tripleBuffering", MagFlags::TripleBuffering, profile.flags);
Expand All @@ -811,7 +837,7 @@ bool AppSettings::_LoadProfile(
}
profile.cursorScaling = (CursorScaling)cursorScaling;
}

JsonHelper::ReadFloat(profileObj, "customCursorScaling", profile.customCursorScaling);
if (profile.customCursorScaling < 0) {
profile.customCursorScaling = 1.0f;
Expand Down Expand Up @@ -840,14 +866,72 @@ bool AppSettings::_LoadProfile(
|| profile.cropping.Right < 0
|| !JsonHelper::ReadFloat(croppingObj, "bottom", profile.cropping.Bottom, true)
|| profile.cropping.Bottom < 0
) {
) {
profile.cropping = {};
}
}

return true;
}

bool AppSettings::_LoadProfileApplication(
const rapidjson::GenericObject<true, rapidjson::Value>& applicationObj,
ProfileApplication& application
) {
if (!JsonHelper::ReadBool(applicationObj, "packaged", application.isPackaged, true)) {
return false;
}

if (!JsonHelper::ReadString(applicationObj, "pathRule", application.pathRule, true)
|| application.pathRule.empty()) {
return false;
}

if (!JsonHelper::ReadString(applicationObj, "classNameRule", application.classNameRule, true)
|| application.classNameRule.empty()) {
return false;
}

JsonHelper::ReadString(applicationObj, "launchParameters", application.launchParameters);

if (!application.isPackaged) {
_SetTruePath(application);
}

return true;
}

fire_and_forget AppSettings::_SetTruePath(ProfileApplication& application) {
HANDLE handle = CreateFile(
application.pathRule.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);

if (handle == INVALID_HANDLE_VALUE) {
co_return;
}

TCHAR path[MAX_PATH];
DWORD length = GetFinalPathNameByHandle(
handle,
path,
MAX_PATH,
0
);

if (length > 0) {
// Skip `\\?\` prefix
application.truePath = &path[4];
}

CloseHandle(handle);
}

bool AppSettings::_SetDefaultShortcuts() {
bool changed = false;

Expand All @@ -869,6 +953,15 @@ bool AppSettings::_SetDefaultShortcuts() {
changed = true;
}

Shortcut& is3DGameModeShortcut = _shortcuts[(size_t)ShortcutAction::Is3DGameMode];
if (is3DGameModeShortcut.IsEmpty()) {
is3DGameModeShortcut.win = true;
is3DGameModeShortcut.shift = true;
is3DGameModeShortcut.code = 'E';

changed = true;
}

return changed;
}

Expand Down
7 changes: 6 additions & 1 deletion src/Magpie.App/AppSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct _AppSettingsData {

// 上一次自动检查更新的日期
std::chrono::system_clock::time_point _updateCheckDate;

bool _isPortableMode = false;
bool _isAlwaysRunAsAdmin = false;
bool _isDebugMode = false;
Expand Down Expand Up @@ -337,6 +337,11 @@ class AppSettings : private _AppSettingsData {
Profile& profile,
bool isDefault = false
);
bool _LoadProfileApplication(
const rapidjson::GenericObject<true, rapidjson::Value>& applicationObj,
ProfileApplication& application
);
fire_and_forget _SetTruePath(ProfileApplication& application);
bool _SetDefaultShortcuts();
void _SetDefaultScalingModes();

Expand Down
Loading

0 comments on commit a585ab4

Please sign in to comment.