Resolve launch item and conflicts

- Better handling for launch items
- Resolved code conflicts
This commit is contained in:
Bashar Astifan 2023-08-14 07:46:14 +04:00
parent 07c119a80c
commit c9b3d8aedf
7 changed files with 228 additions and 142 deletions

View file

@ -216,7 +216,6 @@ void App::Uninitialize() {
}
// Application lifecycle event handlers.
extern LaunchItem launchItem;
void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) {
// Run() won't start until the CoreWindow is activated.
CoreWindow::GetForCurrentThread()->Activate();
@ -227,15 +226,8 @@ void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^
if (g_Config.UseFullScreen())
Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->TryEnterFullScreenMode();
if (args->Kind == ActivationKind::File) {
FileActivatedEventArgs^ protocolArgs = dynamic_cast<Windows::ApplicationModel::Activation::FileActivatedEventArgs^>(args);
launchItem = LaunchItem((StorageFile^)protocolArgs->Files->GetAt(0));
}
if (args->Kind == ActivationKind::Protocol)
{
ProtocolActivatedEventArgs^ protocolArgs = dynamic_cast<Windows::ApplicationModel::Activation::ProtocolActivatedEventArgs^>(args);
launchItem = LaunchItem(protocolArgs);
}
//Detect if app started or activated by launch item (file, uri)
DetectLaunchItem(args);
}
void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {

View file

@ -57,9 +57,6 @@ PPSSPP_UWPMain *g_main;
extern WindowsAudioBackend *winAudioBackend;
std::string langRegion;
std::list<std::unique_ptr<InputDevice>> g_input;
// This item will be assigned by 'App.cpp' at 'App::OnActivated'
LaunchItem launchItem;
// TODO: Use Microsoft::WRL::ComPtr<> for D3D11 objects?
// TODO: See https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/WindowsAudioSession for WASAPI with UWP
@ -126,22 +123,29 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResourc
bool debugLogLevel = false;
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
if (debugLogLevel) {
LogManager::GetInstance()->SetAllLogLevels(LogTypes::LDEBUG);
}
const char *argv[2] = { "fake", nullptr };
std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data());
NativeInit(1, argv, "", "", cacheFolder.c_str());
// Set log file location
if (g_Config.bEnableLogging) {
LogManager::GetInstance()->ChangeFileLog(GetLogFile().c_str());
}
const char *argv[2] = { "fake", nullptr };
int argc = 1;
std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data());
// 'PPSSPP_UWPMain' is getting called before 'OnActivated'
// this make detecting launch items on startup hard
// I think 'Init' process must be moved out and invoked from 'OnActivated' one time only
// currently launchItem will work fine but we cannot skip logo screen
// we should pass file path to 'argv' using 'GetLaunchItemPath(args)'
// instead of depending on 'boot_filename' (LaunchItem.cpp)
NativeInit(argc, argv, "", "", cacheFolder.c_str());
NativeInitGraphics(ctx_.get());
NativeResized();
@ -179,15 +183,6 @@ void PPSSPP_UWPMain::CreateWindowSizeDependentResources() {
ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, m_deviceResources->GetBackBufferRenderTargetView());
}
void PPSSPP_UWPMain::BootToLaunchFile() {
if (launchItem.IsValid() && !launchItem.IsHandled()) {
launchItem.SetState(true);
std::string path = launchItem.GetFilePath();
if (!path.empty()) {
System_PostUIMessage("boot", path.c_str());
}
}
}
// Renders the current frame according to the current application state.
// Returns true if the frame was rendered and is ready to be displayed.
bool PPSSPP_UWPMain::Render() {
@ -577,9 +572,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
case SystemRequestType::NOTIFY_UI_STATE:
{
if (!param1.empty() && !strcmp(param1.c_str(), "menu")) {
if (launchItem.IsValid() && launchItem.IsHandled()) {
launchItem.Close();
}
CloseLaunchItem();
}
return true;
}

View file

@ -35,7 +35,6 @@ public:
PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResources>& deviceResources);
~PPSSPP_UWPMain();
void CreateWindowSizeDependentResources();
void BootToLaunchFile();
bool Render();
// IDeviceNotify

View file

@ -89,7 +89,7 @@
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
<AppxBundle>Never</AppxBundle>
<PackageCertificateThumbprint>C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA</PackageCertificateThumbprint>
<PackageCertificateThumbprint>C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA</PackageCertificateThumbprint>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppInstallerUpdateFrequency>0</AppInstallerUpdateFrequency>
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
@ -468,6 +468,7 @@
<ClInclude Include="UWPHelpers\StorageAsync.h" />
<ClInclude Include="UWPHelpers\StorageManager.h" />
<ClInclude Include="UWPHelpers\StoragePickers.h" />
<ClInclude Include="UWPHelpers\LaunchItem.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\git-version.cpp">
@ -479,11 +480,11 @@
<ClCompile Include="Common\DeviceResources.cpp" />
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
<ClCompile Include="PPSSPP_UWPMain.cpp" />
<ClCompile Include="UWPHelpers\LaunchItem.h" />
<ClCompile Include="UWPHelpers\StorageAccess.cpp" />
<ClCompile Include="UWPHelpers\StorageAsync.cpp" />
<ClCompile Include="UWPHelpers\StorageManager.cpp" />
<ClCompile Include="UWPHelpers\StoragePickers.cpp" />
<ClCompile Include="UWPHelpers\LaunchItem.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
@ -980,4 +981,4 @@
<Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\MeshContentTask.targets" />
<Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\ShaderGraphContentTask.targets" />
</ImportGroup>
</Project>
</Project>

View file

@ -120,7 +120,10 @@
<ClCompile Include="..\Windows\InputDevice.cpp">
<Filter>Input</Filter>
</ClCompile>
<ClCompile Include="UWPHelpers\LaunchItem.h">
<ClInclude Include="UWPHelpers\LaunchItem.h">
<Filter>UWPHelpers</Filter>
</ClInclude>
<ClCompile Include="UWPHelpers\LaunchItem.cpp">
<Filter>UWPHelpers</Filter>
</ClCompile>
</ItemGroup>
@ -613,4 +616,4 @@
<Filter>Content</Filter>
</Font>
</ItemGroup>
</Project>
</Project>

View file

@ -0,0 +1,185 @@
// Copyright (c) 2023- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include "pch.h"
#include <io.h>
#include <fcntl.h>
#include <regex>
#include "LaunchItem.h"
#include "Common/Log.h"
#include <Common/System/System.h>
#include <Common/File/Path.h>
#include "UWPUtil.h"
extern void AddItemToFutureList(IStorageItem^ item);
// Temporary to handle startup items
// See remarks at 'PPSSPP_UWPMain.cpp', above 'NativeInit(..)'
extern Path boot_filename;
#pragma region LaunchItemClass
class LaunchItem {
public:
LaunchItem() {
}
~LaunchItem() {
delete storageFile;
}
void Activate(IStorageFile^ file) {
storageFile = file;
AddItemToFutureList(storageFile);
launchPath = std::string();
launchOnExit = std::string();
}
void Activate(ProtocolActivatedEventArgs^ args) {
try {
unsigned i;
Windows::Foundation::WwwFormUrlDecoder^ query = args->Uri->QueryParsed;
for (i = 0; i < query->Size; i++)
{
IWwwFormUrlDecoderEntry^ arg = query->GetAt(i);
if (arg->Name == "cmd")
{
auto command = FromPlatformString(arg->Value);
DEBUG_LOG(FILESYS, "Launch command %s", command.c_str());
std::regex rgx("\"(.+[^\\/]+)\"");
std::smatch match;
if (std::regex_search(command, match, rgx)) {
try
{
launchPath = match[1];
}
catch (...) {
launchPath = match[0];
}
DEBUG_LOG(FILESYS, "Launch target %s", launchPath.c_str());
}
}
else if (arg->Name == "launchOnExit") {
launchOnExit = FromPlatformString(arg->Value);
DEBUG_LOG(FILESYS, "On exit URI %s", launchOnExit.c_str());
}
}
}
catch (...) {
}
storageFile = nullptr;
}
void Start() {
if (IsValid()) {
SetState(true);
std::string path = GetFilePath();
System_PostUIMessage("boot", path.c_str());
boot_filename = Path(path); // Temporary to handle startup items
}
}
bool IsHandled() {
return handled;
}
void SetState(bool fileHandled) {
handled = fileHandled;
}
bool IsValid() {
return storageFile != nullptr || !launchPath.empty();
}
std::string GetFilePath() {
std::string path = launchPath;
if (storageFile != nullptr) {
path = FromPlatformString(storageFile->Path);
}
return path;
}
void Close(bool callLaunchOnExit) {
storageFile = nullptr;
launchPath = std::string();
handled = false;
if (!launchOnExit.empty()) {
if (callLaunchOnExit) {
DEBUG_LOG(FILESYS, "Calling back %s", launchOnExit.c_str());
auto uri = ref new Windows::Foundation::Uri(ToPlatformString(launchOnExit));
Windows::System::Launcher::LaunchUriAsync(uri);
}
else {
DEBUG_LOG(FILESYS, "Ignoring callback %s, due to callLaunchOnExit is false", launchOnExit.c_str());
}
}
launchOnExit = std::string();
boot_filename.clear(); // Temporary to handle startup items
}
private:
IStorageFile^ storageFile;
std::string launchPath;
std::string launchOnExit;
bool handled = false;
};
#pragma endregion
LaunchItem launchItemHandler;
void DetectLaunchItem(IActivatedEventArgs^ activateArgs, bool onlyActivate) {
if (activateArgs != nullptr) {
if (!launchItemHandler.IsHandled()) {
if (activateArgs->Kind == ActivationKind::File) {
FileActivatedEventArgs^ fileArgs = dynamic_cast<FileActivatedEventArgs^>(activateArgs);
launchItemHandler.Activate((StorageFile^)fileArgs->Files->GetAt(0));
}
else if (activateArgs->Kind == ActivationKind::Protocol)
{
ProtocolActivatedEventArgs^ protocolArgs = dynamic_cast<ProtocolActivatedEventArgs^>(activateArgs);
launchItemHandler.Activate(protocolArgs);
}
if (!onlyActivate) {
launchItemHandler.Start();
}
}
}
}
std::string GetLaunchItemPath(IActivatedEventArgs^ activateArgs) {
DetectLaunchItem(activateArgs, true); // Just activate
if (launchItemHandler.IsValid()) {
// Expected that 'GetLaunchItemPath' called to handle startup item
// it should be marked as handled by default
launchItemHandler.SetState(true);
}
return launchItemHandler.GetFilePath();
}
void CloseLaunchItem(bool launchOnExit) {
if (launchItemHandler.IsValid() && launchItemHandler.IsHandled()) {
launchItemHandler.Close(launchOnExit);
}
}

View file

@ -15,115 +15,28 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include "pch.h"
#include <io.h>
#include <fcntl.h>
#include "Common/Log.h"
#include "UWPUtil.h"
#include <regex>
using namespace Platform;
using namespace Windows::Storage;
using namespace Windows::Foundation;
using namespace Windows::UI::Core;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Activation;
extern void AddItemToFutureList(IStorageItem^ item);
class LaunchItem {
public:
LaunchItem() {
}
// LaunchItem can detect launch items in two cases
// 1- StorageFile
// 2- URI [ppsspp:?cmd="fullpath"&launchOnExit=customURI]
LaunchItem(IStorageFile^ file) {
storageFile = file;
AddItemToFutureList(storageFile);
launchPath = std::string();
launchOnExit = std::string();
}
// Detect if activate args has launch item
// it will auto start the item unless 'onlyActivate' set to 'true'
void DetectLaunchItem(IActivatedEventArgs^ activateArgs, bool onlyActivate = false);
LaunchItem(ProtocolActivatedEventArgs^ args) {
try {
unsigned i;
Windows::Foundation::WwwFormUrlDecoder^ query = args->Uri->QueryParsed;
// Get current launch item path (same as 'DetectLaunchItem' but it doesn't start)
// this function made to handle item on startup
// it will mark the item as 'Handled' by default
// consider to close it if you want to use it for other purposes
std::string GetLaunchItemPath(IActivatedEventArgs^ activateArgs);
for (i = 0; i < query->Size; i++)
{
IWwwFormUrlDecoderEntry^ arg = query->GetAt(i);
if (arg->Name == "cmd")
{
auto command = FromPlatformString(arg->Value);
DEBUG_LOG(FILESYS, "Launch command %s", command.c_str());
std::regex rgx("\"(.+\[^\/]+)\"");
std::smatch match;
if (std::regex_search(command, match, rgx)) {
try
{
launchPath = match[1];
}
catch (...) {
launchPath = match[0];
}
DEBUG_LOG(FILESYS, "Launch target %s", launchPath.c_str());
}
}
else if (arg->Name == "launchOnExit") {
launchOnExit = FromPlatformString(arg->Value);
DEBUG_LOG(FILESYS, "On exit URI %s", launchOnExit.c_str());
}
}
}
catch (...) {
}
storageFile = nullptr;
}
~LaunchItem() {
delete storageFile;
}
bool IsHandled() {
return handled;
}
void SetState(bool fileHandled) {
handled = fileHandled;
}
bool IsValid() {
return storageFile != nullptr || !launchPath.empty();
}
std::string GetFilePath() {
std::string path = launchPath;
if (storageFile != nullptr) {
path = FromPlatformString(storageFile->Path);
}
return path;
}
void Close() {
storageFile = nullptr;
launchPath = std::string();
handled = false;
if (!launchOnExit.empty()) {
DEBUG_LOG(FILESYS, "Calling back %s", launchOnExit.c_str());
auto uri = ref new Windows::Foundation::Uri(ToPlatformString(launchOnExit));
Windows::System::Launcher::LaunchUriAsync(uri);
}
launchOnExit = std::string();
}
private:
IStorageFile^ storageFile;
std::string launchPath;
std::string launchOnExit;
bool handled = false;
};
// Close current launch item
// it will launch back 'launchOnExit' if passed with URI 'cmd'
// if you want to ignore 'launchOnExit' call set it to 'false'
void CloseLaunchItem(bool launchOnExit = true);