Merge remote-tracking branch 'origin/master' into pr-4014
# Conflicts: # include/group.hpp # src/group.cpp
This commit is contained in:
+130
-9
@@ -3,11 +3,15 @@
|
||||
#include <gtk-layer-shell.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "client.hpp"
|
||||
#include "factory.hpp"
|
||||
#include "group.hpp"
|
||||
#include "util/enum.hpp"
|
||||
#include "util/hosts_check.hpp"
|
||||
#include "util/kill_signal.hpp"
|
||||
|
||||
#ifdef HAVE_SWAY
|
||||
#include "modules/sway/bar.hpp"
|
||||
@@ -170,6 +174,10 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
right_.set_spacing(spacing);
|
||||
}
|
||||
|
||||
if (config.isMember("height") && !config["height"].isUInt()) {
|
||||
spdlog::warn("Invalid type for 'height', expected unsigned integer");
|
||||
}
|
||||
|
||||
height_ = config["height"].isUInt() ? config["height"].asUInt() : 0;
|
||||
width_ = config["width"].isUInt() ? config["width"].asUInt() : 0;
|
||||
|
||||
@@ -227,7 +235,8 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
gtk_layer_init_for_window(gtk_window);
|
||||
gtk_layer_set_keyboard_mode(gtk_window, GTK_LAYER_SHELL_KEYBOARD_MODE_NONE);
|
||||
gtk_layer_set_monitor(gtk_window, output->monitor->gobj());
|
||||
gtk_layer_set_namespace(gtk_window, "waybar");
|
||||
gtk_layer_set_namespace(gtk_window,
|
||||
config["name"].isString() ? config["name"].asCString() : "waybar");
|
||||
|
||||
gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, margins_.left);
|
||||
gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, margins_.right);
|
||||
@@ -260,6 +269,16 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
|
||||
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
|
||||
|
||||
window.signal_unmap().connect([this]() {
|
||||
spdlog::debug("Output {} unmapped (DPMS off), suspending modules", output->name);
|
||||
toggleSuspend(true);
|
||||
});
|
||||
|
||||
window.signal_map().connect([this]() {
|
||||
spdlog::debug("Output {} mapped (DPMS on), resuming modules", output->name);
|
||||
toggleSuspend(false);
|
||||
});
|
||||
|
||||
#if HAVE_SWAY
|
||||
if (auto ipc = config["ipc"]; ipc.isBool() && ipc.asBool()) {
|
||||
bar_id = Client::inst()->bar_id;
|
||||
@@ -277,9 +296,48 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
||||
}
|
||||
#endif
|
||||
|
||||
waybar::util::EnumParser<util::KillSignalAction> m_signalActionEnumParser;
|
||||
const auto& configSigusr1 = config["on-sigusr1"];
|
||||
if (configSigusr1.isString()) {
|
||||
auto strSigusr1 = configSigusr1.asString();
|
||||
try {
|
||||
onSigusr1 =
|
||||
m_signalActionEnumParser.parseStringToEnum(strSigusr1, util::userKillSignalActions);
|
||||
} catch (const std::invalid_argument& e) {
|
||||
onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1;
|
||||
spdlog::warn(
|
||||
"Invalid string representation for on-sigusr1. Falling back to default mode (toggle).");
|
||||
}
|
||||
}
|
||||
const auto& configSigusr2 = config["on-sigusr2"];
|
||||
if (configSigusr2.isString()) {
|
||||
auto strSigusr2 = configSigusr2.asString();
|
||||
try {
|
||||
onSigusr2 =
|
||||
m_signalActionEnumParser.parseStringToEnum(strSigusr2, util::userKillSignalActions);
|
||||
} catch (const std::invalid_argument& e) {
|
||||
onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2;
|
||||
spdlog::warn(
|
||||
"Invalid string representation for on-sigusr2. Falling back to default mode (reload).");
|
||||
}
|
||||
}
|
||||
|
||||
setupWidgets();
|
||||
window.show_all();
|
||||
|
||||
/*
|
||||
* If gtk-layer-shell's synchronous wait for the initial configure timed out, show_all() can
|
||||
* return with a configured but not-yet-presented surface. Kick GTK/layer-shell once control has
|
||||
* returned to the main loop, when any late initial configure has been dispatched and widgets have
|
||||
* had a chance to allocate/draw.
|
||||
*/
|
||||
Glib::signal_idle().connect(sigc::track_obj([this] {
|
||||
window.queue_resize();
|
||||
window.queue_draw();
|
||||
forceLayerCommit();
|
||||
return false;
|
||||
}, *this));
|
||||
|
||||
if (spdlog::should_log(spdlog::level::debug)) {
|
||||
// Unfortunately, this function isn't in the C++ bindings, so we have to call the C version.
|
||||
char* gtk_tree = gtk_style_context_to_string(
|
||||
@@ -345,7 +403,14 @@ void waybar::Bar::setMode(const struct bar_mode& mode) {
|
||||
* gtk-layer-shell schedules a commit on the next frame event in GTK, but this could fail in
|
||||
* certain scenarios, such as fully occluded bar.
|
||||
*/
|
||||
gtk_layer_try_force_commit(gtk_window);
|
||||
forceLayerCommit();
|
||||
}
|
||||
|
||||
void waybar::Bar::forceLayerCommit() {
|
||||
auto* gtk_window = window.gobj();
|
||||
if (gtk_window != nullptr && gtk_widget_get_realized(GTK_WIDGET(gtk_window))) {
|
||||
gtk_layer_try_force_commit(gtk_window);
|
||||
}
|
||||
wl_display_flush(Client::inst()->wl_display);
|
||||
}
|
||||
|
||||
@@ -405,7 +470,18 @@ void waybar::Bar::onMap(GdkEventAny* /*unused*/) {
|
||||
/*
|
||||
* Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor).
|
||||
*/
|
||||
auto* gdk_window = window.get_window()->gobj();
|
||||
auto gdk_window_ref = window.get_window();
|
||||
if (!gdk_window_ref) {
|
||||
spdlog::warn("Failed to get GDK window during onMap, deferring surface initialization");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* gdk_window = gdk_window_ref->gobj();
|
||||
if (!gdk_window) {
|
||||
spdlog::warn("GDK window object is null during onMap, deferring surface initialization");
|
||||
return;
|
||||
}
|
||||
|
||||
surface = gdk_wayland_window_get_wl_surface(gdk_window);
|
||||
configureGlobalOffset(gdk_window_get_width(gdk_window), gdk_window_get_height(gdk_window));
|
||||
|
||||
@@ -422,6 +498,8 @@ void waybar::Bar::setVisible(bool value) {
|
||||
}
|
||||
|
||||
void waybar::Bar::toggle() { setVisible(!visible); }
|
||||
void waybar::Bar::show() { setVisible(true); }
|
||||
void waybar::Bar::hide() { setVisible(false); }
|
||||
|
||||
// Converting string to button code rn as to avoid doing it later
|
||||
void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) {
|
||||
@@ -479,6 +557,9 @@ void waybar::Bar::handleSignal(int signal) {
|
||||
}
|
||||
}
|
||||
|
||||
waybar::util::KillSignalAction waybar::Bar::getOnSigusr1Action() { return this->onSigusr1; }
|
||||
waybar::util::KillSignalAction waybar::Bar::getOnSigusr2Action() { return this->onSigusr2; }
|
||||
|
||||
void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||
waybar::Group* group = nullptr) {
|
||||
auto module_list = group != nullptr ? config[pos]["modules"] : config[pos];
|
||||
@@ -486,6 +567,11 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||
for (const auto& name : module_list) {
|
||||
try {
|
||||
auto ref = name.asString();
|
||||
|
||||
if (config[ref].isMember("hosts") && !waybar::util::valid_host(config[ref])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AModule* module;
|
||||
|
||||
if (ref.compare(0, 6, "group/") == 0 && ref.size() > 6) {
|
||||
@@ -496,9 +582,15 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
||||
auto vertical = (group != nullptr ? group->getBox().get_orientation()
|
||||
: box_.get_orientation()) == Gtk::ORIENTATION_VERTICAL;
|
||||
|
||||
auto* group_module = new waybar::Group(id_name, class_name, config[ref], vertical);
|
||||
getModules(factory, ref, group_module);
|
||||
module = group_module;
|
||||
const Json::Value& group_config = config[ref];
|
||||
if (group_config["modules"].isNull()) {
|
||||
spdlog::warn("Group definition '{}' has not been found, group will be hidden", ref);
|
||||
}
|
||||
auto group_module =
|
||||
std::make_unique<waybar::Group>(id_name, class_name, group_config, vertical);
|
||||
|
||||
getModules(factory, ref, group_module.get());
|
||||
module = group_module.release();
|
||||
} else {
|
||||
module = factory.makeModule(ref, pos);
|
||||
}
|
||||
@@ -545,7 +637,6 @@ auto waybar::Bar::setupWidgets() -> void {
|
||||
if (config["fixed-center"].isBool() ? config["fixed-center"].asBool() : true) {
|
||||
box_.set_center_widget(center_);
|
||||
} else {
|
||||
spdlog::error("No fixed center_");
|
||||
box_.pack_start(center_, true, expand_center);
|
||||
}
|
||||
}
|
||||
@@ -569,13 +660,13 @@ auto waybar::Bar::setupWidgets() -> void {
|
||||
|
||||
if (!no_center) {
|
||||
for (auto const& module : modules_center_) {
|
||||
center_.pack_start(*module, false, false);
|
||||
center_.pack_start(*module, module->expandEnabled(), module->expandEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
std::reverse(modules_right_.begin(), modules_right_.end());
|
||||
for (auto const& module : modules_right_) {
|
||||
right_.pack_end(*module, false, false);
|
||||
right_.pack_end(*module, module->expandEnabled(), module->expandEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,6 +693,17 @@ void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
|
||||
|
||||
configureGlobalOffset(ev->width, ev->height);
|
||||
spdlog::info(BAR_SIZE_MSG, ev->width, ev->height, output->name);
|
||||
|
||||
/*
|
||||
* gtk-layer-shell waits for the compositor's initial configure while realizing the window. On a
|
||||
* busy compositor (common during session startup) that wait can time out even though the initial
|
||||
* configure arrives shortly afterwards. In that case GTK may not schedule the frame commit that
|
||||
* presents the first layer-surface buffer, leaving an otherwise configured bar invisible. Force a
|
||||
* commit after every configure so late initial configures, and later compositor-driven resizes,
|
||||
* always result in a submitted surface state.
|
||||
*/
|
||||
window.queue_draw();
|
||||
forceLayerCommit();
|
||||
}
|
||||
|
||||
void waybar::Bar::configureGlobalOffset(int width, int height) {
|
||||
@@ -646,3 +748,22 @@ void waybar::Bar::configureGlobalOffset(int width, int height) {
|
||||
void waybar::Bar::onOutputGeometryChanged() {
|
||||
configureGlobalOffset(window.get_width(), window.get_height());
|
||||
}
|
||||
|
||||
void waybar::Bar::toggleSuspend(bool suspend) {
|
||||
auto process_modules = [suspend](Gtk::Box& module_box) {
|
||||
for (auto* widget : module_box.get_children()) {
|
||||
auto* module = dynamic_cast<waybar::AModule*>(widget);
|
||||
if (module && module->shouldSuspend()) {
|
||||
if (suspend) {
|
||||
module->suspend();
|
||||
} else {
|
||||
module->resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
process_modules(left_);
|
||||
process_modules(center_);
|
||||
process_modules(right_);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user