Browse Source

starter 2

pull/2953/head
Maufeat 3 months ago
parent
commit
cf9476f81a
  1. 50
      src/core/core.cpp
  2. 7
      src/core/core.h
  3. 12
      src/core/hle/service/am/display_layer_manager.cpp
  4. 2
      src/core/hle/service/am/service/all_system_applet_proxies_service.cpp
  5. 21
      src/core/hle/service/am/service/home_menu_functions.cpp
  6. 3
      src/core/hle/service/am/service/home_menu_functions.h
  7. 27
      src/core/hle/service/am/service/overlay_functions.cpp
  8. 115
      src/core/hle/service/am/window_system.cpp
  9. 7
      src/core/hle/service/am/window_system.h
  10. 2
      src/core/hle/service/set/setting_formats/system_settings.cpp

50
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<std::vector<u8>> user_channel;
std::mutex general_channel_mutex;
std::deque<std::vector<u8>> general_channel;
std::unique_ptr<Service::KernelHelpers::ServiceContext> general_channel_context; // lazy
std::unique_ptr<Service::Event> general_channel_event; // lazy
bool general_channel_initialized{false};
void EnsureGeneralChannelInitialized(System& system) {
if (general_channel_initialized) {
return;
}
general_channel_context = std::make_unique<Service::KernelHelpers::ServiceContext>(system, "GeneralChannel");
general_channel_event = std::make_unique<Service::Event>(*general_channel_context);
general_channel_initialized = true;
}
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
@ -980,6 +995,39 @@ std::deque<std::vector<u8>>& System::GetUserChannel() {
return impl->user_channel;
}
std::deque<std::vector<u8>>& System::GetGeneralChannel() {
return impl->general_channel;
}
void System::PushGeneralChannelData(std::vector<u8>&& 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<u8>& 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);
}

7
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<std::vector<u8>>& GetUserChannel();
[[nodiscard]] std::deque<std::vector<u8>>& GetGeneralChannel();
void PushGeneralChannelData(std::vector<u8>&& data);
bool TryPopGeneralChannel(std::vector<u8>& 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<void()>;

12
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<u32>(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<u32>(m_applet_id));
m_manager_display_service->SetLayerVisibility(m_visible, layer_id);
}

2
src/core/hle/service/am/service/all_system_applet_proxies_service.cpp

@ -75,7 +75,7 @@ Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy(
Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle,
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> 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<IOverlayAppletProxy>(

21
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> 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<SharedPointer<IStorage>> out_storage) {
LOG_DEBUG(Service_AM, "called");
std::vector<u8> data;
if (!system.TryPopGeneralChannel(data)) {
R_THROW(AM::ResultNoDataInChannel);
}
*out_storage = std::make_shared<IStorage>(system, std::move(data));
R_SUCCEED();
}
Result IHomeMenuFunctions::GetPopFromGeneralChannelEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_AM, "called");
*out_event = m_pop_from_general_channel_event.GetHandle();
*out_event = system.GetGeneralChannelEvent().GetHandle();
R_SUCCEED();
}

3
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<IHomeMenuFunctions> {
public:
@ -23,6 +24,7 @@ private:
Result RequestToGetForeground();
Result LockForeground();
Result UnlockForeground();
Result PopFromGeneralChannel(Out<SharedPointer<IStorage>> out_storage);
Result GetPopFromGeneralChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsRebootEnabled(Out<bool> out_is_reboot_enbaled);
Result IsForceTerminateApplicationDisabledForDebug(
@ -31,7 +33,6 @@ private:
WindowSystem& m_window_system;
const std::shared_ptr<Applet> m_applet;
KernelHelpers::ServiceContext m_context;
Event m_pop_from_general_channel_event;
};
} // namespace Service::AM

27
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();
}

115
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);

7
src/core/hle/service/am/window_system.h

@ -11,6 +11,7 @@
#include <mutex>
#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.

2
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 = {},
};

Loading…
Cancel
Save