From cf9476f81a39eca407068f7c2a3ad1cfea25d134 Mon Sep 17 00:00:00 2001 From: Maufeat Date: Sat, 8 Nov 2025 23:14:57 +0100 Subject: [PATCH] starter 2 --- src/core/core.cpp | 50 +++++++- src/core/core.h | 7 ++ .../hle/service/am/display_layer_manager.cpp | 12 +- .../all_system_applet_proxies_service.cpp | 2 +- .../am/service/home_menu_functions.cpp | 21 +++- .../service/am/service/home_menu_functions.h | 3 +- .../service/am/service/overlay_functions.cpp | 27 +--- src/core/hle/service/am/window_system.cpp | 115 +++++++++++------- src/core/hle/service/am/window_system.h | 7 +- .../set/setting_formats/system_settings.cpp | 2 +- 10 files changed, 162 insertions(+), 84 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 7315f35e0c..f10d8c675b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -106,7 +106,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) : kernel{system}, fs_controller{system}, hid_core{}, cpu_manager{system}, - reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {} + reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} /* remove early general channel init */ {} u64 program_id; @@ -567,6 +567,21 @@ struct System::Impl { gpu_dirty_memory_managers; std::deque> user_channel; + + std::mutex general_channel_mutex; + std::deque> general_channel; + std::unique_ptr general_channel_context; // lazy + std::unique_ptr general_channel_event; // lazy + bool general_channel_initialized{false}; + + void EnsureGeneralChannelInitialized(System& system) { + if (general_channel_initialized) { + return; + } + general_channel_context = std::make_unique(system, "GeneralChannel"); + general_channel_event = std::make_unique(*general_channel_context); + general_channel_initialized = true; + } }; System::System() : impl{std::make_unique(*this)} {} @@ -980,6 +995,39 @@ std::deque>& System::GetUserChannel() { return impl->user_channel; } +std::deque>& System::GetGeneralChannel() { + return impl->general_channel; +} + +void System::PushGeneralChannelData(std::vector&& data) { + std::scoped_lock lk{impl->general_channel_mutex}; + impl->EnsureGeneralChannelInitialized(*this); + const bool was_empty = impl->general_channel.empty(); + impl->general_channel.push_back(std::move(data)); + if (was_empty) { + impl->general_channel_event->Signal(); + } +} + +bool System::TryPopGeneralChannel(std::vector& out_data) { + std::scoped_lock lk{impl->general_channel_mutex}; + if (!impl->general_channel_initialized || impl->general_channel.empty()) { + return false; + } + out_data = std::move(impl->general_channel.back()); + impl->general_channel.pop_back(); + if (impl->general_channel.empty()) { + impl->general_channel_event->Clear(); + } + return true; +} + +Service::Event& System::GetGeneralChannelEvent() { + std::scoped_lock lk{impl->general_channel_mutex}; + impl->EnsureGeneralChannelInitialized(*this); + return *impl->general_channel_event; +} + void System::RegisterExitCallback(ExitCallback&& callback) { impl->exit_callback = std::move(callback); } diff --git a/src/core/core.h b/src/core/core.h index 12a957791d..60bf73d4e1 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -17,6 +17,8 @@ #include "common/common_types.h" #include "core/file_sys/vfs/vfs_types.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/kernel_helpers.h" namespace Core::Frontend { class EmuWindow; @@ -428,6 +430,11 @@ public: */ [[nodiscard]] std::deque>& GetUserChannel(); + [[nodiscard]] std::deque>& GetGeneralChannel(); + void PushGeneralChannelData(std::vector&& data); + bool TryPopGeneralChannel(std::vector& out_data); + [[nodiscard]] Service::Event& GetGeneralChannelEvent(); + /// Type used for the frontend to designate a callback for System to exit the application. using ExitCallback = std::function; diff --git a/src/core/hle/service/am/display_layer_manager.cpp b/src/core/hle/service/am/display_layer_manager.cpp index 833572bba5..81efea72fb 100644 --- a/src/core/hle/service/am/display_layer_manager.cpp +++ b/src/core/hle/service/am/display_layer_manager.cpp @@ -80,10 +80,10 @@ Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) { if (m_applet_id != AppletId::Application) { (void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id); if (m_applet_id == AppletId::OverlayDisplay) { - static constexpr s32 kOverlayBackgroundZ = -100000; + static constexpr s32 kOverlayBackgroundZ = -1; (void)m_manager_display_service->SetLayerZIndex(kOverlayBackgroundZ, *out_layer_id); } else { - static constexpr s32 kOverlayZ = 100000; + static constexpr s32 kOverlayZ = 3; (void)m_manager_display_service->SetLayerZIndex(kOverlayZ, *out_layer_id); } } @@ -132,9 +132,9 @@ Result DisplayLayerManager::IsSystemBufferSharingEnabled() { // Ensure the overlay layer is visible m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); m_manager_display_service->SetLayerBlending(m_blending_enabled, m_system_shared_layer_id); - s32 initial_z = 100; + s32 initial_z = 1; if (m_applet_id == AppletId::OverlayDisplay) { - initial_z = -100000; + initial_z = -1; } m_manager_display_service->SetLayerZIndex(initial_z, m_system_shared_layer_id); LOG_INFO(Service_VI, @@ -164,13 +164,13 @@ void DisplayLayerManager::SetWindowVisibility(bool visible) { if (m_manager_display_service) { if (m_system_shared_layer_id) { - LOG_INFO(Service_VI, "DLM: SetWindowVisibility shared_layer={} visible={} applet_id={}", + LOG_INFO(Service_VI, "shared_layer={} visible={} applet_id={}", m_system_shared_layer_id, m_visible, static_cast(m_applet_id)); m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); } for (const auto layer_id : m_managed_display_layers) { - LOG_INFO(Service_VI, "DLM: SetWindowVisibility managed_layer={} visible={} applet_id={}", + LOG_INFO(Service_VI, "managed_layer={} visible={} applet_id={}", layer_id, m_visible, static_cast(m_applet_id)); m_manager_display_service->SetLayerVisibility(m_visible, layer_id); } diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp index ec15708ed8..562d95f001 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp @@ -75,7 +75,7 @@ Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy( Out> out_overlay_applet_proxy, ClientProcessId pid, InCopyHandle process_handle, InLargeData attribute) { - LOG_DEBUG(Service_AM, "called"); + LOG_WARNING(Service_AM, "called"); if (const auto applet = this->GetAppletFromProcessId(pid); applet) { *out_overlay_applet_proxy = std::make_shared( diff --git a/src/core/hle/service/am/service/home_menu_functions.cpp b/src/core/hle/service/am/service/home_menu_functions.cpp index 25f78beb5a..d091ace05b 100644 --- a/src/core/hle/service/am/service/home_menu_functions.cpp +++ b/src/core/hle/service/am/service/home_menu_functions.cpp @@ -6,20 +6,21 @@ #include "core/hle/service/am/service/home_menu_functions.h" #include "core/hle/service/am/window_system.h" #include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/am/am_results.h" +#include "core/hle/service/am/service/storage.h" namespace Service::AM { IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr applet, WindowSystem& window_system) : ServiceFramework{system_, "IHomeMenuFunctions"}, m_window_system{window_system}, - m_applet{std::move(applet)}, m_context{system, "IHomeMenuFunctions"}, - m_pop_from_general_channel_event{m_context} { + m_applet{std::move(applet)}, m_context{system, "IHomeMenuFunctions"} { // clang-format off static const FunctionInfo functions[] = { {10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"}, {11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"}, {12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"}, - {20, nullptr, "PopFromGeneralChannel"}, + {20, D<&IHomeMenuFunctions::PopFromGeneralChannel>, "PopFromGeneralChannel"}, {21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"}, {30, nullptr, "GetHomeButtonWriterLockAccessor"}, {31, nullptr, "GetWriterLockAccessorEx"}, @@ -57,10 +58,22 @@ Result IHomeMenuFunctions::UnlockForeground() { R_SUCCEED(); } +Result IHomeMenuFunctions::PopFromGeneralChannel(Out> out_storage) { + LOG_DEBUG(Service_AM, "called"); + + std::vector data; + if (!system.TryPopGeneralChannel(data)) { + R_THROW(AM::ResultNoDataInChannel); + } + + *out_storage = std::make_shared(system, std::move(data)); + R_SUCCEED(); +} + Result IHomeMenuFunctions::GetPopFromGeneralChannelEvent( OutCopyHandle out_event) { LOG_INFO(Service_AM, "called"); - *out_event = m_pop_from_general_channel_event.GetHandle(); + *out_event = system.GetGeneralChannelEvent().GetHandle(); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/home_menu_functions.h b/src/core/hle/service/am/service/home_menu_functions.h index f56094aa9d..182389898d 100644 --- a/src/core/hle/service/am/service/home_menu_functions.h +++ b/src/core/hle/service/am/service/home_menu_functions.h @@ -12,6 +12,7 @@ namespace Service::AM { struct Applet; class WindowSystem; +class IStorage; class IHomeMenuFunctions final : public ServiceFramework { public: @@ -23,6 +24,7 @@ private: Result RequestToGetForeground(); Result LockForeground(); Result UnlockForeground(); + Result PopFromGeneralChannel(Out> out_storage); Result GetPopFromGeneralChannelEvent(OutCopyHandle out_event); Result IsRebootEnabled(Out out_is_reboot_enbaled); Result IsForceTerminateApplicationDisabledForDebug( @@ -31,7 +33,6 @@ private: WindowSystem& m_window_system; const std::shared_ptr m_applet; KernelHelpers::ServiceContext m_context; - Event m_pop_from_general_channel_event; }; } // namespace Service::AM diff --git a/src/core/hle/service/am/service/overlay_functions.cpp b/src/core/hle/service/am/service/overlay_functions.cpp index a1f749a69e..5192f9ebbe 100644 --- a/src/core/hle/service/am/service/overlay_functions.cpp +++ b/src/core/hle/service/am/service/overlay_functions.cpp @@ -43,17 +43,9 @@ IOverlayFunctions::~IOverlayFunctions() = default; Result IOverlayFunctions::BeginToWatchShortHomeButtonMessage() { LOG_DEBUG(Service_AM, "called"); - { - std::scoped_lock lk{m_applet->lock}; - m_applet->overlay_in_foreground = true; - m_applet->home_button_short_pressed_blocked = false; - - static constexpr s32 kOverlayForegroundZ = 100000; - m_applet->display_layer_manager.SetOverlayZIndex(kOverlayForegroundZ); - - LOG_INFO(Service_AM, "called, Overlay moved to FOREGROUND (z={}, overlay_in_foreground=true)", kOverlayForegroundZ); - } + m_applet->overlay_in_foreground = true; + m_applet->home_button_short_pressed_blocked = false; if (auto* window_system = system.GetAppletManager().GetWindowSystem()) { window_system->RequestUpdate(); @@ -65,17 +57,8 @@ Result IOverlayFunctions::BeginToWatchShortHomeButtonMessage() { Result IOverlayFunctions::EndToWatchShortHomeButtonMessage() { LOG_DEBUG(Service_AM, "called"); - { - std::scoped_lock lk{m_applet->lock}; - - m_applet->overlay_in_foreground = false; - m_applet->home_button_short_pressed_blocked = false; - - static constexpr s32 kOverlayBackgroundZ = -100; - m_applet->display_layer_manager.SetOverlayZIndex(kOverlayBackgroundZ); - - LOG_INFO(Service_AM, "Overlay moved to BACKGROUND (z={}, overlay_in_foreground=false)", kOverlayBackgroundZ); - } + m_applet->overlay_in_foreground = false; + m_applet->home_button_short_pressed_blocked = false; if (auto* window_system = system.GetAppletManager().GetWindowSystem()) { window_system->RequestUpdate(); @@ -106,7 +89,7 @@ Result IOverlayFunctions::SetAutoSleepTimeAndDimmingTimeEnabled(bool enabled) { Result IOverlayFunctions::SetHandlingHomeButtonShortPressedEnabled(bool enabled) { LOG_DEBUG(Service_AM, "called, enabled={}", enabled); std::scoped_lock lk{m_applet->lock}; - m_applet->home_button_short_pressed_blocked = false; + m_applet->home_button_short_pressed_blocked = !enabled; R_SUCCEED(); } diff --git a/src/core/hle/service/am/window_system.cpp b/src/core/hle/service/am/window_system.cpp index c76c154651..4d29ecb2a3 100644 --- a/src/core/hle/service/am/window_system.cpp +++ b/src/core/hle/service/am/window_system.cpp @@ -158,58 +158,67 @@ void WindowSystem::OnExitRequested() { } } -void WindowSystem::OnHomeButtonPressed(ButtonPressDuration type) { - std::scoped_lock lk{m_lock}; - - LOG_INFO(Service_AM, "WindowSystem::OnHomeButtonPressed - type={} overlay={} home_menu={} application={} foreground={}", - type == ButtonPressDuration::ShortPressing ? "Short" : "Long", - m_overlay_display != nullptr, m_home_menu != nullptr, m_application != nullptr, - m_foreground_requested_applet == m_home_menu ? "home_menu" : - m_foreground_requested_applet == m_application ? "application" : "none"); - - // Priority 1: Check overlay first (works everywhere, even in qlaunch) - // Long press always goes to overlay for toggling - // Short press only when overlay is already open (to close it) +void WindowSystem::SendButtonAppletMessageLocked(AppletMessage message) { + if (m_home_menu) { + std::scoped_lock lk_home{m_home_menu->lock}; + m_home_menu->lifecycle_manager.PushUnorderedMessage(message); + } if (m_overlay_display) { - std::scoped_lock lk3{m_overlay_display->lock}; - const bool overlay_should_handle = !m_overlay_display->home_button_short_pressed_blocked; - - if (overlay_should_handle) { - const bool overlay_in_fg = m_overlay_display->overlay_in_foreground; - - if (type == ButtonPressDuration::LongPressing || - (type == ButtonPressDuration::ShortPressing && overlay_in_fg)) { - - LOG_INFO(Service_AM, "Sending {} press to overlay (foreground={})", - type == ButtonPressDuration::ShortPressing ? "short" : "long", - overlay_in_fg); - - if (type == ButtonPressDuration::ShortPressing) { - m_overlay_display->lifecycle_manager.PushUnorderedMessage( - AppletMessage::DetectShortPressingHomeButton); - } else { - m_overlay_display->lifecycle_manager.PushUnorderedMessage( - AppletMessage::DetectLongPressingHomeButton); - } - return; - } - } + std::scoped_lock lk_overlay{m_overlay_display->lock}; + m_overlay_display->lifecycle_manager.PushUnorderedMessage(message); + } + if (m_application) { + std::scoped_lock lk_application{m_application->lock}; + m_application->lifecycle_manager.PushUnorderedMessage(message); + } + if (m_event_observer) { + m_event_observer->RequestUpdate(); } +} - if (m_home_menu) { - std::scoped_lock lk2{m_home_menu->lock}; - LOG_DEBUG(Service_AM, "called, Sending home button to home menu"); - if (type == ButtonPressDuration::ShortPressing) { - m_home_menu->lifecycle_manager.PushUnorderedMessage( - AppletMessage::DetectShortPressingHomeButton); - } else if (type == ButtonPressDuration::LongPressing) { - m_home_menu->lifecycle_manager.PushUnorderedMessage( - AppletMessage::DetectLongPressingHomeButton); +void WindowSystem::OnSystemButtonPress(SystemButtonType type) { + std::scoped_lock lk{m_lock}; + switch (type) { + case SystemButtonType::HomeButtonShortPressing: + SendButtonAppletMessageLocked(AppletMessage::DetectShortPressingHomeButton); + break; + case SystemButtonType::HomeButtonLongPressing: { + // Toggle overlay foreground visibility on long home press + if (m_overlay_display) { + std::scoped_lock lk_overlay{m_overlay_display->lock}; + m_overlay_display->overlay_in_foreground = !m_overlay_display->overlay_in_foreground; + // Tie window visibility to foreground state so hidden when not active + m_overlay_display->window_visible = m_overlay_display->overlay_in_foreground; + LOG_INFO(Service_AM, "Overlay long-press toggle: overlay_in_foreground={} window_visible={}", m_overlay_display->overlay_in_foreground, m_overlay_display->window_visible); } - return; + SendButtonAppletMessageLocked(AppletMessage::DetectLongPressingHomeButton); + // Force a state update after toggling overlay + if (m_event_observer) { + m_event_observer->RequestUpdate(); + } + break; } + case SystemButtonType::CaptureButtonShortPressing: + SendButtonAppletMessageLocked(AppletMessage::DetectShortPressingCaptureButton); + break; + case SystemButtonType::CaptureButtonLongPressing: + SendButtonAppletMessageLocked(AppletMessage::DetectLongPressingCaptureButton); + break; + default: + break; } +} - LOG_DEBUG(Service_AM, "called, No target for home button press"); +void WindowSystem::OnHomeButtonPressed(ButtonPressDuration type) { + // Map duration to SystemButtonType for legacy callers + switch (type) { + case ButtonPressDuration::ShortPressing: + OnSystemButtonPress(SystemButtonType::HomeButtonShortPressing); + break; + case ButtonPressDuration::MiddlePressing: + case ButtonPressDuration::LongPressing: + OnSystemButtonPress(SystemButtonType::HomeButtonLongPressing); + break; + } } void WindowSystem::PruneTerminatedAppletsLocked() { @@ -382,6 +391,20 @@ void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground, b applet->UpdateSuspensionStateLocked(true); } + // Z-index logic like in reference C# implementation (tuned for overlay extremes) + s32 z_index = 0; + const bool now_foreground = inherited_foreground; + if (applet->applet_id == AppletId::OverlayDisplay) { + z_index = applet->overlay_in_foreground ? 100000 : -100000; + } else if (now_foreground && !is_obscured) { + z_index = 2; + } else if (now_foreground) { + z_index = 1; + } else { + z_index = 0; + } + applet->display_layer_manager.SetOverlayZIndex(z_index); + // Recurse into child applets. for (const auto& child_applet : applet->child_applets) { this->UpdateAppletStateLocked(child_applet.get(), is_foreground, overlay_blocking); diff --git a/src/core/hle/service/am/window_system.h b/src/core/hle/service/am/window_system.h index 7167d6af32..c208a3f89f 100644 --- a/src/core/hle/service/am/window_system.h +++ b/src/core/hle/service/am/window_system.h @@ -11,6 +11,7 @@ #include #include "common/common_types.h" +#include "core/hle/service/am/am_types.h" // added for SystemButtonType, AppletMessage namespace Core { class System; @@ -52,8 +53,9 @@ public: public: void OnOperationModeChanged(); void OnExitRequested(); - void OnHomeButtonPressed(ButtonPressDuration type); - void OnCaptureButtonPressed(ButtonPressDuration type) {} + void OnHomeButtonPressed(ButtonPressDuration type); // legacy mapping + void OnSystemButtonPress(SystemButtonType type); + void OnCaptureButtonPressed(ButtonPressDuration type) { /* legacy no-op */ } void OnPowerButtonPressed(ButtonPressDuration type) {} private: @@ -61,6 +63,7 @@ private: bool LockHomeMenuIntoForegroundLocked(); void TerminateChildAppletsLocked(Applet* applet); void UpdateAppletStateLocked(Applet* applet, bool is_foreground, bool overlay_blocking = false); + void SendButtonAppletMessageLocked(AppletMessage message); private: // System reference. diff --git a/src/core/hle/service/set/setting_formats/system_settings.cpp b/src/core/hle/service/set/setting_formats/system_settings.cpp index caa30c2d5c..59c451fc7c 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.cpp +++ b/src/core/hle/service/set/setting_formats/system_settings.cpp @@ -35,7 +35,7 @@ SystemSettings DefaultSystemSettings() { }; settings.initial_launch_settings_packed = { - .flags = {0x10001}, + .flags = {0x0}, .timestamp = {}, };