From 1175bbbc23a90f005f8bb935488a724238aef1ac Mon Sep 17 00:00:00 2001 From: Raphael Robatsch Date: Wed, 27 Oct 2021 17:24:47 +0200 Subject: [PATCH] capture xdg-output names --- protocols/meson.build | 1 + src/main.cpp | 63 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/protocols/meson.build b/protocols/meson.build index cefdf64..023c918 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -13,6 +13,7 @@ wayland_scanner_client = generator( wayland_xmls = [ wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml', + wl_protocol_dir + '/unstable/xdg-output/xdg-output-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'net-tapesoftware-dwl-wm-unstable-v1.xml', ] diff --git a/src/main.cpp b/src/main.cpp index 86a822a..2480237 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,17 +19,20 @@ #include #include #include "wlr-layer-shell-unstable-v1-client-protocol.h" +#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-shell-client-protocol.h" #include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h" #include "common.hpp" #include "bar.hpp" struct Monitor { - uint32_t name; + uint32_t registryName; + std::string xdgName; wl_unique_ptr wlOutput; wl_unique_ptr dwlMonitor; std::optional bar; }; + struct SeatPointer { wl_unique_ptr wlPointer; Bar *focusedBar; @@ -58,6 +61,7 @@ znet_tapesoftware_dwl_wm_v1 *dwlWm; std::vector tagNames; std::vector layoutNames; static xdg_wm_base *xdgWmBase; +static zxdg_output_manager_v1 *xdgOutputManager; static wl_surface *cursorSurface; static wl_cursor_image *cursorImage; static bool ready; @@ -71,6 +75,10 @@ static int statusFifoFd {-1}; static int statusFifoWriter {-1}; static bool quitting {false}; +// Intentionally not inside Monitor, so we can preemptively manage the +// visibility of bars on future outputs. +static std::unordered_map barVisibility; + void view(Monitor &m, const Arg &arg) { znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), arg.ui, 1); @@ -109,6 +117,18 @@ static const struct xdg_wm_base_listener xdgWmBaseListener = { } }; +static const struct zxdg_output_v1_listener xdgOutputListener = { + .logical_position = [](void*, zxdg_output_v1*, int, int) { }, + .logical_size = [](void*, zxdg_output_v1*, int, int) { }, + .done = [](void*, zxdg_output_v1*) { }, + .name = [](void *mp, zxdg_output_v1 *xdgOutput, const char *name) { + auto& monitor = *static_cast(mp); + monitor.xdgName = name; + zxdg_output_v1_destroy(xdgOutput); + }, + .description = [](void*, zxdg_output_v1*, const char*) { }, +}; + static Bar* barFromSurface(const wl_surface *surface) { auto mon = std::find_if(begin(monitors), end(monitors), [surface](const Monitor &mon) { @@ -221,6 +241,8 @@ static void setupMonitor(Monitor &monitor) { monitor.bar.emplace(&monitor); monitor.bar->setStatus(lastStatus); znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor); + auto xdgOutput = zxdg_output_manager_v1_get_xdg_output(xdgOutputManager, monitor.wlOutput.get()); + zxdg_output_v1_add_listener(xdgOutput, &xdgOutputListener, &monitor); } // called after we have received the initial batch of globals @@ -229,6 +251,7 @@ static void onReady() requireGlobal(compositor, "wl_compositor"); requireGlobal(shm, "wl_shm"); requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1"); + requireGlobal(xdgOutputManager, "zxdg_output_manager_v1"); requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1"); setupStatusFifo(); wl_display_roundtrip(display); // roundtrip so we receive all dwl tags etc. @@ -270,16 +293,39 @@ static void setupStatusFifo() } } +const std::string prefixStatus = "status "; +const std::string prefixShow = "show "; +const std::string prefixHide = "hide "; +const std::string prefixToggle = "toggle "; +const std::string argAll = "all"; +const std::string argCurrent = "current"; + +template +static void updateVisibility(const std::string &name, T updater) +{ + auto isCurrent = name == argCurrent; + auto isAll = name == argAll; +} + static void onStatus() { char buffer[512]; auto n = read(statusFifoFd, buffer, sizeof(buffer)); - lastStatus = {buffer, (unsigned long) n}; - for (auto &monitor : monitors) { - if (monitor.bar) { - monitor.bar->setStatus(lastStatus); - monitor.bar->invalidate(); + auto str = std::string {buffer, (unsigned long) n}; + if (str.rfind(prefixStatus, 0) == 0) { + lastStatus = str.substr(prefixStatus.size()); + for (auto &monitor : monitors) { + if (monitor.bar) { + monitor.bar->setStatus(lastStatus); + monitor.bar->invalidate(); + } } + } else if (str.rfind(prefixShow, 0) == 0) { + updateVisibility(str.substr(prefixShow.size()), [](bool) { return true; }); + } else if (str.rfind(prefixHide, 0) == 0) { + updateVisibility(str.substr(prefixHide.size()), [](bool) { return false; }); + } else if (str.rfind(prefixToggle, 0) == 0) { + updateVisibility(str.substr(prefixToggle.size()), [](bool vis) { return !vis; }); } } @@ -301,6 +347,7 @@ static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, co if (reg.handle(compositor, wl_compositor_interface, 4)) return; if (reg.handle(shm, wl_shm_interface, 1)) return; if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 4)) return; + if (reg.handle(xdgOutputManager, zxdg_output_manager_v1_interface, 3)) return; if (reg.handle(xdgWmBase, xdg_wm_base_interface, 2)) { xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr); return; @@ -315,7 +362,7 @@ static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, co return; } if (wl_output *output; reg.handle(output, wl_output_interface, 1)) { - auto& m = monitors.emplace_back(Monitor {name, wl_unique_ptr {output}}); + auto& m = monitors.emplace_back(Monitor {name, {}, wl_unique_ptr {output}}); if (ready) { setupMonitor(m); } @@ -324,7 +371,7 @@ static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, co } static void registryHandleRemove(void*, wl_registry *registry, uint32_t name) { - monitors.remove_if([name](const Monitor &mon) { return mon.name == name; }); + monitors.remove_if([name](const Monitor &mon) { return mon.registryName == name; }); seats.remove_if([name](const Seat &seat) { return seat.name == name; }); } static const struct wl_registry_listener registry_listener = {