Fix home button detection and crashes when switching menus

This commit is contained in:
XorTroll 2020-10-13 15:13:39 +02:00
parent b20e374e12
commit f477da1d24
6 changed files with 49 additions and 43 deletions

View file

@ -4,6 +4,8 @@
namespace ipc {
// Note: domains and pointer buffer are required since ECS sessions will make use of them (like normal fs interfaces)
struct ServerOptions {
static const size_t PointerBufferSize = 0x400;
static const size_t MaxDomains = 0x40;

View file

@ -13,6 +13,8 @@
#include <util/util_Convert.hpp>
#include <cfg/cfg_Config.hpp>
// Outside of anonymous namespace since these are accessed by IPC
ams::os::Mutex g_LastMenuMessageLock(false);
dmi::MenuMessage g_LastMenuMessage = dmi::MenuMessage::Invalid;
@ -42,12 +44,12 @@ namespace {
u8 *g_UsbViewerReadBuffer = nullptr;
cfg::Config g_Config = {};
ams::os::ThreadType g_UsbViewerThread;
alignas(ams::os::ThreadStackAlignment) u8 g_UsbViewerThreadStack[0x8000];
alignas(ams::os::ThreadStackAlignment) u8 g_UsbViewerThreadStack[0x4000];
UsbMode g_UsbViewerMode = UsbMode::Invalid;
// In the USB packet, the first u32 / the first 4 bytes are the USB mode (raw RGBA or JPEG, depending on what the console supports)
// In the USB packet, the first u32 stores the USB mode (raw RGBA or JPEG, depending on what the console supports)
constexpr size_t UsbPacketSize = RawRGBAScreenBufferSize + sizeof(u32);
constexpr size_t UsbPacketSize = RawRGBAScreenBufferSize + sizeof(UsbMode);
}
@ -69,10 +71,13 @@ extern "C" {
u32 __nx_applet_type = AppletType_SystemApplet;
u32 __nx_fs_num_sessions = 1;
bool __nx_fsdev_support_cwd = false;
u32 __nx_fsdev_direntry_cache_size = 0;
void __libnx_initheap();
void __appInit();
void __appExit();
}
extern char *fake_heap_start;
@ -99,10 +104,9 @@ void __appInit() {
}
void __appExit() {
((void(*)())0xBEEFBABE)();
// qlaunch should not terminate, so this is considered an invalid system state
// am would fatal otherwise
fatalThrow(0xDEBF);
fatalThrow(0xDEADBABE);
}
namespace {
@ -129,27 +133,25 @@ namespace {
appletStartSleepSequence(true);
}
Result LaunchMenu(dmi::MenuStartMode stmode, dmi::DaemonStatus status) {
R_TRY(ecs::RegisterLaunchAsApplet(g_Config.menu_program_id, static_cast<u32>(stmode), "/ulaunch/bin/uMenu", &status, sizeof(status)));
return ResultSuccess;
inline Result LaunchMenu(dmi::MenuStartMode stmode, dmi::DaemonStatus status) {
return ecs::RegisterLaunchAsApplet(g_Config.menu_program_id, static_cast<u32>(stmode), "/ulaunch/bin/uMenu", &status, sizeof(status));
}
void HandleHomeButton() {
if(am::LibraryAppletIsActive() && !am::LibraryAppletIsMenu()) {
// An applet is opened (which is not our menu), thus close it and reopen the menu
am::LibraryAppletTerminate();
auto status = CreateStatus();
UL_ASSERT(LaunchMenu(dmi::MenuStartMode::Menu, status));
return;
}
if(am::ApplicationIsActive()) {
if(am::ApplicationHasForeground()) {
am::HomeMenuSetForeground();
auto status = CreateStatus();
UL_ASSERT(LaunchMenu(dmi::MenuStartMode::MenuApplicationSuspended, status));
return;
}
else if(am::ApplicationIsActive() && am::ApplicationHasForeground()) {
// Hide the application currently on focus and open our menu
am::HomeMenuSetForeground();
auto status = CreateStatus();
UL_ASSERT(LaunchMenu(dmi::MenuStartMode::MenuApplicationSuspended, status));
}
if(am::LibraryAppletIsMenu()) {
else if(am::LibraryAppletIsMenu()) {
// Send a message to our menu to handle itself the home press
std::scoped_lock lk(g_LastMenuMessageLock);
g_LastMenuMessage = dmi::MenuMessage::HomeRequest;
}

View file

@ -8,21 +8,20 @@ extern dmi::MenuMessage g_LastMenuMessage;
namespace ipc {
ams::Result PrivateService::Initialize(const ams::sf::ClientProcessId &client_pid) {
if(this->initialized) {
return ams::ResultSuccess();
}
u64 program_id = 0;
R_TRY(pminfoGetProgramId(&program_id, client_pid.process_id.value));
auto last_menu_program_id = am::LibraryAppletGetProgramIdForAppletId(am::LibraryAppletGetMenuAppletId());
// If Menu hasn't been launched it's program ID will be 0/invalid, thus a != check wouldn't be enough
// If any of the IDs is invalid, something unexpected is happening...
if((last_menu_program_id == 0) || (program_id == 0) || (program_id != last_menu_program_id)) {
return RES_VALUE(Daemon, PrivateServiceInvalidProcess);
if(!this->initialized) {
u64 program_id = 0;
R_TRY(pminfoGetProgramId(&program_id, client_pid.process_id.value));
auto last_menu_program_id = am::LibraryAppletGetProgramIdForAppletId(am::LibraryAppletGetMenuAppletId());
// If Menu hasn't been launched it's program ID will be 0/invalid, thus a != check wouldn't be enough
// If any of the IDs is invalid, something unexpected is happening...
if((last_menu_program_id == 0) || (program_id == 0) || (program_id != last_menu_program_id)) {
return RES_VALUE(Daemon, PrivateServiceInvalidProcess);
}
this->initialized = true;
}
this->initialized = true;
return ams::ResultSuccess();
}
@ -33,6 +32,12 @@ namespace ipc {
std::scoped_lock lk(g_LastMenuMessageLock);
out_msg.SetValue(g_LastMenuMessage);
auto f = fopen("sdmc:/udaemon-priv.log", "ab+");
if(f) {
auto msg = "Sending message: " + std::to_string(static_cast<u32>(g_LastMenuMessage));
fwrite(msg.c_str(), msg.length(), 1, f);
fclose(f);
}
g_LastMenuMessage = dmi::MenuMessage::Invalid;
return ams::ResultSuccess();
}

View file

@ -2,8 +2,6 @@
namespace {
Service g_DaemonPrivateService;
Result daemonPrivateInitialize(Service *srv) {
u64 pid_placeholder = 0;
return serviceDispatchIn(srv, 0, pid_placeholder,
@ -12,9 +10,11 @@ namespace {
}
Result daemonPrivateGetMessage(Service *srv, dmi::MenuMessage *out_msg) {
return serviceDispatchOut(&g_DaemonPrivateService, 1, out_msg);
return serviceDispatchOut(srv, 1, *out_msg);
}
Service g_DaemonPrivateService;
Result daemonInitializePrivateService() {
if(serviceIsActive(&g_DaemonPrivateService)) {
return ResultSuccess;
@ -58,11 +58,10 @@ namespace am {
break;
}
auto tmp_msg = daemonGetMessage();
auto last_msg = daemonGetMessage();
mutexLock(&g_ReceiverLock);
for(auto &[cb, msg] : g_ReceiverCallbackTable) {
if(msg == tmp_msg) {
if(msg == last_msg) {
cb();
}
}
@ -81,7 +80,7 @@ namespace am {
R_TRY(daemonInitializePrivateService());
g_ReceiveThreadShouldStop = false;
R_TRY(threadCreate(&g_ReceiverThread, &DaemonMessageReceiverThread, nullptr, nullptr, 0x1000, 0x2b, -2));
R_TRY(threadCreate(&g_ReceiverThread, &DaemonMessageReceiverThread, nullptr, nullptr, 0x2000, 0x2B, -2));
R_TRY(threadStart(&g_ReceiverThread));
g_Initialized = true;

View file

@ -679,6 +679,8 @@ namespace ui {
}
void MenuLayout::MoveFolder(const std::string &name, bool fade) {
this->itemsMenu->SetSelectedItem(0);
if(fade) {
g_MenuApplication->FadeOut();
}

View file

@ -14,12 +14,8 @@
"filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF"
},
"service_host": [
"*"
],
"service_access": [
"*"
],
"service_host": [ "*" ],
"service_access": [ "*" ],
"kernel_capabilities": [
{
"type": "kernel_flags",