[idd] helper: retry topology after desktop access failure
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled

The interactive Helper can start when the console user token exists but
before WinSta0\Default is ready. SetDisplayConfig then returns
ERROR_ACCESS_DENIED while recovery exit caches the failure and keeps
topology enforcement suppressed.

Keep the recovery request pending while desktop access is transient.
Move the pipe worker to the input desktop and retry without caching
intermediate failures. Leave an exhausted access failure uncached so a
later replay can recover.

Restore the periodic enforcement timer and retry topology without
reapplying a display mode that Windows has already accepted.
This commit is contained in:
Geoffrey McRae
2026-08-21 01:02:10 +10:00
parent e2ee9244ed
commit 82c59cecf2
3 changed files with 238 additions and 57 deletions

View File

@@ -39,6 +39,7 @@
#define ID_DISPLAY_CHECK_TIMER 1
#define DISPLAY_SETTLE_DELAY 250
#define DISPLAY_RETRY_DELAY 1000
#define DISPLAY_CHECK_INTERVAL 5000
ATOM CNotifyWindow::s_atom = 0;
UINT CNotifyWindow::s_taskbarCreated = 0;
@@ -135,7 +136,9 @@ LRESULT CNotifyWindow::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_DISPLAYCHANGE:
if (!m_recoveryActive)
{
scheduleDisplayCheck(DISPLAY_SETTLE_DELAY);
}
return 0;
case WM_TIMER:
@@ -145,10 +148,18 @@ LRESULT CNotifyWindow::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
KillTimer(m_hwnd, ID_DISPLAY_CHECK_TIMER);
if (m_recoveryActive)
break;
if (m_onEnsureOnlyDisplay && m_onEnsureOnlyDisplay())
DEBUG_INFO("Enforced Looking Glass as the only display");
const bool success =
m_onEnsureOnlyDisplay && m_onEnsureOnlyDisplay();
if (success)
{
DEBUG_TRACE("Enforced Looking Glass as the only display");
}
else
{
DEBUG_WARN("Failed to ensure Looking Glass is the only display");
}
scheduleDisplayCheck(success ?
DISPLAY_CHECK_INTERVAL : DISPLAY_RETRY_DELAY);
break;
}
return 0;
@@ -218,7 +229,11 @@ LRESULT CNotifyWindow::onNotifyIcon(UINT uEvent, WORD wIconId, int x, int y)
PostMessage(m_hwnd, WM_CLEAN_UP_CONFIG, 0, 0);
});
if (m_onSettingChange)
m_config->onSettingChange(m_onSettingChange);
m_config->onSettingChange([this]() {
m_onSettingChange();
KillTimer(m_hwnd, ID_DISPLAY_CHECK_TIMER);
scheduleDisplayCheck(DISPLAY_SETTLE_DELAY);
});
ShowWindow(*m_config, SW_NORMAL);
break;
}