From 3663b9193dc6e3100fa02c472e5b068e988a8f81 Mon Sep 17 00:00:00 2001 From: Aleksei Bavshin Date: Sun, 9 Aug 2020 18:58:01 -0700 Subject: [PATCH] refactor(bar): separate GTK event handlers for gtk-layer-shell Cleanly separate resizing logic for gtk-layer-shell and manually managed layer surface code. --- include/bar.hpp | 7 ++- src/bar.cpp | 127 +++++++++++++++++++++++++++++++----------------- 2 files changed, 89 insertions(+), 45 deletions(-) diff --git a/include/bar.hpp b/include/bar.hpp index 63f0e221..fdc5a739 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -53,13 +53,18 @@ class Bar { static void layerSurfaceHandleClosed(void *, struct zwlr_layer_surface_v1 *); #ifdef HAVE_GTK_LAYER_SHELL + /* gtk-layer-shell code */ void initGtkLayerShell(); + void onConfigureGLS(GdkEventConfigure *ev); + void onMapGLS(GdkEventAny *ev); #endif + /* fallback layer-surface code */ void onConfigure(GdkEventConfigure *ev); void onRealize(); void onMap(GdkEventAny *ev); - void setExclusiveZone(uint32_t width, uint32_t height); void setSurfaceSize(uint32_t width, uint32_t height); + /* common code */ + void setExclusiveZone(uint32_t width, uint32_t height); auto setupWidgets() -> void; void getModules(const Factory &, const std::string &); void setupAltFormatKeyForModule(const std::string &module_name); diff --git a/src/bar.cpp b/src/bar.cpp index 3bbc2a35..45e34201 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -101,56 +101,25 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) use_gls_ = config["gtk-layer-shell"].isBool() ? config["gtk-layer-shell"].asBool() : true; if (use_gls_) { initGtkLayerShell(); + window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMapGLS)); + window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigureGLS)); } #endif - window.signal_realize().connect_notify(sigc::mem_fun(*this, &Bar::onRealize)); - window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap)); - window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure)); + if (!use_gls_) { + window.signal_realize().connect_notify(sigc::mem_fun(*this, &Bar::onRealize)); + window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap)); + window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure)); + } window.set_size_request(width_, height_); setupWidgets(); - if (window.get_realized()) { + if (!use_gls_ && window.get_realized()) { onRealize(); } window.show_all(); } -void waybar::Bar::onConfigure(GdkEventConfigure* ev) { - auto tmp_height = height_; - auto tmp_width = width_; - if (ev->height > static_cast(height_)) { - // Default minimal value - if (height_ > 1) { - spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height); - } - if (config["height"].isUInt()) { - spdlog::info(SIZE_DEFINED, "Height"); - } else { - tmp_height = ev->height; - } - } - if (ev->width > static_cast(width_)) { - // Default minimal value - if (width_ > 1) { - spdlog::warn(MIN_WIDTH_MSG, width_, ev->width); - } - if (config["width"].isUInt()) { - spdlog::info(SIZE_DEFINED, "Width"); - } else { - tmp_width = ev->width; - } - } - if (use_gls_) { - width_ = tmp_width; - height_ = tmp_height; - spdlog::debug("Set surface size {}x{} for output {}", width_, height_, output->name); - setExclusiveZone(tmp_width, tmp_height); - } else if (tmp_width != width_ || tmp_height != height_) { - setSurfaceSize(tmp_width, tmp_height); - } -} - #ifdef HAVE_GTK_LAYER_SHELL void waybar::Bar::initGtkLayerShell() { auto gtk_window = window.gobj(); @@ -181,8 +150,80 @@ void waybar::Bar::initGtkLayerShell() { setExclusiveZone(width_, height_); } } + +void waybar::Bar::onConfigureGLS(GdkEventConfigure* ev) { + /* + * GTK wants new size for the window. + * Actual resizing is done within the gtk-layer-shell code; the only remaining action is to apply + * exclusive zone. + * gtk_layer_auto_exclusive_zone_enable() could handle even that, but at the cost of ignoring + * margins on unanchored edge. + * + * Note: forced resizing to a window smaller than required by GTK would not work with + * gtk-layer-shell. + */ + if (vertical) { + if (width_ > 1 && ev->width > static_cast(width_)) { + spdlog::warn(MIN_WIDTH_MSG, width_, ev->width); + } + } else { + if (!vertical && height_ > 1 && ev->height > static_cast(height_)) { + spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height); + } + } + width_ = ev->width; + height_ = ev->height; + spdlog::info(BAR_SIZE_MSG, width_, height_, output->name); + setExclusiveZone(width_, height_); +} + +void waybar::Bar::onMapGLS(GdkEventAny* ev) { + /* + * Obtain a pointer to the custom layer surface for modules that require it (idle_inhibitor). + */ + auto gdk_window = window.get_window(); + surface = gdk_wayland_window_get_wl_surface(gdk_window->gobj()); +} + #endif +void waybar::Bar::onConfigure(GdkEventConfigure* ev) { + /* + * GTK wants new size for the window. + * + * Prefer configured size if it's non-default. + * If the size is not set and the window is smaller than requested by GTK, request resize from + * layer surface. + */ + auto tmp_height = height_; + auto tmp_width = width_; + if (ev->height > static_cast(height_)) { + // Default minimal value + if (height_ > 1) { + spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height); + } + if (config["height"].isUInt()) { + spdlog::info(SIZE_DEFINED, "Height"); + } else { + tmp_height = ev->height; + } + } + if (ev->width > static_cast(width_)) { + // Default minimal value + if (width_ > 1) { + spdlog::warn(MIN_WIDTH_MSG, width_, ev->width); + } + if (config["width"].isUInt()) { + spdlog::info(SIZE_DEFINED, "Width"); + } else { + tmp_width = ev->width; + } + } + if (tmp_width != width_ || tmp_height != height_) { + setSurfaceSize(tmp_width, tmp_height); + } +} + void waybar::Bar::onRealize() { auto gdk_window = window.get_window()->gobj(); gdk_wayland_window_set_use_custom_surface(gdk_window); @@ -192,10 +233,6 @@ void waybar::Bar::onMap(GdkEventAny* ev) { auto gdk_window = window.get_window()->gobj(); surface = gdk_wayland_window_get_wl_surface(gdk_window); - if (use_gls_) { - return; - } - auto client = waybar::Client::inst(); // owned by output->monitor; no need to destroy auto wl_output = gdk_wayland_monitor_get_wl_output(output->monitor->gobj()); @@ -362,7 +399,9 @@ auto waybar::Bar::toggle() -> void { window.set_opacity(1); } setExclusiveZone(width_, height_); - wl_surface_commit(surface); + if (!use_gls_) { + wl_surface_commit(surface); + } } void waybar::Bar::getModules(const Factory& factory, const std::string& pos) {