CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/UWP/UWPHelpers/LaunchItem.cpp
Views: 1401
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
23
#include "LaunchItem.h"
24
#include "StorageAccess.h"
25
26
#include "Common/Log.h"
27
#include "Common/System/System.h"
28
#include "Common/File/Path.h"
29
#include "UWPUtil.h"
30
31
#include <ppl.h>
32
#include <ppltasks.h>
33
34
#pragma region LaunchItemClass
35
class LaunchItem {
36
public:
37
LaunchItem() {
38
}
39
40
~LaunchItem() {
41
delete storageFile;
42
}
43
44
void Activate(IStorageFile^ file) {
45
storageFile = file;
46
AddItemToFutureList(storageFile);
47
launchPath = std::string();
48
launchOnExit = std::string();
49
}
50
51
void Activate(ProtocolActivatedEventArgs^ args) {
52
try {
53
unsigned i;
54
Windows::Foundation::WwwFormUrlDecoder^ query = args->Uri->QueryParsed;
55
56
for (i = 0; i < query->Size; i++)
57
{
58
IWwwFormUrlDecoderEntry^ arg = query->GetAt(i);
59
60
if (arg->Name == "cmd")
61
{
62
auto command = FromPlatformString(arg->Value);
63
DEBUG_LOG(Log::FileSystem, "Launch command %s", command.c_str());
64
65
std::regex rgx("\"(.+[^\\/]+)\"");
66
std::smatch match;
67
68
if (std::regex_search(command, match, rgx)) {
69
try
70
{
71
launchPath = match[1];
72
}
73
catch (...) {
74
launchPath = match[0];
75
}
76
DEBUG_LOG(Log::FileSystem, "Launch target %s", launchPath.c_str());
77
}
78
}
79
else if (arg->Name == "launchOnExit") {
80
launchOnExit = FromPlatformString(arg->Value);
81
DEBUG_LOG(Log::FileSystem, "On exit URI %s", launchOnExit.c_str());
82
}
83
}
84
}
85
catch (...) {
86
87
}
88
storageFile = nullptr;
89
}
90
91
void Start() {
92
if (IsValid()) {
93
concurrency::create_task([&] {
94
SetState(true);
95
std::string path = GetFilePath();
96
// Delay to be able to launch on startup too
97
std::this_thread::sleep_for(std::chrono::milliseconds(100));
98
System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, path);
99
});
100
}
101
}
102
103
bool IsHandled() {
104
return handled;
105
}
106
void SetState(bool fileHandled) {
107
handled = fileHandled;
108
}
109
110
bool IsValid() {
111
return storageFile != nullptr || !launchPath.empty();
112
}
113
114
std::string GetFilePath() {
115
std::string path = launchPath;
116
if (storageFile != nullptr) {
117
path = FromPlatformString(storageFile->Path);
118
}
119
return path;
120
}
121
122
void Close(bool callLaunchOnExit) {
123
storageFile = nullptr;
124
launchPath = std::string();
125
handled = false;
126
127
if (!launchOnExit.empty()) {
128
if (callLaunchOnExit) {
129
DEBUG_LOG(Log::FileSystem, "Calling back %s", launchOnExit.c_str());
130
auto uri = ref new Windows::Foundation::Uri(ToPlatformString(launchOnExit));
131
Windows::System::Launcher::LaunchUriAsync(uri);
132
}
133
else {
134
DEBUG_LOG(Log::FileSystem, "Ignoring callback %s, due to callLaunchOnExit is false", launchOnExit.c_str());
135
}
136
}
137
launchOnExit = std::string();
138
}
139
140
private:
141
IStorageFile^ storageFile;
142
std::string launchPath;
143
std::string launchOnExit;
144
bool handled = false;
145
};
146
#pragma endregion
147
148
LaunchItem launchItemHandler;
149
void DetectLaunchItem(IActivatedEventArgs^ activateArgs, bool onlyActivate) {
150
if (activateArgs != nullptr) {
151
if (!launchItemHandler.IsHandled()) {
152
if (activateArgs->Kind == ActivationKind::File) {
153
FileActivatedEventArgs^ fileArgs = dynamic_cast<FileActivatedEventArgs^>(activateArgs);
154
launchItemHandler.Activate((StorageFile^)fileArgs->Files->GetAt(0));
155
}
156
else if (activateArgs->Kind == ActivationKind::Protocol)
157
{
158
ProtocolActivatedEventArgs^ protocolArgs = dynamic_cast<ProtocolActivatedEventArgs^>(activateArgs);
159
launchItemHandler.Activate(protocolArgs);
160
}
161
if (!onlyActivate) {
162
launchItemHandler.Start();
163
}
164
}
165
}
166
}
167
168
std::string GetLaunchItemPath(IActivatedEventArgs^ activateArgs) {
169
DetectLaunchItem(activateArgs, true); // Just activate
170
if (launchItemHandler.IsValid()) {
171
// Expected that 'GetLaunchItemPath' called to handle startup item
172
// it should be marked as handled by default
173
launchItemHandler.SetState(true);
174
}
175
return launchItemHandler.GetFilePath();
176
}
177
178
void CloseLaunchItem(bool launchOnExit) {
179
if (launchItemHandler.IsValid() && launchItemHandler.IsHandled()) {
180
launchItemHandler.Close(launchOnExit);
181
}
182
}
183
184