mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
fix(mango): use dwl-ipc selected output for preferredInteractiveOutput
This commit is contained in:
@@ -323,6 +323,14 @@ void CompositorPlatform::setCursorShape(std::uint32_t serial, std::uint32_t shap
|
||||
}
|
||||
|
||||
wl_output* CompositorPlatform::preferredInteractiveOutput(std::chrono::milliseconds pointerMaxAge) const {
|
||||
// Mango/dwl: zdwl_ipc_output_v2.active (committed on frame) tracks the compositor-selected monitor, which
|
||||
// follows the cursor even when keyboard focus stays on a client in another tag/output.
|
||||
if (compositors::detect() == compositors::CompositorKind::Mango && m_workspaces != nullptr) {
|
||||
if (wl_output* ipc = m_workspaces->dwlIpcSelectedOutput(); ipc != nullptr) {
|
||||
return ipc;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& backend : m_focusedOutputBackends) {
|
||||
if (backend == nullptr) {
|
||||
continue;
|
||||
|
||||
@@ -193,7 +193,10 @@ void MangoWorkspaceBackend::onOutputActive(zdwl_ipc_output_v2* handle, std::uint
|
||||
}
|
||||
auto state = m_outputs.find(it->second);
|
||||
if (state != m_outputs.end()) {
|
||||
state->second.active = active != 0;
|
||||
// Double-buffer like noctalia-qs: dwl commits ipc state on frame; applying active immediately can leave
|
||||
// multiple outputs marked active if the compositor updates selection across outputs in one dispatch.
|
||||
state->second.hasPendingIpcActive = true;
|
||||
state->second.pendingIpcActive = active != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,8 +240,20 @@ void MangoWorkspaceBackend::onOutputFrame(zdwl_ipc_output_v2* handle) {
|
||||
if (it != m_outputByHandle.end()) {
|
||||
const auto stateIt = m_outputs.find(it->second);
|
||||
if (stateIt != m_outputs.end()) {
|
||||
kLog.debug("frame output={} total_tags={} snapshot={}", static_cast<const void*>(stateIt->second.output),
|
||||
m_tagCount, summarizeTags(stateIt->second));
|
||||
auto& st = stateIt->second;
|
||||
if (st.hasPendingIpcActive) {
|
||||
if (st.pendingIpcActive) {
|
||||
for (auto& [_, other] : m_outputs) {
|
||||
other.active = false;
|
||||
}
|
||||
st.active = true;
|
||||
} else {
|
||||
st.active = false;
|
||||
}
|
||||
st.hasPendingIpcActive = false;
|
||||
}
|
||||
kLog.debug("frame output={} total_tags={} snapshot={}", static_cast<const void*>(st.output), m_tagCount,
|
||||
summarizeTags(st));
|
||||
}
|
||||
}
|
||||
notifyChanged();
|
||||
@@ -345,3 +360,12 @@ void MangoWorkspaceBackend::notifyChanged() {
|
||||
m_changeCallback();
|
||||
}
|
||||
}
|
||||
|
||||
wl_output* MangoWorkspaceBackend::ipcSelectedOutput() const {
|
||||
for (const auto& [_, state] : m_outputs) {
|
||||
if (state.active) {
|
||||
return state.output;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ public:
|
||||
std::uint32_t focused);
|
||||
void onOutputFrame(zdwl_ipc_output_v2* handle);
|
||||
|
||||
/// zdwl_ipc_output_v2.active after frame application — the compositor-selected monitor (cursor output).
|
||||
[[nodiscard]] wl_output* ipcSelectedOutput() const;
|
||||
|
||||
private:
|
||||
struct TagInfo {
|
||||
bool active = false;
|
||||
@@ -47,6 +50,8 @@ private:
|
||||
wl_output* output = nullptr;
|
||||
zdwl_ipc_output_v2* handle = nullptr;
|
||||
bool active = false;
|
||||
bool pendingIpcActive = false;
|
||||
bool hasPendingIpcActive = false;
|
||||
std::vector<TagInfo> tags;
|
||||
};
|
||||
|
||||
|
||||
@@ -211,6 +211,13 @@ std::vector<Workspace> WaylandWorkspaces::forOutput(wl_output* output) const {
|
||||
return m_activeBackend != nullptr ? m_activeBackend->forOutput(output) : std::vector<Workspace>{};
|
||||
}
|
||||
|
||||
wl_output* WaylandWorkspaces::dwlIpcSelectedOutput() const {
|
||||
if (m_dwlIpcBackend == nullptr || !m_dwlIpcBackend->isAvailable()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<MangoWorkspaceBackend*>(m_dwlIpcBackend)->ipcSelectedOutput();
|
||||
}
|
||||
|
||||
void WaylandWorkspaces::setActiveBackend(WorkspaceBackend* backend) {
|
||||
m_activeBackend = backend;
|
||||
kLog.info("workspace backend={}", backendName());
|
||||
|
||||
@@ -42,6 +42,9 @@ public:
|
||||
[[nodiscard]] std::vector<Workspace> all() const;
|
||||
[[nodiscard]] std::vector<Workspace> forOutput(wl_output* output) const;
|
||||
|
||||
/// dwl-ipc selected output (zdwl active bit), or nullptr if ipc is not bound or no output is active yet.
|
||||
[[nodiscard]] wl_output* dwlIpcSelectedOutput() const;
|
||||
|
||||
private:
|
||||
void setActiveBackend(WorkspaceBackend* backend);
|
||||
void notifyChanged() const;
|
||||
|
||||
Reference in New Issue
Block a user