Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/cli/LuaPrelude.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,11 +784,24 @@ function ac.batch(steps, opts)
local results = response.data and response.data.results or {}
for i, result in ipairs(results) do
local step = normalized_steps[i] or {}
local diagnostic = type(result.data) == "table" and result.data or {}
local desktop = type(diagnostic.after) == "table" and diagnostic.after
or (type(diagnostic.before) == "table" and diagnostic.before or {})
local frontmost = type(diagnostic.frontmostApp) == "table"
and diagnostic.frontmostApp or {}
log_line("action", result.ok and "ok" or "failed", {
id = result.id or step.id,
method = step.method,
code = result.code,
error = result.error,
desktopStatus = desktop.status,
screenLocked = desktop.screenLocked,
screenSaverActive = desktop.screenSaverActive,
displayAsleep = desktop.displayAsleep,
wakeForced = diagnostic.forced,
wakeSignalSent = diagnostic.wakeSignalSent,
frontmostApp = frontmost.name,
frontmostBundle = frontmost.bundleId,
})
end
if not opts.allow_error then
Expand Down
41 changes: 36 additions & 5 deletions src/daemon/DaemonDesktop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ bool CanAttemptDesktopWake(const Platform::DesktopSessionState& state, bool forc
(!state.screenLocked || state.screenSaverActive || force);
}

bool ShouldForceAutomaticDesktopWake(const Platform::DesktopSessionState& state) {
// Recent macOS versions can report a password-protected screensaver as
// locked without exposing ScreenSaverEngine to the current GUI session.
// A forced wake only posts user activity; readiness is still verified
// afterward and a real lock screen remains locked.
return state.screenLocked && !state.screenSaverActive;
}

bool IsPermissionsPane(const std::string& pane) {
return pane == "accessibility" ||
pane == "screen" ||
Expand Down Expand Up @@ -256,7 +264,16 @@ json RunDesktopWakeCommand(const json& params) {
return Error("desktop GUI session is unavailable", "desktop_session_unavailable");
}
if (!CanAttemptDesktopWake(before, force)) {
return Error("desktop session is locked and requires manual unlock", "desktop_locked");
return ErrorWithData(
"desktop session is locked and requires manual unlock",
"desktop_locked",
{
{"forced", force},
{"wakeSignalSent", false},
{"before", DesktopSessionToJson(before)},
{"after", DesktopSessionToJson(before)},
{"frontmostApp", AppToJson(Platform::GetFrontmostApp())}
});
}

const bool alreadyReady = !force && IsDesktopSessionReady(before);
Expand All @@ -273,7 +290,16 @@ json RunDesktopWakeCommand(const json& params) {
} while (std::chrono::steady_clock::now() < deadline);
}
if (after.screenLocked) {
return Error("desktop woke to a lock screen and requires manual unlock", "desktop_locked");
return ErrorWithData(
"desktop woke to a lock screen and requires manual unlock",
"desktop_locked",
{
{"forced", force},
{"wakeSignalSent", wakeSignalSent},
{"before", DesktopSessionToJson(before)},
{"after", DesktopSessionToJson(after)},
{"frontmostApp", AppToJson(Platform::GetFrontmostApp())}
});
}
return Ok({
{"wakeRequested", !alreadyReady},
Expand Down Expand Up @@ -304,12 +330,17 @@ json EnsureDesktopSessionReadyForNativeControl() {
});
}

json wake = RunDesktopWakeCommand(json::object());
json wakeParams = json::object();
if (ShouldForceAutomaticDesktopWake(state)) {
wakeParams["force"] = true;
}
json wake = RunDesktopWakeCommand(wakeParams);
if (!wake.value("ok", false)) return wake;
if (!wake.value("data", json::object()).value("ready", false)) {
return Error(
return ErrorWithData(
"native user activity did not make the desktop session ready",
"desktop_wake_failed");
"desktop_wake_failed",
wake.value("data", json::object()));
}
return wake;
}
Expand Down
1 change: 1 addition & 0 deletions src/daemon/DaemonDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace ComputerCpp {
std::set<std::string> VisibleWindowIds(const std::vector<Platform::WindowInfo>& windows);
bool IsDesktopSessionReady(const Platform::DesktopSessionState& state);
bool CanAttemptDesktopWake(const Platform::DesktopSessionState& state, bool force = false);
bool ShouldForceAutomaticDesktopWake(const Platform::DesktopSessionState& state);
nlohmann::json RunPermissionsCommand(const nlohmann::json& params);
nlohmann::json RunOpenPermissionsCommand(const nlohmann::json& params);
nlohmann::json RunStateCommand(const std::string& session);
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/DaemonMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ json SchemaJson() {
{"desktop", {
{"sessionState", "method desktop_session_state; reports status ready, screensaver, display_asleep, locked, unavailable, or unsupported"},
{"wake", "method desktop_wake; optional force boolean sends native user activity despite a false-ready state, then conditionally polls for readiness"},
{"automaticWake", "managed-browser, window, and PID-based app activation wake an unlocked screensaver or sleeping display before native control"},
{"automaticWake", "managed-browser, window, and PID-based app activation wake a screensaver or sleeping display before native control; ambiguous macOS lock reports receive a forced user-activity probe"},
{"safety", "desktop_wake never attempts to authenticate or bypass a lock screen; desktop_locked requires manual unlock"},
{"sessionResponse", "detectionSupported, available, onConsole, loginDone, screenLocked, screenSaverActive, displayAsleep, ready, and status"},
{"wakeResponse", "wakeRequested, forced, wakeSignalSent, ready, before/after session state, and frontmostApp"}
Expand Down
3 changes: 3 additions & 0 deletions tests/DaemonDispatchTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ void TestDesktopSessionReadiness() {
assert(!ComputerCpp::IsDesktopSessionReady(state));
assert(!ComputerCpp::CanAttemptDesktopWake(state));
assert(ComputerCpp::CanAttemptDesktopWake(state, true));
assert(ComputerCpp::ShouldForceAutomaticDesktopWake(state));

state.screenSaverActive = true;
assert(ComputerCpp::CanAttemptDesktopWake(state));
assert(!ComputerCpp::ShouldForceAutomaticDesktopWake(state));
state.screenSaverActive = false;

state.screenLocked = false;
state.displayAsleep = true;
assert(ComputerCpp::CanAttemptDesktopWake(state));
assert(!ComputerCpp::ShouldForceAutomaticDesktopWake(state));
}

void TestManagedBrowserCompatibilityPortMarker() {
Expand Down
Loading