feat(widgets): add idle inhibitor

This commit is contained in:
Lysec
2026-04-09 14:16:02 +02:00
parent 235004a1b9
commit f0422efe72
15 changed files with 395 additions and 9 deletions
+25
View File
@@ -71,6 +71,8 @@ set(XDG_ACTIVATION_XML
"${WAYLAND_PROTOCOLS_PKGDATADIR}/staging/xdg-activation/xdg-activation-v1.xml")
set(EXT_SESSION_LOCK_XML
"${WAYLAND_PROTOCOLS_PKGDATADIR}/staging/ext-session-lock/ext-session-lock-v1.xml")
set(IDLE_INHIBIT_XML
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml")
set(WLR_FOREIGN_TOPLEVEL_XML
"${CMAKE_CURRENT_SOURCE_DIR}/protocols/wlr-foreign-toplevel-management-unstable-v1.xml")
set(WLR_DATA_CONTROL_XML
@@ -110,6 +112,10 @@ set(EXT_SESSION_LOCK_PROTOCOL_C
"${GENERATED_PROTOCOL_DIR}/ext-session-lock-v1-client-protocol.c")
set(EXT_SESSION_LOCK_PROTOCOL_H
"${GENERATED_PROTOCOL_DIR}/ext-session-lock-v1-client-protocol.h")
set(IDLE_INHIBIT_PROTOCOL_C
"${GENERATED_PROTOCOL_DIR}/idle-inhibit-unstable-v1-client-protocol.c")
set(IDLE_INHIBIT_PROTOCOL_H
"${GENERATED_PROTOCOL_DIR}/idle-inhibit-unstable-v1-client-protocol.h")
set(WLR_FOREIGN_TOPLEVEL_PROTOCOL_C
"${GENERATED_PROTOCOL_DIR}/wlr-foreign-toplevel-management-unstable-v1-client-protocol.c")
set(WLR_FOREIGN_TOPLEVEL_PROTOCOL_H
@@ -262,6 +268,20 @@ add_custom_command(
VERBATIM
)
add_custom_command(
OUTPUT "${IDLE_INHIBIT_PROTOCOL_C}"
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${IDLE_INHIBIT_XML}" "${IDLE_INHIBIT_PROTOCOL_C}"
DEPENDS "${IDLE_INHIBIT_XML}"
VERBATIM
)
add_custom_command(
OUTPUT "${IDLE_INHIBIT_PROTOCOL_H}"
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" client-header "${IDLE_INHIBIT_XML}" "${IDLE_INHIBIT_PROTOCOL_H}"
DEPENDS "${IDLE_INHIBIT_XML}"
VERBATIM
)
add_custom_command(
OUTPUT "${WLR_FOREIGN_TOPLEVEL_PROTOCOL_C}"
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${WLR_FOREIGN_TOPLEVEL_XML}" "${WLR_FOREIGN_TOPLEVEL_PROTOCOL_C}"
@@ -310,6 +330,8 @@ add_custom_target(noctalia_wayland_protocols
"${XDG_ACTIVATION_PROTOCOL_H}"
"${EXT_SESSION_LOCK_PROTOCOL_C}"
"${EXT_SESSION_LOCK_PROTOCOL_H}"
"${IDLE_INHIBIT_PROTOCOL_C}"
"${IDLE_INHIBIT_PROTOCOL_H}"
"${WLR_FOREIGN_TOPLEVEL_PROTOCOL_C}"
"${WLR_FOREIGN_TOPLEVEL_PROTOCOL_H}"
"${WLR_DATA_CONTROL_PROTOCOL_C}"
@@ -336,6 +358,7 @@ add_executable(noctalia
src/dbus/upower/upower_service.cpp
src/debug/debug_service.cpp
src/font/font_service.cpp
src/idle/idle_inhibitor.cpp
src/ipc/ipc_client.cpp
src/ipc/ipc_service.cpp
src/launcher/app_provider.cpp
@@ -398,6 +421,7 @@ add_executable(noctalia
src/shell/widgets/active_window_widget.cpp
src/shell/widgets/battery_widget.cpp
src/shell/widgets/clock_widget.cpp
src/shell/widgets/idle_inhibitor_widget.cpp
src/shell/widgets/launcher_widget.cpp
src/shell/widgets/media_mini_widget.cpp
src/shell/widgets/notification_widget.cpp
@@ -455,6 +479,7 @@ add_executable(noctalia
"${EXT_DATA_CONTROL_PROTOCOL_C}"
"${XDG_ACTIVATION_PROTOCOL_C}"
"${EXT_SESSION_LOCK_PROTOCOL_C}"
"${IDLE_INHIBIT_PROTOCOL_C}"
"${WLR_FOREIGN_TOPLEVEL_PROTOCOL_C}"
"${WLR_DATA_CONTROL_PROTOCOL_C}"
)
+18
View File
@@ -232,6 +232,24 @@ No configurable settings.
---
### `idle_inhibitor`
Shows a keep-awake glyph and toggles the compositor idle inhibitor on click.
This uses the standard Wayland `zwp_idle_inhibit_manager_v1` protocol when available.
No configurable settings.
You can also control it over Noctalia IPC:
```sh
noctalia-ipc enable-idle-inhibitor
noctalia-ipc disable-idle-inhibitor
noctalia-ipc toggle-idle-inhibitor
```
---
### `sysmon`
System resource monitor. Shows an icon and value for one configurable stat. Multiple instances with different stats can coexist on the same bar.
+1 -1
View File
@@ -178,7 +178,7 @@ gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug
- [ ] PipeWire audio spectrum
- [~] Clipboard manager <- missing auto-paste /
- [~] Lock screen (ext-session-lock-v1) <- still needs polish
- [ ] Idle inhibitor (prevent sleep)
- [x] Idle inhibitor (prevent sleep)
- [~] More compositors (Labwc pending)
- [ ] Application file search provider
+37 -1
View File
@@ -221,6 +221,9 @@ void Application::initServices() {
m_wayland.setWorkspaceChangeCallback([this]() { m_bar.refresh(); });
m_wayland.setToplevelChangeCallback([this]() { m_bar.refresh(); });
m_idleInhibitor.initialize(m_wayland, &m_renderContext);
m_idleInhibitor.setChangeCallback([this]() { m_bar.refresh(); });
m_wallpaper.initialize(m_wayland, &m_configService, &m_stateService);
m_overview.initialize(m_wayland, &m_configService, &m_stateService, &m_wallpaper);
@@ -418,7 +421,7 @@ void Application::initUi() {
m_bar.initialize(m_wayland, &m_configService, &m_timeService, &m_notificationManager, m_trayService.get(),
m_pipewireService.get(), m_upowerService.get(), m_systemMonitor.get(), m_powerProfilesService.get(),
m_mprisService.get(), &m_httpClient, &m_weatherService, &m_renderContext);
&m_idleInhibitor, m_mprisService.get(), &m_httpClient, &m_weatherService, &m_renderContext);
if (m_pipewireService != nullptr) {
m_audioOsd.suppressFor(std::chrono::milliseconds(2000));
@@ -571,6 +574,39 @@ void Application::initIpc() {
return "ok\n";
},
"toggle-clipboard", "Toggle the clipboard history panel");
m_ipcService.registerHandler(
"enable-idle-inhibitor",
[this](const std::string&) -> std::string {
if (!m_idleInhibitor.available()) {
return "error: idle inhibitor protocol unavailable\n";
}
m_idleInhibitor.setEnabled(true);
return "ok\n";
},
"enable-idle-inhibitor", "Enable the compositor idle inhibitor");
m_ipcService.registerHandler(
"disable-idle-inhibitor",
[this](const std::string&) -> std::string {
if (!m_idleInhibitor.available()) {
return "error: idle inhibitor protocol unavailable\n";
}
m_idleInhibitor.setEnabled(false);
return "ok\n";
},
"disable-idle-inhibitor", "Disable the compositor idle inhibitor");
m_ipcService.registerHandler(
"toggle-idle-inhibitor",
[this](const std::string&) -> std::string {
if (!m_idleInhibitor.available()) {
return "error: idle inhibitor protocol unavailable\n";
}
m_idleInhibitor.toggle();
return "ok\n";
},
"toggle-idle-inhibitor", "Toggle the compositor idle inhibitor");
}
std::vector<PollSource*> Application::buildPollSources() {
+2
View File
@@ -17,6 +17,7 @@
#include "dbus/tray/tray_service.h"
#include "dbus/upower/upower_service.h"
#include "debug/debug_service.h"
#include "idle/idle_inhibitor.h"
#include "ipc/ipc_poll_source.h"
#include "ipc/ipc_service.h"
#include "net/http_client.h"
@@ -78,6 +79,7 @@ private:
std::unique_ptr<SystemBus> m_systemBus;
std::unique_ptr<SystemMonitorService> m_systemMonitor;
std::unique_ptr<DebugService> m_debugService;
IdleInhibitor m_idleInhibitor;
std::unique_ptr<MprisService> m_mprisService;
std::unique_ptr<PowerProfilesService> m_powerProfilesService;
std::unique_ptr<UPowerService> m_upowerService;
+122
View File
@@ -0,0 +1,122 @@
#include "idle/idle_inhibitor.h"
#include "core/log.h"
#include "wayland/layer_surface.h"
#include "wayland/wayland_connection.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include <wayland-client.h>
namespace {
constexpr Logger kLog("idle");
} // namespace
IdleInhibitor::IdleInhibitor() = default;
IdleInhibitor::~IdleInhibitor() {
destroyInhibitor();
m_surface.reset();
}
bool IdleInhibitor::initialize(WaylandConnection& wayland, RenderContext* renderContext) {
m_wayland = &wayland;
m_renderContext = renderContext;
m_manager = m_wayland->idleInhibitManager();
if (m_manager == nullptr) {
kLog.info("idle inhibit protocol unavailable");
}
return true;
}
void IdleInhibitor::toggle() { setEnabled(!m_enabled); }
void IdleInhibitor::setEnabled(bool enabled) {
if (m_enabled == enabled) {
return;
}
m_enabled = enabled;
syncInhibitor();
notifyChanged();
}
void IdleInhibitor::setChangeCallback(ChangeCallback callback) { m_changeCallback = std::move(callback); }
void IdleInhibitor::ensureSurface() {
if (m_surface != nullptr || m_wayland == nullptr || m_renderContext == nullptr || m_wayland->outputs().empty()) {
return;
}
const auto& output = m_wayland->outputs().front();
LayerSurfaceConfig config{
.nameSpace = "noctalia-idle-inhibitor",
.layer = LayerShellLayer::Overlay,
.anchor = LayerShellAnchor::Top | LayerShellAnchor::Left,
.width = 1,
.height = 1,
.exclusiveZone = 0,
.marginTop = 0,
.marginRight = 0,
.marginBottom = 0,
.marginLeft = 0,
.keyboard = LayerShellKeyboard::None,
.defaultWidth = 1,
.defaultHeight = 1,
};
auto surface = std::make_unique<LayerSurface>(*m_wayland, std::move(config));
surface->setRenderContext(m_renderContext);
surface->setConfigureCallback([](std::uint32_t /*width*/, std::uint32_t /*height*/) {});
if (!surface->initialize(output.output, output.scale)) {
kLog.warn("failed to initialize idle inhibitor surface");
return;
}
if (wl_region* region = wl_compositor_create_region(m_wayland->compositor()); region != nullptr) {
wl_surface_set_input_region(surface->wlSurface(), region);
wl_region_destroy(region);
wl_surface_commit(surface->wlSurface());
}
m_surface = std::move(surface);
}
void IdleInhibitor::syncInhibitor() {
if (m_manager == nullptr) {
return;
}
if (!m_enabled) {
destroyInhibitor();
return;
}
ensureSurface();
if (m_surface == nullptr || m_surface->wlSurface() == nullptr || m_inhibitor != nullptr) {
return;
}
m_inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(m_manager, m_surface->wlSurface());
if (m_inhibitor != nullptr) {
kLog.info("idle inhibitor enabled");
}
}
void IdleInhibitor::destroyInhibitor() {
if (m_inhibitor != nullptr) {
zwp_idle_inhibitor_v1_destroy(m_inhibitor);
m_inhibitor = nullptr;
kLog.info("idle inhibitor disabled");
}
}
void IdleInhibitor::notifyChanged() {
if (m_changeCallback) {
m_changeCallback();
}
}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include <functional>
#include <memory>
class LayerSurface;
class RenderContext;
class WaylandConnection;
struct zwp_idle_inhibit_manager_v1;
struct zwp_idle_inhibitor_v1;
class IdleInhibitor {
public:
using ChangeCallback = std::function<void()>;
IdleInhibitor();
~IdleInhibitor();
IdleInhibitor(const IdleInhibitor&) = delete;
IdleInhibitor& operator=(const IdleInhibitor&) = delete;
bool initialize(WaylandConnection& wayland, RenderContext* renderContext);
void toggle();
void setEnabled(bool enabled);
[[nodiscard]] bool enabled() const noexcept { return m_enabled; }
[[nodiscard]] bool available() const noexcept { return m_manager != nullptr; }
void setChangeCallback(ChangeCallback callback);
private:
void ensureSurface();
void syncInhibitor();
void destroyInhibitor();
void notifyChanged();
WaylandConnection* m_wayland = nullptr;
RenderContext* m_renderContext = nullptr;
zwp_idle_inhibit_manager_v1* m_manager = nullptr;
zwp_idle_inhibitor_v1* m_inhibitor = nullptr;
std::unique_ptr<LayerSurface> m_surface;
ChangeCallback m_changeCallback;
bool m_enabled = false;
};
+4 -3
View File
@@ -109,7 +109,7 @@ Bar::Bar() = default;
bool Bar::initialize(WaylandConnection& wayland, ConfigService* config, TimeService* timeService,
NotificationManager* notifications, TrayService* tray, PipeWireService* audio,
UPowerService* upower, SystemMonitorService* sysmon, PowerProfilesService* powerProfiles,
MprisService* mpris,
IdleInhibitor* idleInhibitor, MprisService* mpris,
HttpClient* httpClient, WeatherService* weatherService, RenderContext* renderContext) {
m_wayland = &wayland;
m_config = config;
@@ -120,13 +120,14 @@ bool Bar::initialize(WaylandConnection& wayland, ConfigService* config, TimeServ
m_upower = upower;
m_sysmon = sysmon;
m_powerProfiles = powerProfiles;
m_idleInhibitor = idleInhibitor;
m_mpris = mpris;
m_httpClient = httpClient;
m_weatherService = weatherService;
m_renderContext = renderContext;
m_widgetFactory = std::make_unique<WidgetFactory>(*m_wayland, m_time, m_config->config(), m_notifications, m_tray,
m_audio, m_upower, m_sysmon, m_powerProfiles, m_mpris, m_httpClient,
m_audio, m_upower, m_sysmon, m_powerProfiles, m_idleInhibitor, m_mpris, m_httpClient,
m_weatherService);
if (timeService != nullptr) {
@@ -153,7 +154,7 @@ bool Bar::initialize(WaylandConnection& wayland, ConfigService* config, TimeServ
void Bar::reload() {
kLog.info("reloading config");
m_widgetFactory = std::make_unique<WidgetFactory>(*m_wayland, m_time, m_config->config(), m_notifications, m_tray,
m_audio, m_upower, m_sysmon, m_powerProfiles, m_mpris, m_httpClient,
m_audio, m_upower, m_sysmon, m_powerProfiles, m_idleInhibitor, m_mpris, m_httpClient,
m_weatherService);
m_instances.clear();
m_surfaceMap.clear();
+3 -1
View File
@@ -9,6 +9,7 @@
class ConfigService;
class HttpClient;
class IdleInhibitor;
class MprisService;
class NotificationManager;
class PipeWireService;
@@ -30,7 +31,7 @@ public:
bool initialize(WaylandConnection& wayland, ConfigService* config, TimeService* timeService,
NotificationManager* notifications, TrayService* tray, PipeWireService* audio,
UPowerService* upower, SystemMonitorService* sysmon, PowerProfilesService* powerProfiles,
MprisService* mpris, HttpClient* httpClient, WeatherService* weatherService,
IdleInhibitor* idleInhibitor, MprisService* mpris, HttpClient* httpClient, WeatherService* weatherService,
RenderContext* renderContext);
void reload();
void closeAllInstances();
@@ -60,6 +61,7 @@ private:
UPowerService* m_upower = nullptr;
SystemMonitorService* m_sysmon = nullptr;
PowerProfilesService* m_powerProfiles = nullptr;
IdleInhibitor* m_idleInhibitor = nullptr;
MprisService* m_mpris = nullptr;
HttpClient* m_httpClient = nullptr;
WeatherService* m_weatherService = nullptr;
+10 -2
View File
@@ -5,11 +5,13 @@
#include "dbus/power/power_profiles_service.h"
#include "dbus/mpris/mpris_service.h"
#include "dbus/tray/tray_service.h"
#include "idle/idle_inhibitor.h"
#include "net/http_client.h"
#include "notification/notification_manager.h"
#include "shell/widgets/active_window_widget.h"
#include "shell/widgets/battery_widget.h"
#include "shell/widgets/clock_widget.h"
#include "shell/widgets/idle_inhibitor_widget.h"
#include "shell/widgets/launcher_widget.h"
#include "shell/widgets/media_mini_widget.h"
#include "shell/widgets/notification_widget.h"
@@ -29,9 +31,9 @@
WidgetFactory::WidgetFactory(WaylandConnection& wayland, TimeService* time, const Config& config,
NotificationManager* notifications, TrayService* tray, PipeWireService* audio,
UPowerService* upower, SystemMonitorService* sysmon, PowerProfilesService* powerProfiles,
MprisService* mpris, HttpClient* httpClient, WeatherService* weather)
IdleInhibitor* idleInhibitor, MprisService* mpris, HttpClient* httpClient, WeatherService* weather)
: m_wayland(wayland), m_time(time), m_config(config), m_notifications(notifications), m_tray(tray), m_audio(audio),
m_upower(upower), m_sysmon(sysmon), m_powerProfiles(powerProfiles), m_mpris(mpris), m_httpClient(httpClient),
m_upower(upower), m_sysmon(sysmon), m_powerProfiles(powerProfiles), m_idleInhibitor(idleInhibitor), m_mpris(mpris), m_httpClient(httpClient),
m_weather(weather) {}
std::unique_ptr<Widget> WidgetFactory::create(const std::string& name, wl_output* output, float contentScale) const {
@@ -119,6 +121,12 @@ std::unique_ptr<Widget> WidgetFactory::create(const std::string& name, wl_output
return widget;
}
if (type == "idle_inhibitor") {
auto widget = std::make_unique<IdleInhibitorWidget>(m_idleInhibitor);
widget->setContentScale(contentScale);
return widget;
}
if (type == "volume") {
std::int32_t scale = 1;
const auto* wlOutput = m_wayland.findOutputByWl(output);
+3 -1
View File
@@ -8,6 +8,7 @@
struct Config;
class NotificationManager;
class HttpClient;
class IdleInhibitor;
class MprisService;
class PipeWireService;
class PowerProfilesService;
@@ -23,7 +24,7 @@ class WidgetFactory {
public:
WidgetFactory(WaylandConnection& wayland, TimeService* time, const Config& config, NotificationManager* notifications,
TrayService* tray, PipeWireService* audio, UPowerService* upower, SystemMonitorService* sysmon,
PowerProfilesService* powerProfiles, MprisService* mpris, HttpClient* httpClient,
PowerProfilesService* powerProfiles, IdleInhibitor* idleInhibitor, MprisService* mpris, HttpClient* httpClient,
WeatherService* weather);
[[nodiscard]] std::unique_ptr<Widget> create(const std::string& name, wl_output* output,
@@ -39,6 +40,7 @@ private:
UPowerService* m_upower;
SystemMonitorService* m_sysmon;
PowerProfilesService* m_powerProfiles;
IdleInhibitor* m_idleInhibitor;
MprisService* m_mpris;
HttpClient* m_httpClient;
WeatherService* m_weather;
@@ -0,0 +1,84 @@
#include "shell/widgets/idle_inhibitor_widget.h"
#include "idle/idle_inhibitor.h"
#include "render/core/renderer.h"
#include "render/scene/input_area.h"
#include "ui/controls/glyph.h"
#include "ui/palette.h"
#include "ui/style.h"
#include <memory>
namespace {
const char* glyphForState(bool enabled) {
return enabled ? "keep-awake-on" : "keep-awake-off";
}
} // namespace
IdleInhibitorWidget::IdleInhibitorWidget(IdleInhibitor* inhibitor) : m_inhibitor(inhibitor) {}
void IdleInhibitorWidget::create() {
auto area = std::make_unique<InputArea>();
area->setOnClick([this](const InputArea::PointerData& /*data*/) {
if (m_inhibitor != nullptr && m_inhibitor->available()) {
m_inhibitor->toggle();
}
});
m_area = area.get();
auto glyph = std::make_unique<Glyph>();
glyph->setGlyph(glyphForState(false));
glyph->setGlyphSize(Style::fontSizeBody * m_contentScale);
glyph->setColor(palette.onSurfaceVariant);
m_glyph = glyph.get();
area->addChild(std::move(glyph));
setRoot(std::move(area));
}
void IdleInhibitorWidget::layout(Renderer& renderer, float /*containerWidth*/, float /*containerHeight*/) {
if (m_glyph == nullptr) {
return;
}
syncState(renderer);
m_glyph->setGlyphSize(Style::fontSizeBody * m_contentScale);
m_glyph->measure(renderer);
if (auto* node = root(); node != nullptr) {
node->setSize(m_glyph->width(), m_glyph->height());
}
}
void IdleInhibitorWidget::update(Renderer& renderer) {
syncState(renderer);
Widget::update(renderer);
}
void IdleInhibitorWidget::syncState(Renderer& renderer) {
if (m_glyph == nullptr || m_area == nullptr) {
return;
}
const bool available = m_inhibitor != nullptr && m_inhibitor->available();
const bool enabled = available && m_inhibitor->enabled();
if (available == m_lastAvailable && enabled == m_lastEnabled) {
return;
}
m_lastAvailable = available;
m_lastEnabled = enabled;
m_glyph->setGlyph(glyphForState(enabled));
m_glyph->setGlyphSize(Style::fontSizeBody * m_contentScale);
m_glyph->setColor(!available ? palette.onSurfaceVariant : (enabled ? palette.primary : palette.onSurface));
m_glyph->measure(renderer);
m_area->setEnabled(available);
if (auto* node = root(); node != nullptr) {
node->setOpacity(available ? 1.0f : 0.55f);
}
requestRedraw();
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "shell/widget/widget.h"
class Glyph;
class IdleInhibitor;
class InputArea;
class IdleInhibitorWidget : public Widget {
public:
explicit IdleInhibitorWidget(IdleInhibitor* inhibitor);
void create() override;
void layout(Renderer& renderer, float containerWidth, float containerHeight) override;
void update(Renderer& renderer) override;
private:
void syncState(Renderer& renderer);
IdleInhibitor* m_inhibitor = nullptr;
InputArea* m_area = nullptr;
Glyph* m_glyph = nullptr;
bool m_lastEnabled = false;
bool m_lastAvailable = false;
};
+15
View File
@@ -14,6 +14,7 @@
#include "ext-data-control-v1-client-protocol.h"
#include "ext-session-lock-v1-client-protocol.h"
#include "ext-workspace-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "wlr-data-control-unstable-v1-client-protocol.h"
#include "wlr-foreign-toplevel-management-unstable-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
@@ -32,6 +33,7 @@ namespace {
constexpr std::uint32_t kCursorShapeManagerVersion = 1;
constexpr std::uint32_t kXdgActivationVersion = 1;
constexpr std::uint32_t kExtSessionLockManagerVersion = 1;
constexpr std::uint32_t kIdleInhibitManagerVersion = 1;
constexpr std::uint32_t kOutputVersion = 4;
const wl_registry_listener kRegistryListener = {
@@ -296,6 +298,7 @@ bool WaylandConnection::hasExtWorkspaceManager() const noexcept { return m_hasEx
bool WaylandConnection::hasMangoWorkspaceManager() const noexcept { return m_hasMangoWorkspaceGlobal; }
bool WaylandConnection::hasForeignToplevelManager() const noexcept { return m_hasForeignToplevelManagerGlobal; }
bool WaylandConnection::hasSessionLockManager() const noexcept { return m_sessionLockManager != nullptr; }
bool WaylandConnection::hasIdleInhibitManager() const noexcept { return m_idleInhibitManager != nullptr; }
bool WaylandConnection::hasXdgActivation() const noexcept { return m_xdgActivation != nullptr; }
std::string WaylandConnection::requestActivationToken(wl_surface* surface) const {
@@ -338,6 +341,7 @@ wl_shm* WaylandConnection::shm() const noexcept { return m_shm; }
zwlr_layer_shell_v1* WaylandConnection::layerShell() const noexcept { return m_layerShell; }
ext_session_lock_manager_v1* WaylandConnection::sessionLockManager() const noexcept { return m_sessionLockManager; }
zwp_idle_inhibit_manager_v1* WaylandConnection::idleInhibitManager() const noexcept { return m_idleInhibitManager; }
const std::vector<WaylandOutput>& WaylandConnection::outputs() const noexcept { return m_outputs; }
@@ -474,6 +478,13 @@ void WaylandConnection::bindGlobal(wl_registry* registry, std::uint32_t name, co
return;
}
if (interfaceName == zwp_idle_inhibit_manager_v1_interface.name) {
const auto bindVersion = std::min(version, kIdleInhibitManagerVersion);
m_idleInhibitManager = static_cast<zwp_idle_inhibit_manager_v1*>(
wl_registry_bind(registry, name, &zwp_idle_inhibit_manager_v1_interface, bindVersion));
return;
}
if (interfaceName == ext_data_control_manager_v1_interface.name) {
if (m_dataControlManager != nullptr && m_dataControlOps != extDataControlOps()) {
m_dataControlOps->destroyManager(m_dataControlManager);
@@ -562,6 +573,10 @@ void WaylandConnection::cleanup() {
ext_session_lock_manager_v1_destroy(m_sessionLockManager);
m_sessionLockManager = nullptr;
}
if (m_idleInhibitManager != nullptr) {
zwp_idle_inhibit_manager_v1_destroy(m_idleInhibitManager);
m_idleInhibitManager = nullptr;
}
if (m_dataControlManager != nullptr && m_dataControlOps != nullptr) {
m_dataControlOps->destroyManager(m_dataControlManager);
+4
View File
@@ -21,6 +21,7 @@ struct zwlr_layer_shell_v1;
struct zxdg_output_manager_v1;
struct zxdg_output_v1;
struct wp_cursor_shape_manager_v1;
struct zwp_idle_inhibit_manager_v1;
struct xdg_activation_v1;
struct ext_session_lock_manager_v1;
struct zwlr_foreign_toplevel_manager_v1;
@@ -85,11 +86,13 @@ public:
[[nodiscard]] bool hasMangoWorkspaceManager() const noexcept;
[[nodiscard]] bool hasForeignToplevelManager() const noexcept;
[[nodiscard]] bool hasSessionLockManager() const noexcept;
[[nodiscard]] bool hasIdleInhibitManager() const noexcept;
[[nodiscard]] wl_display* display() const noexcept;
[[nodiscard]] wl_compositor* compositor() const noexcept;
[[nodiscard]] wl_shm* shm() const noexcept;
[[nodiscard]] zwlr_layer_shell_v1* layerShell() const noexcept;
[[nodiscard]] ext_session_lock_manager_v1* sessionLockManager() const noexcept;
[[nodiscard]] zwp_idle_inhibit_manager_v1* idleInhibitManager() const noexcept;
[[nodiscard]] const std::vector<WaylandOutput>& outputs() const noexcept;
[[nodiscard]] WaylandOutput* findOutputByWl(wl_output* wlOutput);
[[nodiscard]] WaylandOutput* findOutputByXdg(zxdg_output_v1* xdgOutput);
@@ -128,6 +131,7 @@ private:
wp_cursor_shape_manager_v1* m_cursorShapeManager = nullptr;
xdg_activation_v1* m_xdgActivation = nullptr;
ext_session_lock_manager_v1* m_sessionLockManager = nullptr;
zwp_idle_inhibit_manager_v1* m_idleInhibitManager = nullptr;
void* m_dataControlManager = nullptr;
const DataControlOps* m_dataControlOps = nullptr;
ClipboardService* m_clipboardService = nullptr;