From 4e05659109f95652fcdb9b582ffc691dff503a46 Mon Sep 17 00:00:00 2001 From: Jan Larres Date: Sun, 1 Dec 2024 12:48:07 +1300 Subject: [PATCH 1/5] sway/workspaces: use X11 class for XWayland windows When using `window-rewrite`, the `class<>` rule would previously only match against the `app_id` of a window. However, XWayland windows don't have an app ID. This change falls back to checking the `class` window property if there is no app ID to support matching against XWayland windows. --- man/waybar-sway-workspaces.5.scd | 1 + src/modules/sway/workspaces.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/man/waybar-sway-workspaces.5.scd b/man/waybar-sway-workspaces.5.scd index a710ab50..1c4360e9 100644 --- a/man/waybar-sway-workspaces.5.scd +++ b/man/waybar-sway-workspaces.5.scd @@ -88,6 +88,7 @@ warp-on-scroll: ++ Keys are the rules, while the values are the methods of representation. Rules may specify `class<...>`, `title<...>`, or both in order to fine-tune the matching. You may assign an empty value to a rule to have it ignored from generating any representation in workspaces. + For Wayland windows `class` is matched against the `app_id`, and for X11 windows against the `class` property. *window-rewrite-default*: typeof: string ++ diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 8f273300..33d4bb29 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -260,7 +260,9 @@ void Workspaces::updateWindows(const Json::Value &node, std::string &windows) { if ((node["type"].asString() == "con" || node["type"].asString() == "floating_con") && node["name"].isString()) { std::string title = g_markup_escape_text(node["name"].asString().c_str(), -1); - std::string windowClass = node["app_id"].asString(); + std::string windowClass = node["app_id"].isString() + ? node["app_id"].asString() + : node["window_properties"]["class"].asString(); // Only add window rewrites that can be looked up if (!windowClass.empty()) { From 0e5728b53388de6104bc6a644009fa87e3008ee9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 1 Dec 2024 00:12:55 +0000 Subject: [PATCH 2/5] flake.lock: Update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flake lock file updates: • Updated input 'flake-compat': 'github:edolstra/flake-compat/0f9255e01c2351cc7d116c072cb317785dd33b33?narHash=sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U%3D' (2023-10-04) → 'github:edolstra/flake-compat/9ed2ac151eada2306ca8c418ebd97807bb08f6ac?narHash=sha256-HRJ/18p%2BWoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg%3D' (2024-11-27) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/807e9154dcb16384b1b765ebe9cd2bba2ac287fd?narHash=sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU%3D' (2024-10-29) → 'github:NixOS/nixpkgs/970e93b9f82e2a0f3675757eb0bfc73297cc6370?narHash=sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE%3D' (2024-11-28) --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index d0ca27b8..24b83454 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1732722421, + "narHash": "sha256-HRJ/18p+WoXpWJkcdsk9St5ZiukCqSDgbOGFa8Okehg=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac", "type": "github" }, "original": { @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730200266, - "narHash": "sha256-l253w0XMT8nWHGXuXqyiIC/bMvh1VRszGXgdpQlfhvU=", + "lastModified": 1732837521, + "narHash": "sha256-jNRNr49UiuIwaarqijgdTR2qLPifxsVhlJrKzQ8XUIE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "807e9154dcb16384b1b765ebe9cd2bba2ac287fd", + "rev": "970e93b9f82e2a0f3675757eb0bfc73297cc6370", "type": "github" }, "original": { From 6d28740896b33005cfe6344719bcebb8de0cabfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Tue, 3 Dec 2024 19:37:36 +0100 Subject: [PATCH 3/5] Add locking for interacting with the pulseaudio thread Before this commit, Waybar would sometimes get into a state where it would consume 100% of a CPU core, and the pulseaudio widget would stop responding to volume adjustments. In this state, the pulseaudio mainloop thread would spin, with the counter of enabled defer events at 1, but no actual enabled defer event in the list to get the counter back to zero after an iteration in the mainloop. This could happen if the unsynchronized interactions with the mainloop thread happened to modify the list of deferred events at the same time as the mainloop. This commit introduces locking in accordance with the PulseAudio documentation on the threaded mainloop: > The lock needs to be held whenever you call any PulseAudio function that > uses an object associated with this main loop. Those objects include > pa_mainloop, pa_context, pa_stream and pa_operation, and the various event > objects (pa_io_event, pa_time_event, pa_defer_event). --- src/util/audio_backend.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/util/audio_backend.cpp b/src/util/audio_backend.cpp index 73aac148..807b5dc7 100644 --- a/src/util/audio_backend.cpp +++ b/src/util/audio_backend.cpp @@ -236,7 +236,9 @@ void AudioBackend::changeVolume(uint16_t volume, uint16_t min_volume, uint16_t m volume = std::clamp(volume, min_volume, max_volume); pa_cvolume_set(&pa_volume, pa_volume_.channels, volume * volume_tick); + pa_threaded_mainloop_lock(mainloop_); pa_context_set_sink_volume_by_index(context_, sink_idx_, &pa_volume, volumeModifyCb, this); + pa_threaded_mainloop_unlock(mainloop_); } void AudioBackend::changeVolume(ChangeType change_type, double step, uint16_t max_volume) { @@ -265,31 +267,41 @@ void AudioBackend::changeVolume(ChangeType change_type, double step, uint16_t ma pa_cvolume_dec(&pa_volume, change); } } + pa_threaded_mainloop_lock(mainloop_); pa_context_set_sink_volume_by_index(context_, sink_idx_, &pa_volume, volumeModifyCb, this); + pa_threaded_mainloop_unlock(mainloop_); } void AudioBackend::toggleSinkMute() { muted_ = !muted_; + pa_threaded_mainloop_lock(mainloop_); pa_context_set_sink_mute_by_index(context_, sink_idx_, static_cast(muted_), nullptr, nullptr); + pa_threaded_mainloop_unlock(mainloop_); } void AudioBackend::toggleSinkMute(bool mute) { muted_ = mute; + pa_threaded_mainloop_lock(mainloop_); pa_context_set_sink_mute_by_index(context_, sink_idx_, static_cast(muted_), nullptr, nullptr); + pa_threaded_mainloop_unlock(mainloop_); } void AudioBackend::toggleSourceMute() { source_muted_ = !muted_; + pa_threaded_mainloop_lock(mainloop_); pa_context_set_source_mute_by_index(context_, source_idx_, static_cast(source_muted_), nullptr, nullptr); + pa_threaded_mainloop_unlock(mainloop_); } void AudioBackend::toggleSourceMute(bool mute) { source_muted_ = mute; + pa_threaded_mainloop_lock(mainloop_); pa_context_set_source_mute_by_index(context_, source_idx_, static_cast(source_muted_), nullptr, nullptr); + pa_threaded_mainloop_unlock(mainloop_); } bool AudioBackend::isBluetooth() { From 6bac784b51bc319bba7ab91bc1cc5ee8815a2cae Mon Sep 17 00:00:00 2001 From: eritque0arcus Date: Wed, 4 Dec 2024 12:46:09 -0600 Subject: [PATCH 4/5] fix: use auto and add self as fallback --- src/util/backlight_backend.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/util/backlight_backend.cpp b/src/util/backlight_backend.cpp index bb102cd9..41236462 100644 --- a/src/util/backlight_backend.cpp +++ b/src/util/backlight_backend.cpp @@ -153,7 +153,13 @@ BacklightBackend::BacklightBackend(std::chrono::milliseconds interval, // Connect to the login interface login_proxy_ = Gio::DBus::Proxy::create_for_bus_sync( Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.login1", - "/org/freedesktop/login1/session/self", "org.freedesktop.login1.Session"); + "/org/freedesktop/login1/session/auto", "org.freedesktop.login1.Session"); + + if (!login_proxy_) { + login_proxy_ = Gio::DBus::Proxy::create_for_bus_sync( + Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.login1", + "/org/freedesktop/login1/session/self", "org.freedesktop.login1.Session"); + } udev_thread_ = [this] { std::unique_ptr udev{udev_new()}; From db943dae9817d989031cf06309d759f8a7416284 Mon Sep 17 00:00:00 2001 From: Gustaf Ullberg Date: Thu, 5 Dec 2024 15:15:33 +0100 Subject: [PATCH 5/5] Let network module handle ipv4 and ipv6 simultaneously --- include/modules/network.hpp | 1 - src/modules/network.cpp | 34 +++++++--------------------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/include/modules/network.hpp b/include/modules/network.hpp index 4a84b02f..df0ba9c3 100644 --- a/include/modules/network.hpp +++ b/include/modules/network.hpp @@ -50,7 +50,6 @@ class Network : public ALabel { std::optional> readBandwidthUsage(); int ifid_; - sa_family_t family_; struct sockaddr_nl nladdr_ = {0}; struct nl_sock* sock_ = nullptr; struct nl_sock* ev_sock_ = nullptr; diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 0bbea631..393b4296 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -80,7 +80,6 @@ waybar::modules::Network::readBandwidthUsage() { waybar::modules::Network::Network(const std::string &id, const Json::Value &config) : ALabel(config, "network", id, DEFAULT_FORMAT, 60), ifid_(-1), - family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET), efd_(-1), ev_fd_(-1), want_route_dump_(false), @@ -141,12 +140,7 @@ waybar::modules::Network::~Network() { close(efd_); } if (ev_sock_ != nullptr) { - nl_socket_drop_membership(ev_sock_, RTNLGRP_LINK); - if (family_ == AF_INET) { - nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV4_IFADDR); - } else { - nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV6_IFADDR); - } + nl_socket_drop_memberships(ev_sock_, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR); nl_close(ev_sock_); nl_socket_free(ev_sock_); } @@ -161,7 +155,7 @@ void waybar::modules::Network::createEventSocket() { nl_socket_disable_seq_check(ev_sock_); nl_socket_modify_cb(ev_sock_, NL_CB_VALID, NL_CB_CUSTOM, handleEvents, this); nl_socket_modify_cb(ev_sock_, NL_CB_FINISH, NL_CB_CUSTOM, handleEventsDone, this); - auto groups = RTMGRP_LINK | (family_ == AF_INET ? RTMGRP_IPV4_IFADDR : RTMGRP_IPV6_IFADDR); + auto groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; nl_join_groups(ev_sock_, groups); // Deprecated if (nl_connect(ev_sock_, NETLINK_ROUTE) != 0) { throw std::runtime_error("Can't connect network socket"); @@ -169,18 +163,9 @@ void waybar::modules::Network::createEventSocket() { if (nl_socket_set_nonblocking(ev_sock_)) { throw std::runtime_error("Can't set non-blocking on network socket"); } - nl_socket_add_membership(ev_sock_, RTNLGRP_LINK); - if (family_ == AF_INET) { - nl_socket_add_membership(ev_sock_, RTNLGRP_IPV4_IFADDR); - } else { - nl_socket_add_membership(ev_sock_, RTNLGRP_IPV6_IFADDR); - } + nl_socket_add_memberships(ev_sock_, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, 0); if (!config_["interface"].isString()) { - if (family_ == AF_INET) { - nl_socket_add_membership(ev_sock_, RTNLGRP_IPV4_ROUTE); - } else { - nl_socket_add_membership(ev_sock_, RTNLGRP_IPV6_ROUTE); - } + nl_socket_add_memberships(ev_sock_, RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV6_ROUTE, 0); } efd_ = epoll_create1(EPOLL_CLOEXEC); @@ -531,10 +516,6 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { return NL_OK; } - if (ifa->ifa_family != net->family_) { - return NL_OK; - } - // We ignore address mark as scope for the link or host, // which should leave scope global addresses. if (ifa->ifa_scope >= RT_SCOPE_LINK) { @@ -591,6 +572,7 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { // to find the interface used to reach the outside world struct rtmsg *rtm = static_cast(NLMSG_DATA(nh)); + int family = rtm->rtm_family; ssize_t attrlen = RTM_PAYLOAD(nh); struct rtattr *attr = RTM_RTA(rtm); bool has_gateway = false; @@ -618,14 +600,14 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { * If someone ever needs to figure out the gateway address as well, * it's here as the attribute payload. */ - inet_ntop(net->family_, RTA_DATA(attr), temp_gw_addr, sizeof(temp_gw_addr)); + inet_ntop(family, RTA_DATA(attr), temp_gw_addr, sizeof(temp_gw_addr)); has_gateway = true; break; case RTA_DST: { /* The destination address. * Should be either missing, or maybe all 0s. Accept both. */ - const uint32_t nr_zeroes = (net->family_ == AF_INET) ? 4 : 16; + const uint32_t nr_zeroes = (family == AF_INET) ? 4 : 16; unsigned char c = 0; size_t dstlen = RTA_PAYLOAD(attr); if (dstlen != nr_zeroes) { @@ -717,7 +699,6 @@ void waybar::modules::Network::askForStateDump(void) { }; if (want_route_dump_) { - rt_hdr.rtgen_family = family_; nl_send_simple(ev_sock_, RTM_GETROUTE, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); want_route_dump_ = false; dump_in_progress_ = true; @@ -728,7 +709,6 @@ void waybar::modules::Network::askForStateDump(void) { dump_in_progress_ = true; } else if (want_addr_dump_) { - rt_hdr.rtgen_family = family_; nl_send_simple(ev_sock_, RTM_GETADDR, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); want_addr_dump_ = false; dump_in_progress_ = true;