mirror of
https://github.com/rad4day/Waybar.git
synced 2025-09-18 08:22:32 +02:00
Fix merge conflict with #2930
This commit is contained in:
@@ -53,8 +53,8 @@ waybar::modules::Cava::Cava(const std::string& id, const Json::Value& config)
|
||||
if (config_["method"].isString())
|
||||
prm_.input = cava::input_method_by_name(config_["method"].asString().c_str());
|
||||
if (config_["source"].isString()) prm_.audio_source = config_["source"].asString().data();
|
||||
if (config_["sample_rate"].isNumeric()) prm_.fifoSample = config_["sample_rate"].asLargestInt();
|
||||
if (config_["sample_bits"].isInt()) prm_.fifoSampleBits = config_["sample_bits"].asInt();
|
||||
if (config_["sample_rate"].isNumeric()) prm_.samplerate = config_["sample_rate"].asLargestInt();
|
||||
if (config_["sample_bits"].isInt()) prm_.samplebits = config_["sample_bits"].asInt();
|
||||
if (config_["stereo"].isBool()) prm_.stereo = config_["stereo"].asBool();
|
||||
if (config_["reverse"].isBool()) prm_.reverse = config_["reverse"].asBool();
|
||||
if (config_["bar_delimiter"].isInt()) prm_.bar_delim = config_["bar_delimiter"].asInt();
|
||||
|
@@ -2,8 +2,10 @@
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
#include "util/ustring_clen.hpp"
|
||||
|
||||
@@ -20,7 +22,8 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||
tlpFmt_{(config_["tooltip-format"].isString()) ? config_["tooltip-format"].asString() : ""},
|
||||
cldInTooltip_{tlpFmt_.find("{" + kCldPlaceholder + "}") != std::string::npos},
|
||||
tzInTooltip_{tlpFmt_.find("{" + kTZPlaceholder + "}") != std::string::npos},
|
||||
tzCurrIdx_{0} {
|
||||
tzCurrIdx_{0},
|
||||
ordInTooltip_{tlpFmt_.find("{" + kOrdPlaceholder + "}") != std::string::npos} {
|
||||
tlpText_ = tlpFmt_;
|
||||
|
||||
if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
|
||||
@@ -127,7 +130,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||
}
|
||||
|
||||
auto waybar::modules::Clock::update() -> void {
|
||||
auto tz{tzList_[tzCurrIdx_] ?: current_zone()};
|
||||
const auto* tz = tzList_[tzCurrIdx_] != nullptr ? tzList_[tzCurrIdx_] : current_zone();
|
||||
const zoned_time now{tz, floor<seconds>(system_clock::now())};
|
||||
|
||||
label_.set_markup(fmt_lib::vformat(locale_, format_, fmt_lib::make_format_args(now)));
|
||||
@@ -140,11 +143,14 @@ auto waybar::modules::Clock::update() -> void {
|
||||
|
||||
if (tzInTooltip_) tzText_ = getTZtext(now.get_sys_time());
|
||||
if (cldInTooltip_) cldText_ = get_calendar(today, shiftedDay, tz);
|
||||
if (tzInTooltip_ || cldInTooltip_) {
|
||||
if (ordInTooltip_) ordText_ = get_ordinal_date(shiftedDay);
|
||||
if (tzInTooltip_ || cldInTooltip_ || ordInTooltip_) {
|
||||
// std::vformat doesn't support named arguments.
|
||||
tlpText_ = std::regex_replace(tlpFmt_, std::regex("\\{" + kTZPlaceholder + "\\}"), tzText_);
|
||||
tlpText_ =
|
||||
std::regex_replace(tlpText_, std::regex("\\{" + kCldPlaceholder + "\\}"), cldText_);
|
||||
tlpText_ =
|
||||
std::regex_replace(tlpText_, std::regex("\\{" + kOrdPlaceholder + "\\}"), ordText_);
|
||||
}
|
||||
|
||||
tlpText_ = fmt_lib::vformat(locale_, tlpText_, fmt_lib::make_format_args(shiftedNow));
|
||||
@@ -161,7 +167,8 @@ auto waybar::modules::Clock::getTZtext(sys_seconds now) -> std::string {
|
||||
std::stringstream os;
|
||||
for (size_t tz_idx{0}; tz_idx < tzList_.size(); ++tz_idx) {
|
||||
if (static_cast<int>(tz_idx) == tzCurrIdx_) continue;
|
||||
auto zt{zoned_time{tzList_[tz_idx], now}};
|
||||
const auto* tz = tzList_[tz_idx] != nullptr ? tzList_[tz_idx] : current_zone();
|
||||
auto zt{zoned_time{tz, now}};
|
||||
os << fmt_lib::vformat(locale_, format_, fmt_lib::make_format_args(zt)) << '\n';
|
||||
}
|
||||
|
||||
@@ -214,22 +221,22 @@ auto getCalendarLine(const year_month_day& currDate, const year_month ym, const
|
||||
}
|
||||
// Print first week prefixed with spaces if necessary
|
||||
case 2: {
|
||||
auto d{day{1}};
|
||||
auto wd{weekday{ym / 1}};
|
||||
os << std::string((wd - firstdow).count() * 3, ' ');
|
||||
|
||||
if (currDate != ym / 1d)
|
||||
os << date::format(*locale_, "{:L%e}", 1d);
|
||||
if (currDate != ym / d)
|
||||
os << date::format(*locale_, "{:L%e}", d);
|
||||
else
|
||||
os << "{today}";
|
||||
|
||||
auto d{2d};
|
||||
while (++wd != firstdow) {
|
||||
++d;
|
||||
|
||||
if (currDate != ym / d)
|
||||
os << date::format(*locale_, " {:L%e}", d);
|
||||
else
|
||||
os << " {today}";
|
||||
|
||||
++d;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -437,3 +444,28 @@ auto waybar::modules::Clock::first_day_of_week() -> weekday {
|
||||
#endif
|
||||
return Sunday;
|
||||
}
|
||||
|
||||
auto waybar::modules::Clock::get_ordinal_date(const year_month_day& today) -> std::string {
|
||||
auto day = static_cast<unsigned int>(today.day());
|
||||
std::stringstream res;
|
||||
res << day;
|
||||
if (day >= 11 && day <= 13) {
|
||||
res << "th";
|
||||
return res.str();
|
||||
}
|
||||
|
||||
switch (day % 10) {
|
||||
case 1:
|
||||
res << "st";
|
||||
break;
|
||||
case 2:
|
||||
res << "nd";
|
||||
break;
|
||||
case 3:
|
||||
res << "rd";
|
||||
break;
|
||||
default:
|
||||
res << "th";
|
||||
}
|
||||
return res.str();
|
||||
}
|
@@ -1,15 +1,27 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <cmath> // NAN
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "modules/cpu_frequency.hpp"
|
||||
|
||||
std::vector<float> waybar::modules::CpuFrequency::parseCpuFrequencies() {
|
||||
static std::vector<float> frequencies;
|
||||
std::vector<float> frequencies;
|
||||
char buffer[256];
|
||||
size_t len;
|
||||
int32_t freq;
|
||||
uint32_t i = 0;
|
||||
|
||||
while (true) {
|
||||
len = 4;
|
||||
snprintf(buffer, 256, "dev.cpu.%u.freq", i);
|
||||
if (sysctlbyname(buffer, &freq, &len, NULL, 0) == -1 || len <= 0) break;
|
||||
frequencies.push_back(freq);
|
||||
++i;
|
||||
}
|
||||
|
||||
if (frequencies.empty()) {
|
||||
spdlog::warn(
|
||||
"cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
|
||||
spdlog::warn("cpu/bsd: parseCpuFrequencies failed, not found in sysctl");
|
||||
frequencies.push_back(NAN);
|
||||
}
|
||||
|
||||
return frequencies;
|
||||
}
|
||||
|
@@ -170,22 +170,30 @@ auto waybar::modules::Custom::update() -> void {
|
||||
if (label_.get_tooltip_markup() != str) {
|
||||
label_.set_tooltip_markup(str);
|
||||
}
|
||||
} else if (config_["tooltip-format"].isString()) {
|
||||
auto tooltip = config_["tooltip-format"].asString();
|
||||
tooltip = fmt::format(fmt::runtime(tooltip), text_, fmt::arg("alt", alt_),
|
||||
fmt::arg("icon", getIcon(percentage_, alt_)),
|
||||
fmt::arg("percentage", percentage_));
|
||||
label_.set_tooltip_markup(tooltip);
|
||||
} else {
|
||||
if (label_.get_tooltip_markup() != tooltip_) {
|
||||
label_.set_tooltip_markup(tooltip_);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto classes = label_.get_style_context()->list_classes();
|
||||
auto style = label_.get_style_context();
|
||||
auto classes = style->list_classes();
|
||||
for (auto const& c : classes) {
|
||||
if (c == id_) continue;
|
||||
label_.get_style_context()->remove_class(c);
|
||||
style->remove_class(c);
|
||||
}
|
||||
for (auto const& c : class_) {
|
||||
label_.get_style_context()->add_class(c);
|
||||
style->add_class(c);
|
||||
}
|
||||
label_.get_style_context()->add_class("flat");
|
||||
label_.get_style_context()->add_class("text-button");
|
||||
style->add_class("flat");
|
||||
style->add_class("text-button");
|
||||
style->add_class(MODULE_CLASS);
|
||||
event_box_.show();
|
||||
}
|
||||
}
|
||||
|
@@ -93,7 +93,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
||||
status_manager_{nullptr},
|
||||
seat_{nullptr},
|
||||
bar_(bar),
|
||||
box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
||||
box_{bar.orientation, 0},
|
||||
output_status_{nullptr} {
|
||||
struct wl_display *display = Client::inst()->wl_display;
|
||||
struct wl_registry *registry = wl_display_get_registry(display);
|
||||
@@ -113,6 +113,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(box_);
|
||||
|
||||
// Default to 9 tags, cap at 32
|
||||
|
@@ -54,22 +54,22 @@ void IPC::startIPC() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto file = fdopen(socketfd, "r");
|
||||
auto* file = fdopen(socketfd, "r");
|
||||
|
||||
while (true) {
|
||||
char buffer[1024]; // Hyprland socket2 events are max 1024 bytes
|
||||
std::array<char, 1024> buffer; // Hyprland socket2 events are max 1024 bytes
|
||||
|
||||
auto recievedCharPtr = fgets(buffer, 1024, file);
|
||||
auto* receivedCharPtr = fgets(buffer.data(), buffer.size(), file);
|
||||
|
||||
if (!recievedCharPtr) {
|
||||
if (receivedCharPtr == nullptr) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string messageRecieved(buffer);
|
||||
messageRecieved = messageRecieved.substr(0, messageRecieved.find_first_of('\n'));
|
||||
spdlog::debug("hyprland IPC received {}", messageRecieved);
|
||||
parseIPC(messageRecieved);
|
||||
std::string messageReceived(buffer.data());
|
||||
messageReceived = messageReceived.substr(0, messageReceived.find_first_of('\n'));
|
||||
spdlog::debug("hyprland IPC received {}", messageReceived);
|
||||
parseIPC(messageReceived);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
@@ -78,9 +78,9 @@ void IPC::startIPC() {
|
||||
|
||||
void IPC::parseIPC(const std::string& ev) {
|
||||
std::string request = ev.substr(0, ev.find_first_of('>'));
|
||||
std::unique_lock lock(m_callbackMutex);
|
||||
std::unique_lock lock(callbackMutex_);
|
||||
|
||||
for (auto& [eventname, handler] : m_callbacks) {
|
||||
for (auto& [eventname, handler] : callbacks_) {
|
||||
if (eventname == request) {
|
||||
handler->onEvent(ev);
|
||||
}
|
||||
@@ -88,25 +88,25 @@ void IPC::parseIPC(const std::string& ev) {
|
||||
}
|
||||
|
||||
void IPC::registerForIPC(const std::string& ev, EventHandler* ev_handler) {
|
||||
if (!ev_handler) {
|
||||
if (ev_handler == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock lock(m_callbackMutex);
|
||||
m_callbacks.emplace_back(ev, ev_handler);
|
||||
std::unique_lock lock(callbackMutex_);
|
||||
callbacks_.emplace_back(ev, ev_handler);
|
||||
}
|
||||
|
||||
void IPC::unregisterForIPC(EventHandler* ev_handler) {
|
||||
if (!ev_handler) {
|
||||
if (ev_handler == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock lock(m_callbackMutex);
|
||||
std::unique_lock lock(callbackMutex_);
|
||||
|
||||
for (auto it = m_callbacks.begin(); it != m_callbacks.end();) {
|
||||
for (auto it = callbacks_.begin(); it != callbacks_.end();) {
|
||||
auto& [eventname, handler] = *it;
|
||||
if (handler == ev_handler) {
|
||||
m_callbacks.erase(it++);
|
||||
callbacks_.erase(it++);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
@@ -135,9 +135,9 @@ std::string IPC::getSocket1Reply(const std::string& rq) {
|
||||
}
|
||||
|
||||
// get the instance signature
|
||||
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
auto* instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
|
||||
if (!instanceSig) {
|
||||
if (instanceSig == nullptr) {
|
||||
spdlog::error("Hyprland IPC: HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)");
|
||||
return "";
|
||||
}
|
||||
@@ -169,18 +169,18 @@ std::string IPC::getSocket1Reply(const std::string& rq) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char buffer[8192] = {0};
|
||||
std::array<char, 8192> buffer = {0};
|
||||
std::string response;
|
||||
|
||||
do {
|
||||
sizeWritten = read(serverSocket, buffer, 8192);
|
||||
sizeWritten = read(serverSocket, buffer.data(), 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
spdlog::error("Hyprland IPC: Couldn't read (5)");
|
||||
close(serverSocket);
|
||||
return "";
|
||||
}
|
||||
response.append(buffer, sizeWritten);
|
||||
response.append(buffer.data(), sizeWritten);
|
||||
} while (sizeWritten > 0);
|
||||
|
||||
close(serverSocket);
|
||||
@@ -188,7 +188,7 @@ std::string IPC::getSocket1Reply(const std::string& rq) {
|
||||
}
|
||||
|
||||
Json::Value IPC::getSocket1JsonReply(const std::string& rq) {
|
||||
return m_parser.parse(getSocket1Reply("j/" + rq));
|
||||
return parser_.parse(getSocket1Reply("j/" + rq));
|
||||
}
|
||||
|
||||
} // namespace waybar::modules::hyprland
|
||||
|
@@ -13,7 +13,7 @@ Language::Language(const std::string& id, const Bar& bar, const Json::Value& con
|
||||
: ALabel(config, "language", id, "{}", 0, true), bar_(bar) {
|
||||
modulesReady = true;
|
||||
|
||||
if (!gIPC.get()) {
|
||||
if (!gIPC) {
|
||||
gIPC = std::make_unique<IPC>();
|
||||
}
|
||||
|
||||
@@ -102,11 +102,11 @@ void Language::initLanguage() {
|
||||
}
|
||||
|
||||
auto Language::getLayout(const std::string& fullName) -> Layout {
|
||||
const auto CONTEXT = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES);
|
||||
rxkb_context_parse_default_ruleset(CONTEXT);
|
||||
auto* const context = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES);
|
||||
rxkb_context_parse_default_ruleset(context);
|
||||
|
||||
rxkb_layout* layout = rxkb_layout_first(CONTEXT);
|
||||
while (layout) {
|
||||
rxkb_layout* layout = rxkb_layout_first(context);
|
||||
while (layout != nullptr) {
|
||||
std::string nameOfLayout = rxkb_layout_get_description(layout);
|
||||
|
||||
if (nameOfLayout != fullName) {
|
||||
@@ -115,21 +115,20 @@ auto Language::getLayout(const std::string& fullName) -> Layout {
|
||||
}
|
||||
|
||||
auto name = std::string(rxkb_layout_get_name(layout));
|
||||
auto variant_ = rxkb_layout_get_variant(layout);
|
||||
std::string variant = variant_ == nullptr ? "" : std::string(variant_);
|
||||
const auto* variantPtr = rxkb_layout_get_variant(layout);
|
||||
std::string variant = variantPtr == nullptr ? "" : std::string(variantPtr);
|
||||
|
||||
auto short_description_ = rxkb_layout_get_brief(layout);
|
||||
std::string short_description =
|
||||
short_description_ == nullptr ? "" : std::string(short_description_);
|
||||
const auto* descriptionPtr = rxkb_layout_get_brief(layout);
|
||||
std::string description = descriptionPtr == nullptr ? "" : std::string(descriptionPtr);
|
||||
|
||||
Layout info = Layout{nameOfLayout, name, variant, short_description};
|
||||
Layout info = Layout{nameOfLayout, name, variant, description};
|
||||
|
||||
rxkb_context_unref(CONTEXT);
|
||||
rxkb_context_unref(context);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
rxkb_context_unref(CONTEXT);
|
||||
rxkb_context_unref(context);
|
||||
|
||||
spdlog::debug("hyprland language didn't find matching layout");
|
||||
|
||||
|
@@ -12,7 +12,7 @@ Submap::Submap(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
|
||||
parseConfig(config);
|
||||
|
||||
if (!gIPC.get()) {
|
||||
if (!gIPC) {
|
||||
gIPC = std::make_unique<IPC>();
|
||||
}
|
||||
|
||||
|
@@ -17,9 +17,9 @@ namespace waybar::modules::hyprland {
|
||||
Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
: AAppIconLabel(config, "window", id, "{title}", 0, true), bar_(bar) {
|
||||
modulesReady = true;
|
||||
separate_outputs = config["separate-outputs"].asBool();
|
||||
separateOutputs_ = config["separate-outputs"].asBool();
|
||||
|
||||
if (!gIPC.get()) {
|
||||
if (!gIPC) {
|
||||
gIPC = std::make_unique<IPC>();
|
||||
}
|
||||
|
||||
@@ -45,18 +45,18 @@ auto Window::update() -> void {
|
||||
// fix ampersands
|
||||
std::lock_guard<std::mutex> lg(mutex_);
|
||||
|
||||
std::string window_name = waybar::util::sanitize_string(workspace_.last_window_title);
|
||||
std::string window_address = workspace_.last_window;
|
||||
std::string windowName = waybar::util::sanitize_string(workspace_.last_window_title);
|
||||
std::string windowAddress = workspace_.last_window;
|
||||
|
||||
window_data_.title = window_name;
|
||||
windowData_.title = windowName;
|
||||
|
||||
if (!format_.empty()) {
|
||||
label_.show();
|
||||
label_.set_markup(waybar::util::rewriteString(
|
||||
fmt::format(fmt::runtime(format_), fmt::arg("title", window_name),
|
||||
fmt::arg("initialTitle", window_data_.initial_title),
|
||||
fmt::arg("class", window_data_.class_name),
|
||||
fmt::arg("initialClass", window_data_.initial_class_name)),
|
||||
fmt::format(fmt::runtime(format_), fmt::arg("title", windowName),
|
||||
fmt::arg("initialTitle", windowData_.initial_title),
|
||||
fmt::arg("class", windowData_.class_name),
|
||||
fmt::arg("initialClass", windowData_.initial_class_name)),
|
||||
config_["rewrite"]));
|
||||
} else {
|
||||
label_.hide();
|
||||
@@ -64,22 +64,22 @@ auto Window::update() -> void {
|
||||
|
||||
setClass("empty", workspace_.windows == 0);
|
||||
setClass("solo", solo_);
|
||||
setClass("floating", all_floating_);
|
||||
setClass("floating", allFloating_);
|
||||
setClass("swallowing", swallowing_);
|
||||
setClass("fullscreen", fullscreen_);
|
||||
|
||||
if (!last_solo_class_.empty() && solo_class_ != last_solo_class_) {
|
||||
if (bar_.window.get_style_context()->has_class(last_solo_class_)) {
|
||||
bar_.window.get_style_context()->remove_class(last_solo_class_);
|
||||
spdlog::trace("Removing solo class: {}", last_solo_class_);
|
||||
if (!lastSoloClass_.empty() && soloClass_ != lastSoloClass_) {
|
||||
if (bar_.window.get_style_context()->has_class(lastSoloClass_)) {
|
||||
bar_.window.get_style_context()->remove_class(lastSoloClass_);
|
||||
spdlog::trace("Removing solo class: {}", lastSoloClass_);
|
||||
}
|
||||
}
|
||||
|
||||
if (!solo_class_.empty() && solo_class_ != last_solo_class_) {
|
||||
bar_.window.get_style_context()->add_class(solo_class_);
|
||||
spdlog::trace("Adding solo class: {}", solo_class_);
|
||||
if (!soloClass_.empty() && soloClass_ != lastSoloClass_) {
|
||||
bar_.window.get_style_context()->add_class(soloClass_);
|
||||
spdlog::trace("Adding solo class: {}", soloClass_);
|
||||
}
|
||||
last_solo_class_ = solo_class_;
|
||||
lastSoloClass_ = soloClass_;
|
||||
|
||||
AAppIconLabel::update();
|
||||
}
|
||||
@@ -113,8 +113,12 @@ auto Window::getActiveWorkspace(const std::string& monitorName) -> Workspace {
|
||||
}
|
||||
|
||||
auto Window::Workspace::parse(const Json::Value& value) -> Window::Workspace {
|
||||
return Workspace{value["id"].asInt(), value["windows"].asInt(), value["lastwindow"].asString(),
|
||||
value["lastwindowtitle"].asString()};
|
||||
return Workspace{
|
||||
value["id"].asInt(),
|
||||
value["windows"].asInt(),
|
||||
value["lastwindow"].asString(),
|
||||
value["lastwindowtitle"].asString(),
|
||||
};
|
||||
}
|
||||
|
||||
auto Window::WindowData::parse(const Json::Value& value) -> Window::WindowData {
|
||||
@@ -127,7 +131,7 @@ auto Window::WindowData::parse(const Json::Value& value) -> Window::WindowData {
|
||||
void Window::queryActiveWorkspace() {
|
||||
std::lock_guard<std::mutex> lg(mutex_);
|
||||
|
||||
if (separate_outputs) {
|
||||
if (separateOutputs_) {
|
||||
workspace_ = getActiveWorkspace(this->bar_.output->name);
|
||||
} else {
|
||||
workspace_ = getActiveWorkspace();
|
||||
@@ -136,31 +140,33 @@ void Window::queryActiveWorkspace() {
|
||||
if (workspace_.windows > 0) {
|
||||
const auto clients = gIPC->getSocket1JsonReply("clients");
|
||||
assert(clients.isArray());
|
||||
auto active_window = std::find_if(clients.begin(), clients.end(), [&](Json::Value window) {
|
||||
auto activeWindow = std::find_if(clients.begin(), clients.end(), [&](Json::Value window) {
|
||||
return window["address"] == workspace_.last_window;
|
||||
});
|
||||
if (active_window == std::end(clients)) {
|
||||
if (activeWindow == std::end(clients)) {
|
||||
return;
|
||||
}
|
||||
|
||||
window_data_ = WindowData::parse(*active_window);
|
||||
updateAppIconName(window_data_.class_name, window_data_.initial_class_name);
|
||||
std::vector<Json::Value> workspace_windows;
|
||||
std::copy_if(clients.begin(), clients.end(), std::back_inserter(workspace_windows),
|
||||
windowData_ = WindowData::parse(*activeWindow);
|
||||
updateAppIconName(windowData_.class_name, windowData_.initial_class_name);
|
||||
std::vector<Json::Value> workspaceWindows;
|
||||
std::copy_if(clients.begin(), clients.end(), std::back_inserter(workspaceWindows),
|
||||
[&](Json::Value window) {
|
||||
return window["workspace"]["id"] == workspace_.id && window["mapped"].asBool();
|
||||
});
|
||||
swallowing_ = std::any_of(workspace_windows.begin(), workspace_windows.end(),
|
||||
[&](Json::Value window) { return !window["swallowing"].isNull(); });
|
||||
std::vector<Json::Value> visible_windows;
|
||||
std::copy_if(workspace_windows.begin(), workspace_windows.end(),
|
||||
std::back_inserter(visible_windows),
|
||||
swallowing_ =
|
||||
std::any_of(workspaceWindows.begin(), workspaceWindows.end(), [&](Json::Value window) {
|
||||
return !window["swallowing"].isNull() && window["swallowing"].asString() != "0x0";
|
||||
});
|
||||
std::vector<Json::Value> visibleWindows;
|
||||
std::copy_if(workspaceWindows.begin(), workspaceWindows.end(),
|
||||
std::back_inserter(visibleWindows),
|
||||
[&](Json::Value window) { return !window["hidden"].asBool(); });
|
||||
solo_ = 1 == std::count_if(visible_windows.begin(), visible_windows.end(),
|
||||
solo_ = 1 == std::count_if(visibleWindows.begin(), visibleWindows.end(),
|
||||
[&](Json::Value window) { return !window["floating"].asBool(); });
|
||||
all_floating_ = std::all_of(visible_windows.begin(), visible_windows.end(),
|
||||
[&](Json::Value window) { return window["floating"].asBool(); });
|
||||
fullscreen_ = window_data_.fullscreen;
|
||||
allFloating_ = std::all_of(visibleWindows.begin(), visibleWindows.end(),
|
||||
[&](Json::Value window) { return window["floating"].asBool(); });
|
||||
fullscreen_ = windowData_.fullscreen;
|
||||
|
||||
// Fullscreen windows look like they are solo
|
||||
if (fullscreen_) {
|
||||
@@ -168,23 +174,23 @@ void Window::queryActiveWorkspace() {
|
||||
}
|
||||
|
||||
// Grouped windows have a tab bar and therefore don't look fullscreen or solo
|
||||
if (window_data_.grouped) {
|
||||
if (windowData_.grouped) {
|
||||
fullscreen_ = false;
|
||||
solo_ = false;
|
||||
}
|
||||
|
||||
if (solo_) {
|
||||
solo_class_ = window_data_.class_name;
|
||||
soloClass_ = windowData_.class_name;
|
||||
} else {
|
||||
solo_class_ = "";
|
||||
soloClass_ = "";
|
||||
}
|
||||
} else {
|
||||
window_data_ = WindowData{};
|
||||
all_floating_ = false;
|
||||
windowData_ = WindowData{};
|
||||
allFloating_ = false;
|
||||
swallowing_ = false;
|
||||
fullscreen_ = false;
|
||||
solo_ = false;
|
||||
solo_class_ = "";
|
||||
soloClass_ = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -34,9 +34,7 @@ int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
|
||||
}
|
||||
|
||||
Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||
: AModule(config, "workspaces", id, false, false),
|
||||
m_bar(bar),
|
||||
m_box(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) {
|
||||
: AModule(config, "workspaces", id, false, false), m_bar(bar), m_box(bar.orientation, 0) {
|
||||
modulesReady = true;
|
||||
parseConfig(config);
|
||||
|
||||
@@ -44,12 +42,14 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
||||
if (!id.empty()) {
|
||||
m_box.get_style_context()->add_class(id);
|
||||
}
|
||||
m_box.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(m_box);
|
||||
|
||||
if (!gIPC) {
|
||||
gIPC = std::make_unique<IPC>();
|
||||
}
|
||||
|
||||
setCurrentMonitorId();
|
||||
init();
|
||||
registerIpc();
|
||||
}
|
||||
@@ -65,7 +65,6 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
||||
for (std::string &name : formatIcons.getMemberNames()) {
|
||||
m_iconsMap.emplace(name, formatIcons[name].asString());
|
||||
}
|
||||
|
||||
m_iconsMap.emplace("", "");
|
||||
}
|
||||
|
||||
@@ -113,11 +112,26 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
if (config_["persistent_workspaces"].isObject()) {
|
||||
spdlog::warn(
|
||||
"persistent_workspaces is deprecated. Please change config to use persistent-workspaces.");
|
||||
}
|
||||
|
||||
if (config_["persistent-workspaces"].isObject() || config_["persistent_workspaces"].isObject()) {
|
||||
m_persistentWorkspaceConfig = config_["persistent-workspaces"].isObject()
|
||||
? config_["persistent-workspaces"]
|
||||
: config_["persistent_workspaces"];
|
||||
}
|
||||
|
||||
const Json::Value &formatWindowSeparator = config["format-window-separator"];
|
||||
m_formatWindowSeparator =
|
||||
formatWindowSeparator.isString() ? formatWindowSeparator.asString() : " ";
|
||||
|
||||
const Json::Value &windowRewrite = config["window-rewrite"];
|
||||
if (!windowRewrite.isObject()) {
|
||||
spdlog::debug("window-rewrite is not defined or is not an object, using default rules.");
|
||||
return;
|
||||
}
|
||||
|
||||
const Json::Value &windowRewriteDefaultConfig = config["window-rewrite-default"];
|
||||
std::string windowRewriteDefault =
|
||||
@@ -128,14 +142,15 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
|
||||
[this](std::string &window_rule) { return windowRewritePriorityFunction(window_rule); });
|
||||
}
|
||||
|
||||
void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_paylod) {
|
||||
if (!create_window_paylod.isEmpty(*this)) {
|
||||
m_orphanWindowMap[create_window_paylod.getAddress()] = create_window_paylod.repr(*this);
|
||||
void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_payload) {
|
||||
if (!create_window_payload.isEmpty(*this)) {
|
||||
m_orphanWindowMap[create_window_payload.getAddress()] = create_window_payload.repr(*this);
|
||||
}
|
||||
}
|
||||
|
||||
auto Workspaces::registerIpc() -> void {
|
||||
gIPC->registerForIPC("workspace", this);
|
||||
gIPC->registerForIPC("activespecial", this);
|
||||
gIPC->registerForIPC("createworkspace", this);
|
||||
gIPC->registerForIPC("destroyworkspace", this);
|
||||
gIPC->registerForIPC("focusedmon", this);
|
||||
@@ -145,6 +160,7 @@ auto Workspaces::registerIpc() -> void {
|
||||
gIPC->registerForIPC("closewindow", this);
|
||||
gIPC->registerForIPC("movewindow", this);
|
||||
gIPC->registerForIPC("urgent", this);
|
||||
gIPC->registerForIPC("configreloaded", this);
|
||||
|
||||
if (windowRewriteConfigUsesTitle()) {
|
||||
spdlog::info(
|
||||
@@ -176,6 +192,7 @@ void Workspaces::doUpdate() {
|
||||
m_workspacesToCreate.clear();
|
||||
|
||||
// get all active workspaces
|
||||
spdlog::trace("Getting active workspaces");
|
||||
auto monitors = gIPC->getSocket1JsonReply("monitors");
|
||||
std::vector<std::string> visibleWorkspaces;
|
||||
for (Json::Value &monitor : monitors) {
|
||||
@@ -183,11 +200,18 @@ void Workspaces::doUpdate() {
|
||||
if (ws.isObject() && (ws["name"].isString())) {
|
||||
visibleWorkspaces.push_back(ws["name"].asString());
|
||||
}
|
||||
auto sws = monitor["specialWorkspace"];
|
||||
auto name = sws["name"].asString();
|
||||
if (sws.isObject() && (sws["name"].isString()) && !name.empty()) {
|
||||
visibleWorkspaces.push_back(!name.starts_with("special:") ? name : name.substr(8));
|
||||
}
|
||||
}
|
||||
|
||||
spdlog::trace("Updating workspace states");
|
||||
for (auto &workspace : m_workspaces) {
|
||||
// active
|
||||
workspace->setActive(workspace->name() == m_activeWorkspaceName);
|
||||
workspace->setActive(workspace->name() == m_activeWorkspaceName ||
|
||||
workspace->name() == m_activeSpecialWorkspaceName);
|
||||
// disable urgency if workspace is active
|
||||
if (workspace->name() == m_activeWorkspaceName && workspace->isUrgent()) {
|
||||
workspace->setUrgent(false);
|
||||
@@ -205,6 +229,7 @@ void Workspaces::doUpdate() {
|
||||
workspace->update(m_format, workspaceIcon);
|
||||
}
|
||||
|
||||
spdlog::trace("Updating window count");
|
||||
bool anyWindowCreated = false;
|
||||
std::vector<WindowCreationPayload> notCreated;
|
||||
|
||||
@@ -266,6 +291,8 @@ void Workspaces::onEvent(const std::string &ev) {
|
||||
|
||||
if (eventName == "workspace") {
|
||||
onWorkspaceActivated(payload);
|
||||
} else if (eventName == "activespecial") {
|
||||
onSpecialWorkspaceActivated(payload);
|
||||
} else if (eventName == "destroyworkspace") {
|
||||
onWorkspaceDestroyed(payload);
|
||||
} else if (eventName == "createworkspace") {
|
||||
@@ -286,6 +313,8 @@ void Workspaces::onEvent(const std::string &ev) {
|
||||
onWorkspaceRenamed(payload);
|
||||
} else if (eventName == "windowtitle") {
|
||||
onWindowTitleEvent(payload);
|
||||
} else if (eventName == "configreloaded") {
|
||||
onConfigReloaded();
|
||||
}
|
||||
|
||||
dp.emit();
|
||||
@@ -295,6 +324,11 @@ void Workspaces::onWorkspaceActivated(std::string const &payload) {
|
||||
m_activeWorkspaceName = payload;
|
||||
}
|
||||
|
||||
void Workspaces::onSpecialWorkspaceActivated(std::string const &payload) {
|
||||
std::string name(begin(payload), begin(payload) + payload.find_first_of(','));
|
||||
m_activeSpecialWorkspaceName = (!name.starts_with("special:") ? name : name.substr(8));
|
||||
}
|
||||
|
||||
void Workspaces::onWorkspaceDestroyed(std::string const &payload) {
|
||||
if (!isDoubleSpecial(payload)) {
|
||||
m_workspacesToRemove.push_back(payload);
|
||||
@@ -303,22 +337,37 @@ void Workspaces::onWorkspaceDestroyed(std::string const &payload) {
|
||||
|
||||
void Workspaces::onWorkspaceCreated(std::string const &workspaceName,
|
||||
Json::Value const &clientsData) {
|
||||
const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces");
|
||||
spdlog::debug("Workspace created: {}", workspaceName);
|
||||
auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces");
|
||||
|
||||
if (!isWorkspaceIgnored(workspaceName)) {
|
||||
auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules");
|
||||
for (Json::Value workspaceJson : workspacesJson) {
|
||||
std::string name = workspaceJson["name"].asString();
|
||||
if (name == workspaceName &&
|
||||
(allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
||||
(showSpecial() || !name.starts_with("special")) && !isDoubleSpecial(workspaceName)) {
|
||||
m_workspacesToCreate.emplace_back(workspaceJson, clientsData);
|
||||
break;
|
||||
if (name == workspaceName) {
|
||||
if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
||||
(showSpecial() || !name.starts_with("special")) && !isDoubleSpecial(workspaceName)) {
|
||||
for (Json::Value const &rule : workspaceRules) {
|
||||
if (rule["workspaceString"].asString() == workspaceName) {
|
||||
workspaceJson["persistent"] = rule["persistent"].asBool();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_workspacesToCreate.emplace_back(workspaceJson, clientsData);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
extendOrphans(workspaceJson["id"].asInt(), clientsData);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
spdlog::trace("Not creating workspace because it is ignored: {}", workspaceName);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::onWorkspaceMoved(std::string const &payload) {
|
||||
spdlog::debug("Workspace moved: {}", payload);
|
||||
std::string workspaceName = payload.substr(0, payload.find(','));
|
||||
std::string monitorName = payload.substr(payload.find(',') + 1);
|
||||
|
||||
@@ -326,11 +375,13 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) {
|
||||
Json::Value clientsData = gIPC->getSocket1JsonReply("clients");
|
||||
onWorkspaceCreated(workspaceName, clientsData);
|
||||
} else {
|
||||
spdlog::debug("Removing workspace because it was moved to another monitor: {}");
|
||||
onWorkspaceDestroyed(workspaceName);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::onWorkspaceRenamed(std::string const &payload) {
|
||||
spdlog::debug("Workspace renamed: {}", payload);
|
||||
std::string workspaceIdStr = payload.substr(0, payload.find(','));
|
||||
int workspaceId = workspaceIdStr == "special" ? -99 : std::stoi(workspaceIdStr);
|
||||
std::string newName = payload.substr(payload.find(',') + 1);
|
||||
@@ -347,10 +398,19 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
|
||||
}
|
||||
|
||||
void Workspaces::onMonitorFocused(std::string const &payload) {
|
||||
spdlog::trace("Monitor focused: {}", payload);
|
||||
m_activeWorkspaceName = payload.substr(payload.find(',') + 1);
|
||||
|
||||
for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) {
|
||||
if (monitor["name"].asString() == payload.substr(0, payload.find(','))) {
|
||||
auto name = monitor["specialWorkspace"]["name"].asString();
|
||||
m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::onWindowOpened(std::string const &payload) {
|
||||
spdlog::trace("Window opened: {}", payload);
|
||||
updateWindowCount();
|
||||
size_t lastCommaIdx = 0;
|
||||
size_t nextCommaIdx = payload.find(',');
|
||||
@@ -370,6 +430,7 @@ void Workspaces::onWindowOpened(std::string const &payload) {
|
||||
}
|
||||
|
||||
void Workspaces::onWindowClosed(std::string const &addr) {
|
||||
spdlog::trace("Window closed: {}", addr);
|
||||
updateWindowCount();
|
||||
for (auto &workspace : m_workspaces) {
|
||||
if (workspace->closeWindow(addr)) {
|
||||
@@ -379,6 +440,7 @@ void Workspaces::onWindowClosed(std::string const &addr) {
|
||||
}
|
||||
|
||||
void Workspaces::onWindowMoved(std::string const &payload) {
|
||||
spdlog::trace("Window moved: {}", payload);
|
||||
updateWindowCount();
|
||||
size_t lastCommaIdx = 0;
|
||||
size_t nextCommaIdx = payload.find(',');
|
||||
@@ -417,6 +479,7 @@ void Workspaces::onWindowMoved(std::string const &payload) {
|
||||
}
|
||||
|
||||
void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
||||
spdlog::trace("Window title changed: {}", payload);
|
||||
std::optional<std::function<void(WindowCreationPayload)>> inserter;
|
||||
|
||||
// If the window was an orphan, rename it at the orphan's vector
|
||||
@@ -460,12 +523,19 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::onConfigReloaded() {
|
||||
spdlog::info("Hyprland config reloaded, reinitializing hyprland/workspaces module...");
|
||||
init();
|
||||
}
|
||||
|
||||
void Workspaces::updateWindowCount() {
|
||||
const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces");
|
||||
for (auto &workspace : m_workspaces) {
|
||||
auto workspaceJson = std::find_if(
|
||||
workspacesJson.begin(), workspacesJson.end(),
|
||||
[&](Json::Value const &x) { return x["name"].asString() == workspace->name(); });
|
||||
auto workspaceJson =
|
||||
std::find_if(workspacesJson.begin(), workspacesJson.end(), [&](Json::Value const &x) {
|
||||
return x["name"].asString() == workspace->name() ||
|
||||
(workspace->isSpecial() && x["name"].asString() == "special:" + workspace->name());
|
||||
});
|
||||
uint32_t count = 0;
|
||||
if (workspaceJson != workspacesJson.end()) {
|
||||
try {
|
||||
@@ -516,8 +586,11 @@ std::optional<std::string> Workspace::closeWindow(WindowAddress const &addr) {
|
||||
|
||||
void Workspaces::createWorkspace(Json::Value const &workspace_data,
|
||||
Json::Value const &clients_data) {
|
||||
// avoid recreating existing workspaces
|
||||
auto workspaceName = workspace_data["name"].asString();
|
||||
spdlog::debug("Creating workspace {}, persistent: {}", workspaceName,
|
||||
workspace_data["persistent"].asBool() ? "true" : "false");
|
||||
|
||||
// avoid recreating existing workspaces
|
||||
auto workspace = std::find_if(
|
||||
m_workspaces.begin(), m_workspaces.end(),
|
||||
[workspaceName](std::unique_ptr<Workspace> const &w) {
|
||||
@@ -526,9 +599,8 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
|
||||
});
|
||||
|
||||
if (workspace != m_workspaces.end()) {
|
||||
if (workspace_data["persistent"].asBool() and !(*workspace)->isPersistent()) {
|
||||
(*workspace)->setPersistent();
|
||||
}
|
||||
// don't recreate workspace, but update persistency if necessary
|
||||
(*workspace)->setPersistent(workspace_data["persistent"].asBool());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -541,6 +613,7 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
|
||||
}
|
||||
|
||||
void Workspaces::removeWorkspace(std::string const &name) {
|
||||
spdlog::debug("Removing workspace {}", name);
|
||||
auto workspace =
|
||||
std::find_if(m_workspaces.begin(), m_workspaces.end(), [&](std::unique_ptr<Workspace> &x) {
|
||||
return (name.starts_with("special:") && name.substr(8) == x->name()) || name == x->name();
|
||||
@@ -552,7 +625,7 @@ void Workspaces::removeWorkspace(std::string const &name) {
|
||||
}
|
||||
|
||||
if ((*workspace)->isPersistent()) {
|
||||
// don't remove persistent workspaces, createWorkspace will take care of replacement
|
||||
spdlog::trace("Not removing persistent workspace {}", name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -560,94 +633,106 @@ void Workspaces::removeWorkspace(std::string const &name) {
|
||||
m_workspaces.erase(workspace);
|
||||
}
|
||||
|
||||
void Workspaces::fillPersistentWorkspaces() {
|
||||
if (config_["persistent_workspaces"].isObject()) {
|
||||
spdlog::warn(
|
||||
"persistent_workspaces is deprecated. Please change config to use persistent-workspaces.");
|
||||
Json::Value createPersistentWorkspaceData(std::string const &name, std::string const &monitor) {
|
||||
spdlog::trace("Creating persistent workspace: {} on monitor {}", name, monitor);
|
||||
Json::Value workspaceData;
|
||||
try {
|
||||
// numbered persistent workspaces get the name as ID
|
||||
workspaceData["id"] = name == "special" ? -99 : std::stoi(name);
|
||||
} catch (const std::exception &e) {
|
||||
// named persistent workspaces start with ID=0
|
||||
workspaceData["id"] = 0;
|
||||
}
|
||||
workspaceData["name"] = name;
|
||||
workspaceData["monitor"] = monitor;
|
||||
workspaceData["windows"] = 0;
|
||||
workspaceData["persistent"] = true;
|
||||
return workspaceData;
|
||||
}
|
||||
|
||||
if (config_["persistent-workspaces"].isObject() || config_["persistent_workspaces"].isObject()) {
|
||||
const Json::Value persistentWorkspaces = config_["persistent-workspaces"].isObject()
|
||||
? config_["persistent-workspaces"]
|
||||
: config_["persistent_workspaces"];
|
||||
const std::vector<std::string> keys = persistentWorkspaces.getMemberNames();
|
||||
void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const &clientsJson) {
|
||||
spdlog::info("Loading persistent workspaces from Waybar config");
|
||||
const std::vector<std::string> keys = m_persistentWorkspaceConfig.getMemberNames();
|
||||
std::vector<std::string> persistentWorkspacesToCreate;
|
||||
|
||||
for (const std::string &key : keys) {
|
||||
// only add if either:
|
||||
// 1. key is "*" and this monitor is not already defined in the config
|
||||
// 2. key is the current monitor name
|
||||
bool canCreate =
|
||||
(key == "*" && std::find(keys.begin(), keys.end(), m_bar.output->name) == keys.end()) ||
|
||||
key == m_bar.output->name;
|
||||
const Json::Value &value = persistentWorkspaces[key];
|
||||
const std::string currentMonitor = m_bar.output->name;
|
||||
const bool monitorInConfig = std::find(keys.begin(), keys.end(), currentMonitor) != keys.end();
|
||||
for (const std::string &key : keys) {
|
||||
// only add if either:
|
||||
// 1. key is the current monitor name
|
||||
// 2. key is "*" and this monitor is not already defined in the config
|
||||
bool canCreate = key == currentMonitor || (key == "*" && !monitorInConfig);
|
||||
const Json::Value &value = m_persistentWorkspaceConfig[key];
|
||||
spdlog::trace("Parsing persistent workspace config: {} => {}", key, value.toStyledString());
|
||||
|
||||
if (value.isInt()) {
|
||||
// value is a number => create that many workspaces for this monitor
|
||||
if (canCreate) {
|
||||
int amount = value.asInt();
|
||||
spdlog::debug("Creating {} persistent workspaces for monitor {}", amount,
|
||||
m_bar.output->name);
|
||||
for (int i = 0; i < amount; i++) {
|
||||
m_persistentWorkspacesToCreate.emplace_back(
|
||||
std::to_string(m_monitorId * amount + i + 1));
|
||||
}
|
||||
if (value.isInt()) {
|
||||
// value is a number => create that many workspaces for this monitor
|
||||
if (canCreate) {
|
||||
int amount = value.asInt();
|
||||
spdlog::debug("Creating {} persistent workspaces for monitor {}", amount, currentMonitor);
|
||||
for (int i = 0; i < amount; i++) {
|
||||
persistentWorkspacesToCreate.emplace_back(std::to_string(m_monitorId * amount + i + 1));
|
||||
}
|
||||
} else if (value.isArray() && !value.empty()) {
|
||||
// value is an array => create defined workspaces for this monitor
|
||||
if (canCreate) {
|
||||
for (const Json::Value &workspace : value) {
|
||||
if (workspace.isInt()) {
|
||||
spdlog::debug("Creating workspace {} on monitor {}", workspace, m_bar.output->name);
|
||||
m_persistentWorkspacesToCreate.emplace_back(std::to_string(workspace.asInt()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// key is the workspace and value is array of monitors to create on
|
||||
for (const Json::Value &monitor : value) {
|
||||
if (monitor.isString() && monitor.asString() == m_bar.output->name) {
|
||||
m_persistentWorkspacesToCreate.emplace_back(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (value.isArray() && !value.empty()) {
|
||||
// value is an array => create defined workspaces for this monitor
|
||||
if (canCreate) {
|
||||
for (const Json::Value &workspace : value) {
|
||||
if (workspace.isInt()) {
|
||||
spdlog::debug("Creating workspace {} on monitor {}", workspace, currentMonitor);
|
||||
persistentWorkspacesToCreate.emplace_back(std::to_string(workspace.asInt()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this workspace should be displayed on all monitors
|
||||
m_persistentWorkspacesToCreate.emplace_back(key);
|
||||
// key is the workspace and value is array of monitors to create on
|
||||
for (const Json::Value &monitor : value) {
|
||||
if (monitor.isString() && monitor.asString() == currentMonitor) {
|
||||
persistentWorkspacesToCreate.emplace_back(currentMonitor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this workspace should be displayed on all monitors
|
||||
persistentWorkspacesToCreate.emplace_back(key);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const &workspace : persistentWorkspacesToCreate) {
|
||||
auto const workspaceData = createPersistentWorkspaceData(workspace, m_bar.output->name);
|
||||
m_workspacesToCreate.emplace_back(workspaceData, clientsJson);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value &clientsJson) {
|
||||
spdlog::info("Loading persistent workspaces from Hyprland workspace rules");
|
||||
|
||||
auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules");
|
||||
for (Json::Value const &rule : workspaceRules) {
|
||||
if (!rule["workspaceString"].isString()) {
|
||||
spdlog::warn("Workspace rules: invalid workspaceString, skipping: {}", rule);
|
||||
continue;
|
||||
}
|
||||
if (!rule["persistent"].asBool()) {
|
||||
continue;
|
||||
}
|
||||
auto const &workspace = rule["workspaceString"].asString();
|
||||
auto const &monitor = rule["monitor"].asString();
|
||||
// create this workspace persistently if:
|
||||
// 1. the allOutputs config option is enabled
|
||||
// 2. the rule's monitor is the current monitor
|
||||
// 3. no monitor is specified in the rule => assume it needs to be persistent on every monitor
|
||||
if (allOutputs() || m_bar.output->name == monitor || monitor.empty()) {
|
||||
// => persistent workspace should be shown on this monitor
|
||||
auto workspaceData = createPersistentWorkspaceData(workspace, m_bar.output->name);
|
||||
m_workspacesToCreate.emplace_back(workspaceData, clientsJson);
|
||||
} else {
|
||||
m_workspacesToRemove.emplace_back(workspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::createPersistentWorkspaces() {
|
||||
for (const std::string &workspaceName : m_persistentWorkspacesToCreate) {
|
||||
Json::Value newWorkspace;
|
||||
try {
|
||||
// numbered persistent workspaces get the name as ID
|
||||
newWorkspace["id"] = workspaceName == "special" ? -99 : std::stoi(workspaceName);
|
||||
} catch (const std::exception &e) {
|
||||
// named persistent workspaces start with ID=0
|
||||
newWorkspace["id"] = 0;
|
||||
}
|
||||
newWorkspace["name"] = workspaceName;
|
||||
newWorkspace["monitor"] = m_bar.output->name;
|
||||
newWorkspace["windows"] = 0;
|
||||
newWorkspace["persistent"] = true;
|
||||
|
||||
createWorkspace(newWorkspace);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson) {
|
||||
for (const auto &client : clientsJson) {
|
||||
if (client["workspace"]["id"].asInt() == workspaceId) {
|
||||
registerOrphanWindow({client});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::init() {
|
||||
m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
|
||||
|
||||
void Workspaces::setCurrentMonitorId() {
|
||||
// get monitor ID from name (used by persistent workspaces)
|
||||
m_monitorId = 0;
|
||||
auto monitors = gIPC->getSocket1JsonReply("monitors");
|
||||
@@ -658,29 +743,58 @@ void Workspaces::init() {
|
||||
spdlog::error("Monitor '{}' does not have an ID? Using 0", m_bar.output->name);
|
||||
} else {
|
||||
m_monitorId = (*currentMonitor)["id"].asInt();
|
||||
spdlog::trace("Current monitor ID: {}", m_monitorId);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::initializeWorkspaces() {
|
||||
spdlog::debug("Initializing workspaces");
|
||||
|
||||
// if the workspace rules changed since last initialization, make sure we reset everything:
|
||||
for (auto &workspace : m_workspaces) {
|
||||
m_workspacesToRemove.push_back(workspace->name());
|
||||
}
|
||||
|
||||
const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces");
|
||||
const Json::Value clientsJson = gIPC->getSocket1JsonReply("clients");
|
||||
// get all current workspaces
|
||||
auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces");
|
||||
auto const clientsJson = gIPC->getSocket1JsonReply("clients");
|
||||
|
||||
for (Json::Value workspaceJson : workspacesJson) {
|
||||
std::string workspaceName = workspaceJson["name"].asString();
|
||||
if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
|
||||
(!workspaceName.starts_with("special") || showSpecial()) &&
|
||||
!isWorkspaceIgnored(workspaceName)) {
|
||||
createWorkspace(workspaceJson, clientsJson);
|
||||
m_workspacesToCreate.emplace_back(workspaceJson, clientsJson);
|
||||
} else {
|
||||
extendOrphans(workspaceJson["id"].asInt(), clientsJson);
|
||||
}
|
||||
}
|
||||
|
||||
fillPersistentWorkspaces();
|
||||
createPersistentWorkspaces();
|
||||
spdlog::debug("Initializing persistent workspaces");
|
||||
if (m_persistentWorkspaceConfig.isObject()) {
|
||||
// a persistent workspace config is defined, so use that instead of workspace rules
|
||||
loadPersistentWorkspacesFromConfig(clientsJson);
|
||||
} else {
|
||||
// no persistent workspaces config defined, use Hyprland's workspace rules
|
||||
loadPersistentWorkspacesFromWorkspaceRules(clientsJson);
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson) {
|
||||
spdlog::trace("Extending orphans with workspace {}", workspaceId);
|
||||
for (const auto &client : clientsJson) {
|
||||
if (client["workspace"]["id"].asInt() == workspaceId) {
|
||||
registerOrphanWindow({client});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::init() {
|
||||
m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
|
||||
|
||||
initializeWorkspaces();
|
||||
updateWindowCount();
|
||||
|
||||
sortWorkspaces();
|
||||
|
||||
dp.emit();
|
||||
}
|
||||
|
||||
@@ -697,7 +811,8 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma
|
||||
m_name(workspace_data["name"].asString()),
|
||||
m_output(workspace_data["monitor"].asString()), // TODO:allow using monitor desc
|
||||
m_windows(workspace_data["windows"].asInt()),
|
||||
m_active(true) {
|
||||
m_isActive(true),
|
||||
m_isPersistent(workspace_data["persistent"].asBool()) {
|
||||
if (m_name.starts_with("name:")) {
|
||||
m_name = m_name.substr(5);
|
||||
} else if (m_name.starts_with("special")) {
|
||||
@@ -705,10 +820,6 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma
|
||||
m_isSpecial = true;
|
||||
}
|
||||
|
||||
if (workspace_data.isMember("persistent")) {
|
||||
m_isPersistent = workspace_data["persistent"].asBool();
|
||||
}
|
||||
|
||||
m_button.add_events(Gdk::BUTTON_PRESS_MASK);
|
||||
m_button.signal_button_press_event().connect(sigc::mem_fun(*this, &Workspace::handleClicked),
|
||||
false);
|
||||
@@ -814,8 +925,7 @@ void Workspaces::sortWorkspaces() {
|
||||
if (a->id() == -99 || b->id() == -99) {
|
||||
return b->id() == -99;
|
||||
}
|
||||
// both are 0 (not yet named persistents) / both are named specials (-98 <= ID
|
||||
// <=-1)
|
||||
// both are 0 (not yet named persistents) / named specials (-98 <= ID <= -1)
|
||||
return isNameLess;
|
||||
}
|
||||
|
||||
@@ -834,6 +944,7 @@ void Workspaces::sortWorkspaces() {
|
||||
}
|
||||
|
||||
std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map) {
|
||||
spdlog::trace("Selecting icon for workspace {}", name());
|
||||
if (isUrgent()) {
|
||||
auto urgentIconIt = icons_map.find("urgent");
|
||||
if (urgentIconIt != icons_map.end()) {
|
||||
@@ -892,9 +1003,9 @@ std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map
|
||||
bool Workspace::handleClicked(GdkEventButton *bt) const {
|
||||
if (bt->type == GDK_BUTTON_PRESS) {
|
||||
try {
|
||||
if (id() > 0) { // normal or numbered persistent
|
||||
if (id() > 0) { // normal
|
||||
gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
|
||||
} else if (!isSpecial()) { // named
|
||||
} else if (!isSpecial()) { // named (this includes persistent)
|
||||
gIPC->getSocket1Reply("dispatch workspace name:" + name());
|
||||
} else if (id() != -99) { // named special
|
||||
gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
|
||||
|
@@ -7,6 +7,7 @@ waybar::modules::Image::Image(const std::string& id, const Json::Value& config)
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(box_);
|
||||
|
||||
dp.emit();
|
||||
|
@@ -81,7 +81,7 @@ auto supportsLockStates(const libevdev* dev) -> bool {
|
||||
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar,
|
||||
const Json::Value& config)
|
||||
: AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()),
|
||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||
box_(bar.orientation, 0),
|
||||
numlock_label_(""),
|
||||
capslock_label_(""),
|
||||
numlock_format_(config_["format"].isString() ? config_["format"].asString()
|
||||
@@ -132,6 +132,7 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(box_);
|
||||
|
||||
if (config_["device-path"].isString()) {
|
||||
|
@@ -87,7 +87,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
||||
control_{nullptr},
|
||||
seat_{nullptr},
|
||||
bar_(bar),
|
||||
box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
||||
box_{bar.orientation, 0},
|
||||
output_status_{nullptr} {
|
||||
struct wl_display *display = Client::inst()->wl_display;
|
||||
struct wl_registry *registry = wl_display_get_registry(display);
|
||||
@@ -111,6 +111,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(box_);
|
||||
|
||||
// Default to 9 tags, cap at 32
|
||||
|
@@ -6,7 +6,7 @@ namespace waybar::modules::SNI {
|
||||
|
||||
Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
: AModule(config, "tray", id),
|
||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||
box_(bar.orientation, 0),
|
||||
watcher_(SNI::Watcher::getInstance()),
|
||||
host_(nb_hosts_, config, bar, std::bind(&Tray::onAdd, this, std::placeholders::_1),
|
||||
std::bind(&Tray::onRemove, this, std::placeholders::_1)) {
|
||||
@@ -15,6 +15,7 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
if (config_["spacing"].isUInt()) {
|
||||
box_.set_spacing(config_["spacing"].asUInt());
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ const std::string Language::XKB_ACTIVE_LAYOUT_NAME_KEY = "xkb_active_layout_name
|
||||
|
||||
Language::Language(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "language", id, "{}", 0, true) {
|
||||
hide_single_ = config["hide-single-layout"].isBool() && config["hide-single-layout"].asBool();
|
||||
is_variant_displayed = format_.find("{variant}") != std::string::npos;
|
||||
if (format_.find("{}") != std::string::npos || format_.find("{short}") != std::string::npos) {
|
||||
displayed_short_flag |= static_cast<std::byte>(DispayedShortFlag::ShortName);
|
||||
@@ -95,6 +96,10 @@ void Language::onEvent(const struct Ipc::ipc_response& res) {
|
||||
|
||||
auto Language::update() -> void {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (hide_single_ && layouts_map_.size() <= 1) {
|
||||
event_box_.hide();
|
||||
return;
|
||||
}
|
||||
auto display_layout = trim(fmt::format(
|
||||
fmt::runtime(format_), fmt::arg("short", layout_.short_name),
|
||||
fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name),
|
||||
|
@@ -24,10 +24,28 @@ int Workspaces::convertWorkspaceNameToNum(std::string name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
|
||||
// Rules that match against title are prioritized
|
||||
// Rules that don't specify if they're matching against either title or class are deprioritized
|
||||
bool const hasTitle = window_rule.find("title") != std::string::npos;
|
||||
bool const hasClass = window_rule.find("class") != std::string::npos;
|
||||
|
||||
if (hasTitle && hasClass) {
|
||||
return 3;
|
||||
}
|
||||
if (hasTitle) {
|
||||
return 2;
|
||||
}
|
||||
if (hasClass) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||
: AModule(config, "workspaces", id, false, !config["disable-scroll"].asBool()),
|
||||
bar_(bar),
|
||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) {
|
||||
box_(bar.orientation, 0) {
|
||||
if (config["format-icons"]["high-priority-named"].isArray()) {
|
||||
for (auto &it : config["format-icons"]["high-priority-named"]) {
|
||||
high_priority_named_.push_back(it.asString());
|
||||
@@ -37,11 +55,27 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(box_);
|
||||
if (config_["format-window-separator"].isString()) {
|
||||
m_formatWindowSeperator = config_["format-window-separator"].asString();
|
||||
} else {
|
||||
m_formatWindowSeperator = " ";
|
||||
}
|
||||
const Json::Value &windowRewrite = config["window-rewrite"];
|
||||
|
||||
const Json::Value &windowRewriteDefaultConfig = config["window-rewrite-default"];
|
||||
m_windowRewriteDefault =
|
||||
windowRewriteDefaultConfig.isString() ? windowRewriteDefaultConfig.asString() : "?";
|
||||
|
||||
m_windowRewriteRules = waybar::util::RegexCollection(
|
||||
windowRewrite, m_windowRewriteDefault,
|
||||
[this](std::string &window_rule) { return windowRewritePriorityFunction(window_rule); });
|
||||
ipc_.subscribe(R"(["workspace"])");
|
||||
ipc_.subscribe(R"(["window"])");
|
||||
ipc_.signal_event.connect(sigc::mem_fun(*this, &Workspaces::onEvent));
|
||||
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
||||
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||
ipc_.sendCmd(IPC_GET_TREE);
|
||||
if (config["enable-bar-scroll"].asBool()) {
|
||||
auto &window = const_cast<Bar &>(bar_).window;
|
||||
window.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||
@@ -59,26 +93,33 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
||||
|
||||
void Workspaces::onEvent(const struct Ipc::ipc_response &res) {
|
||||
try {
|
||||
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||
ipc_.sendCmd(IPC_GET_TREE);
|
||||
} catch (const std::exception &e) {
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
||||
if (res.type == IPC_GET_WORKSPACES) {
|
||||
if (res.type == IPC_GET_TREE) {
|
||||
try {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto payload = parser_.parse(res.payload);
|
||||
workspaces_.clear();
|
||||
std::copy_if(payload.begin(), payload.end(), std::back_inserter(workspaces_),
|
||||
std::vector<Json::Value> outputs;
|
||||
std::copy_if(payload["nodes"].begin(), payload["nodes"].end(), std::back_inserter(outputs),
|
||||
[&](const auto &workspace) {
|
||||
return !config_["all-outputs"].asBool()
|
||||
? workspace["output"].asString() == bar_.output->name
|
||||
? workspace["name"].asString() == bar_.output->name
|
||||
: true;
|
||||
});
|
||||
|
||||
for (auto &output : outputs) {
|
||||
std::copy(output["nodes"].begin(), output["nodes"].end(),
|
||||
std::back_inserter(workspaces_));
|
||||
std::copy(output["floating_nodes"].begin(), output["floating_nodes"].end(),
|
||||
std::back_inserter(workspaces_));
|
||||
}
|
||||
if (config_["persistent_workspaces"].isObject()) {
|
||||
spdlog::warn(
|
||||
"persistent_workspaces is deprecated. Please change config to use "
|
||||
@@ -203,6 +244,40 @@ bool Workspaces::filterButtons() {
|
||||
return needReorder;
|
||||
}
|
||||
|
||||
bool Workspaces::hasFlag(const Json::Value &node, const std::string &flag) {
|
||||
if (node[flag].asBool()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::any_of(node["nodes"].begin(), node["nodes"].end(),
|
||||
[&](auto const &e) { return hasFlag(e, flag); })) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Workspaces::updateWindows(const Json::Value &node, std::string &windows) {
|
||||
auto format = config_["window-format"].asString();
|
||||
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 windowReprKey = fmt::format("class<{}> title<{}>", windowClass, title);
|
||||
std::string window = m_windowRewriteRules.get(windowReprKey);
|
||||
// allow result to have formatting
|
||||
window =
|
||||
fmt::format(fmt::runtime(window), fmt::arg("name", title), fmt::arg("class", windowClass));
|
||||
windows.append(window);
|
||||
windows.append(m_formatWindowSeperator);
|
||||
}
|
||||
for (const Json::Value &child : node["nodes"]) {
|
||||
updateWindows(child, windows);
|
||||
}
|
||||
for (const Json::Value &child : node["floating_nodes"]) {
|
||||
updateWindows(child, windows);
|
||||
}
|
||||
}
|
||||
|
||||
auto Workspaces::update() -> void {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
bool needReorder = filterButtons();
|
||||
@@ -212,22 +287,25 @@ auto Workspaces::update() -> void {
|
||||
needReorder = true;
|
||||
}
|
||||
auto &button = bit == buttons_.end() ? addButton(*it) : bit->second;
|
||||
if ((*it)["focused"].asBool()) {
|
||||
if (needReorder) {
|
||||
box_.reorder_child(button, it - workspaces_.begin());
|
||||
}
|
||||
if (hasFlag((*it), "focused")) {
|
||||
button.get_style_context()->add_class("focused");
|
||||
} else {
|
||||
button.get_style_context()->remove_class("focused");
|
||||
}
|
||||
if ((*it)["visible"].asBool()) {
|
||||
if (hasFlag((*it), "visible")) {
|
||||
button.get_style_context()->add_class("visible");
|
||||
} else {
|
||||
button.get_style_context()->remove_class("visible");
|
||||
}
|
||||
if ((*it)["urgent"].asBool()) {
|
||||
if (hasFlag((*it), "urgent")) {
|
||||
button.get_style_context()->add_class("urgent");
|
||||
} else {
|
||||
button.get_style_context()->remove_class("urgent");
|
||||
}
|
||||
if ((*it)["target_output"].isString()) {
|
||||
if (hasFlag((*it), "target_output")) {
|
||||
button.get_style_context()->add_class("persistent");
|
||||
} else {
|
||||
button.get_style_context()->remove_class("persistent");
|
||||
@@ -241,16 +319,19 @@ auto Workspaces::update() -> void {
|
||||
} else {
|
||||
button.get_style_context()->remove_class("current_output");
|
||||
}
|
||||
if (needReorder) {
|
||||
box_.reorder_child(button, it - workspaces_.begin());
|
||||
}
|
||||
std::string output = (*it)["name"].asString();
|
||||
std::string windows = "";
|
||||
if (config_["window-format"].isString()) {
|
||||
updateWindows((*it), windows);
|
||||
}
|
||||
if (config_["format"].isString()) {
|
||||
auto format = config_["format"].asString();
|
||||
output = fmt::format(fmt::runtime(format), fmt::arg("icon", getIcon(output, *it)),
|
||||
fmt::arg("value", output), fmt::arg("name", trimWorkspaceName(output)),
|
||||
fmt::arg("index", (*it)["num"].asString()),
|
||||
fmt::arg("output", (*it)["output"].asString()));
|
||||
output = fmt::format(
|
||||
fmt::runtime(format), fmt::arg("icon", getIcon(output, *it)), fmt::arg("value", output),
|
||||
fmt::arg("name", trimWorkspaceName(output)), fmt::arg("index", (*it)["num"].asString()),
|
||||
fmt::arg("windows",
|
||||
windows.substr(0, windows.length() - m_formatWindowSeperator.length())),
|
||||
fmt::arg("output", (*it)["output"].asString()));
|
||||
}
|
||||
if (!config_["disable-markup"].asBool()) {
|
||||
static_cast<Gtk::Label *>(button.get_children()[0])->set_markup(output);
|
||||
|
@@ -24,11 +24,16 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
|
||||
}
|
||||
}
|
||||
} else if (config_["hwmon-path-abs"].isString() && config_["input-filename"].isString()) {
|
||||
file_path_ = (*std::filesystem::directory_iterator(config_["hwmon-path-abs"].asString()))
|
||||
.path()
|
||||
.string() +
|
||||
"/" + config_["input-filename"].asString();
|
||||
} else {
|
||||
for (const auto& hwmon :
|
||||
std::filesystem::directory_iterator(config_["hwmon-path-abs"].asString())) {
|
||||
if (hwmon.path().filename().string().starts_with("hwmon")) {
|
||||
file_path_ = hwmon.path().string() + "/" + config_["input-filename"].asString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file_path_.empty()) {
|
||||
auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
|
||||
file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
|
||||
}
|
||||
|
@@ -277,7 +277,7 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar,
|
||||
handle_{tl_handle},
|
||||
seat_{seat},
|
||||
id_{global_id++},
|
||||
content_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0} {
|
||||
content_{bar.orientation, 0} {
|
||||
zwlr_foreign_toplevel_handle_v1_add_listener(handle_, &toplevel_handle_impl, this);
|
||||
|
||||
button.set_relief(Gtk::RELIEF_NONE);
|
||||
@@ -730,13 +730,14 @@ static const wl_registry_listener registry_listener_impl = {.global = handle_glo
|
||||
Taskbar::Taskbar(const std::string &id, const waybar::Bar &bar, const Json::Value &config)
|
||||
: waybar::AModule(config, "taskbar", id, false, false),
|
||||
bar_(bar),
|
||||
box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
|
||||
box_{bar.orientation, 0},
|
||||
manager_{nullptr},
|
||||
seat_{nullptr} {
|
||||
box_.set_name("taskbar");
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
box_.get_style_context()->add_class("empty");
|
||||
event_box_.add(box_);
|
||||
|
||||
|
@@ -21,9 +21,7 @@ std::map<std::string, std::string> Workspace::icons_map_;
|
||||
|
||||
WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar,
|
||||
const Json::Value &config)
|
||||
: waybar::AModule(config, "workspaces", id, false, false),
|
||||
bar_(bar),
|
||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) {
|
||||
: waybar::AModule(config, "workspaces", id, false, false), bar_(bar), box_(bar.orientation, 0) {
|
||||
auto config_sort_by_name = config_["sort-by-name"];
|
||||
if (config_sort_by_name.isBool()) {
|
||||
sort_by_name_ = config_sort_by_name.asBool();
|
||||
@@ -54,6 +52,7 @@ WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
box_.get_style_context()->add_class(MODULE_CLASS);
|
||||
event_box_.add(box_);
|
||||
|
||||
add_registry_listener(this);
|
||||
|
Reference in New Issue
Block a user