Swaybackend for output management and Wayland connection handling.

This commit is contained in:
Mathew-D
2026-05-06 17:29:50 -04:00
parent 8cb73cb09f
commit 4d9402fd46
4 changed files with 100 additions and 0 deletions
@@ -1,6 +1,73 @@
#include "compositors/sway/sway_output_backend.h"
#include "core/log.h"
#include "core/process.h"
#include "util/string_utils.h"
#include <cstdlib>
#include <json.hpp>
namespace {
constexpr Logger kLog("sway_output");
[[nodiscard]] std::optional<std::string> parseFocusedOutputName(std::string_view payload) {
if (payload.empty()) {
return std::nullopt;
}
try {
const auto json = nlohmann::json::parse(payload);
if (!json.is_array()) {
return std::nullopt;
}
for (const auto& item : json) {
if (!item.is_object() || !item.value("focused", false)) {
continue;
}
if (auto it = item.find("name"); it != item.end() && it->is_string()) {
const auto value = StringUtils::trim(it->get<std::string>());
if (!value.empty()) {
return value;
}
}
}
} catch (const nlohmann::json::exception&) {
return std::nullopt;
}
return std::nullopt;
}
} // namespace
SwayOutputBackend::SwayOutputBackend(std::string_view compositorHint) {
const bool hinted = StringUtils::containsInsensitive(compositorHint, "sway");
const char* swaySocket = std::getenv("SWAYSOCK");
const char* i3Socket = std::getenv("I3SOCK");
m_enabled = hinted || (swaySocket != nullptr && swaySocket[0] != '\0') || (i3Socket != nullptr && i3Socket[0] != '\0');
}
bool SwayOutputBackend::isAvailable() const noexcept { return m_enabled; }
std::optional<std::string> SwayOutputBackend::focusedOutputName() const {
if (!m_enabled) {
return std::nullopt;
}
const char* msgCommand = process::commandExists("scrollmsg") ? "scrollmsg" : "swaymsg";
if (!process::commandExists(msgCommand)) {
msgCommand = "i3-msg";
}
const auto result = process::runSync({msgCommand, "-t", "get_outputs", "-r"});
if (!result) {
kLog.debug("failed to resolve focused output via {}", msgCommand);
return std::nullopt;
}
return parseFocusedOutputName(result.out);
}
namespace compositors::sway {
@@ -1,5 +1,20 @@
#pragma once
#include <optional>
#include <string>
#include <string_view>
class SwayOutputBackend {
public:
explicit SwayOutputBackend(std::string_view compositorHint);
[[nodiscard]] bool isAvailable() const noexcept;
[[nodiscard]] std::optional<std::string> focusedOutputName() const;
private:
bool m_enabled = false;
};
namespace compositors::sway {
[[nodiscard]] bool setOutputPower(bool on);
+16
View File
@@ -3,6 +3,7 @@
#include "compositors/compositor_detect.h"
#include "compositors/niri/niri_output_backend.h"
#include "compositors/niri/niri_workspace_backend.h"
#include "compositors/sway/sway_output_backend.h"
#include "core/log.h"
#include "cursor-shape-v1-client-protocol.h"
#include "dwl-ipc-unstable-v2-client-protocol.h"
@@ -204,6 +205,7 @@ bool WaylandConnection::connect() {
const std::string compositorHint(compositors::envHint());
m_workspacesHandler.initialize(compositorHint);
m_niriOutputBackend = std::make_unique<NiriOutputBackend>(compositorHint);
m_swayOutputBackend = std::make_unique<SwayOutputBackend>(compositorHint);
m_niriWorkspaceBackend = std::make_unique<NiriWorkspaceBackend>(compositorHint);
logStartupSummary();
return true;
@@ -329,6 +331,19 @@ wl_output* WaylandConnection::preferredPanelOutput(std::chrono::milliseconds poi
}
}
if (m_swayOutputBackend != nullptr && m_swayOutputBackend->isAvailable()) {
if (const auto focusedName = m_swayOutputBackend->focusedOutputName(); focusedName.has_value()) {
for (const auto& output : m_outputs) {
if (output.output == nullptr) {
continue;
}
if (output.connectorName == *focusedName || output.description == *focusedName) {
return output.output;
}
}
}
}
if (wl_output* output = activeToplevelOutput(); output != nullptr) {
return output;
}
@@ -1103,6 +1118,7 @@ void WaylandConnection::cleanup() {
m_hasMangoWorkspaceGlobal = false;
m_hasForeignToplevelManagerGlobal = false;
m_niriOutputBackend.reset();
m_swayOutputBackend.reset();
}
void WaylandConnection::logStartupSummary() const {
+2
View File
@@ -43,6 +43,7 @@ class ClipboardService;
class FocusGrabService;
class NiriOutputBackend;
class NiriWorkspaceBackend;
class SwayOutputBackend;
struct DataControlOps;
class VirtualKeyboardService;
@@ -244,6 +245,7 @@ private:
wl_output* m_lastPointerOutput = nullptr;
std::chrono::steady_clock::time_point m_lastPointerOutputAt{};
std::unique_ptr<NiriOutputBackend> m_niriOutputBackend;
std::unique_ptr<SwayOutputBackend> m_swayOutputBackend;
std::unique_ptr<NiriWorkspaceBackend> m_niriWorkspaceBackend;
WaylandSeat::PointerEventCallback m_pointerEventCallback;