refactor(bar): separate GTK event handlers for gtk-layer-shell

Cleanly separate resizing logic for gtk-layer-shell and manually managed
layer surface code.
This commit is contained in:
Aleksei Bavshin 2020-08-09 18:58:01 -07:00
parent 591eb2ea38
commit 3663b9193d
No known key found for this signature in database
GPG Key ID: 4F071603387A382A
2 changed files with 89 additions and 45 deletions

View File

@ -53,13 +53,18 @@ class Bar {
static void layerSurfaceHandleClosed(void *, struct zwlr_layer_surface_v1 *); static void layerSurfaceHandleClosed(void *, struct zwlr_layer_surface_v1 *);
#ifdef HAVE_GTK_LAYER_SHELL #ifdef HAVE_GTK_LAYER_SHELL
/* gtk-layer-shell code */
void initGtkLayerShell(); void initGtkLayerShell();
void onConfigureGLS(GdkEventConfigure *ev);
void onMapGLS(GdkEventAny *ev);
#endif #endif
/* fallback layer-surface code */
void onConfigure(GdkEventConfigure *ev); void onConfigure(GdkEventConfigure *ev);
void onRealize(); void onRealize();
void onMap(GdkEventAny *ev); void onMap(GdkEventAny *ev);
void setExclusiveZone(uint32_t width, uint32_t height);
void setSurfaceSize(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; auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &); void getModules(const Factory &, const std::string &);
void setupAltFormatKeyForModule(const std::string &module_name); void setupAltFormatKeyForModule(const std::string &module_name);

View File

@ -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; use_gls_ = config["gtk-layer-shell"].isBool() ? config["gtk-layer-shell"].asBool() : true;
if (use_gls_) { if (use_gls_) {
initGtkLayerShell(); 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 #endif
if (!use_gls_) {
window.signal_realize().connect_notify(sigc::mem_fun(*this, &Bar::onRealize)); 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_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure)); window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
}
window.set_size_request(width_, height_); window.set_size_request(width_, height_);
setupWidgets(); setupWidgets();
if (window.get_realized()) { if (!use_gls_ && window.get_realized()) {
onRealize(); onRealize();
} }
window.show_all(); window.show_all();
} }
void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
auto tmp_height = height_;
auto tmp_width = width_;
if (ev->height > static_cast<int>(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<int>(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 #ifdef HAVE_GTK_LAYER_SHELL
void waybar::Bar::initGtkLayerShell() { void waybar::Bar::initGtkLayerShell() {
auto gtk_window = window.gobj(); auto gtk_window = window.gobj();
@ -181,8 +150,80 @@ void waybar::Bar::initGtkLayerShell() {
setExclusiveZone(width_, height_); 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<int>(width_)) {
spdlog::warn(MIN_WIDTH_MSG, width_, ev->width);
}
} else {
if (!vertical && height_ > 1 && ev->height > static_cast<int>(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 #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<int>(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<int>(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() { void waybar::Bar::onRealize() {
auto gdk_window = window.get_window()->gobj(); auto gdk_window = window.get_window()->gobj();
gdk_wayland_window_set_use_custom_surface(gdk_window); 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(); auto gdk_window = window.get_window()->gobj();
surface = gdk_wayland_window_get_wl_surface(gdk_window); surface = gdk_wayland_window_get_wl_surface(gdk_window);
if (use_gls_) {
return;
}
auto client = waybar::Client::inst(); auto client = waybar::Client::inst();
// owned by output->monitor; no need to destroy // owned by output->monitor; no need to destroy
auto wl_output = gdk_wayland_monitor_get_wl_output(output->monitor->gobj()); auto wl_output = gdk_wayland_monitor_get_wl_output(output->monitor->gobj());
@ -362,8 +399,10 @@ auto waybar::Bar::toggle() -> void {
window.set_opacity(1); window.set_opacity(1);
} }
setExclusiveZone(width_, height_); setExclusiveZone(width_, height_);
if (!use_gls_) {
wl_surface_commit(surface); wl_surface_commit(surface);
} }
}
void waybar::Bar::getModules(const Factory& factory, const std::string& pos) { void waybar::Bar::getModules(const Factory& factory, const std::string& pos) {
if (config[pos].isArray()) { if (config[pos].isArray()) {