Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/UWP/UWPHelpers/LaunchItem.cpp
5650 views
1
// Copyright (c) 2023- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include "pch.h"
19
#include <io.h>
20
#include <fcntl.h>
21
#include <regex>
22
#include <thread>
23
24
#include "LaunchItem.h"
25
#include "StorageAccess.h"
26
27
#include "Common/Log.h"
28
#include "Common/System/System.h"
29
#include "Common/File/Path.h"
30
#include "UWPUtil.h"
31
32
#include <ppl.h>
33
#include <ppltasks.h>
34
35
using namespace winrt;
36
using namespace winrt::Windows::Storage;
37
using namespace winrt::Windows::Foundation;
38
using namespace winrt::Windows::ApplicationModel::Activation;
39
40
#pragma region LaunchItemClass
41
class LaunchItem {
42
public:
43
LaunchItem() {
44
}
45
46
~LaunchItem() {
47
}
48
49
void Activate(const IStorageFile& file) {
50
storageFile = file;
51
AddItemToFutureList(storageFile);
52
launchPath = std::string();
53
launchOnExit = std::string();
54
}
55
56
void Activate(const ProtocolActivatedEventArgs& args) {
57
try {
58
unsigned i;
59
auto query = args.Uri().QueryParsed();
60
61
for (i = 0; i < query.Size(); i++)
62
{
63
auto arg = query.GetAt(i);
64
65
if (arg.Name() == L"cmd")
66
{
67
auto command = FromHString(arg.Value());
68
DEBUG_LOG(Log::FileSystem, "Launch command %s", command.c_str());
69
70
std::regex rgx("\"(.+[^\\\\/]+)\"");
71
std::smatch match;
72
73
if (std::regex_search(command, match, rgx)) {
74
try
75
{
76
launchPath = match[1];
77
}
78
catch (...) {
79
launchPath = match[0];
80
}
81
DEBUG_LOG(Log::FileSystem, "Launch target %s", launchPath.c_str());
82
}
83
}
84
else if (arg.Name() == L"launchOnExit") {
85
launchOnExit = FromHString(arg.Value());
86
DEBUG_LOG(Log::FileSystem, "On exit URI %s", launchOnExit.c_str());
87
}
88
}
89
}
90
catch (...) {
91
92
}
93
storageFile = nullptr;
94
}
95
96
void Start() {
97
if (IsValid()) {
98
std::thread([this] {
99
SetState(true);
100
std::string path = GetFilePath();
101
// Delay to be able to launch on startup too
102
std::this_thread::sleep_for(std::chrono::milliseconds(100));
103
System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, path);
104
}).detach();
105
}
106
}
107
108
bool IsHandled() {
109
return handled;
110
}
111
void SetState(bool fileHandled) {
112
handled = fileHandled;
113
}
114
115
bool IsValid() {
116
return storageFile != nullptr || !launchPath.empty();
117
}
118
119
std::string GetFilePath() {
120
std::string path = launchPath;
121
if (storageFile != nullptr) {
122
path = FromHString(storageFile.Path());
123
}
124
return path;
125
}
126
127
void Close(bool callLaunchOnExit) {
128
storageFile = nullptr;
129
launchPath = std::string();
130
handled = false;
131
132
if (!launchOnExit.empty()) {
133
if (callLaunchOnExit) {
134
DEBUG_LOG(Log::FileSystem, "Calling back %s", launchOnExit.c_str());
135
auto uri = winrt::Windows::Foundation::Uri(ToHString(launchOnExit));
136
winrt::Windows::System::Launcher::LaunchUriAsync(uri);
137
}
138
else {
139
DEBUG_LOG(Log::FileSystem, "Ignoring callback %s, due to callLaunchOnExit is false", launchOnExit.c_str());
140
}
141
}
142
launchOnExit = std::string();
143
}
144
145
private:
146
IStorageFile storageFile = nullptr;
147
std::string launchPath;
148
std::string launchOnExit;
149
bool handled = false;
150
};
151
#pragma endregion
152
153
LaunchItem launchItemHandler;
154
void DetectLaunchItem(const IActivatedEventArgs& activateArgs, bool onlyActivate) {
155
if (activateArgs != nullptr) {
156
if (!launchItemHandler.IsHandled()) {
157
if (activateArgs.Kind() == ActivationKind::File) {
158
auto fileArgs = activateArgs.try_as<FileActivatedEventArgs>();
159
if (fileArgs) {
160
auto file = fileArgs.Files().GetAt(0).try_as<StorageFile>();
161
if (file) {
162
launchItemHandler.Activate(file);
163
}
164
}
165
}
166
else if (activateArgs.Kind() == ActivationKind::Protocol)
167
{
168
auto protocolArgs = activateArgs.try_as<ProtocolActivatedEventArgs>();
169
if (protocolArgs) {
170
launchItemHandler.Activate(protocolArgs);
171
}
172
}
173
if (!onlyActivate) {
174
launchItemHandler.Start();
175
}
176
}
177
}
178
}
179
180
std::string GetLaunchItemPath(const IActivatedEventArgs& activateArgs) {
181
DetectLaunchItem(activateArgs, true); // Just activate
182
if (launchItemHandler.IsValid()) {
183
// Expected that 'GetLaunchItemPath' called to handle startup item
184
// it should be marked as handled by default
185
launchItemHandler.SetState(true);
186
}
187
return launchItemHandler.GetFilePath();
188
}
189
190
void CloseLaunchItem(bool launchOnExit) {
191
if (launchItemHandler.IsValid() && launchItemHandler.IsHandled()) {
192
launchItemHandler.Close(launchOnExit);
193
}
194
}
195
196