mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Resolve launch item and conflicts
- Better handling for launch items - Resolved code conflicts
This commit is contained in:
parent
07c119a80c
commit
c9b3d8aedf
7 changed files with 228 additions and 142 deletions
12
UWP/App.cpp
12
UWP/App.cpp
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
185
UWP/UWPHelpers/LaunchItem.cpp
Normal file
185
UWP/UWPHelpers/LaunchItem.cpp
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue