From 57063cb17f2a05e192dda094d905ce56f1440be2 Mon Sep 17 00:00:00 2001 From: Raphael Robatsch Date: Wed, 27 Oct 2021 17:24:47 +0200 Subject: [PATCH] bar hide/show commands --- meson.build | 2 +- src/main.cpp | 91 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 61 insertions(+), 32 deletions(-) diff --git a/meson.build b/meson.build index e81761b..4043100 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('somebar', ['c', 'cpp'], - default_options: ['cpp_std=c++17']) + default_options: ['cpp_std=c++17', 'cpp_args=-Wno-parentheses']) wayland_dep = dependency('wayland-client') wayland_cursor_dep = dependency('wayland-cursor') diff --git a/src/main.cpp b/src/main.cpp index 2480237..e7f6294 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,8 @@ struct Monitor { wl_unique_ptr wlOutput; wl_unique_ptr dwlMonitor; std::optional bar; + bool desiredVisibility {true}; + bool hasData; }; struct SeatPointer { @@ -45,13 +47,14 @@ struct Seat { std::optional pointer; }; -static void waylandFlush(); -static void requireGlobal(const void *p, const char *name); +static void updatemon(Monitor &mon); static void setupStatusFifo(); static void onStatus(); +static void cleanup(); +static void requireGlobal(const void *p, const char *name); +static void waylandFlush(); [[noreturn]] static void diesys(const char *why); [[noreturn]] static void die(const char *why); -static void cleanup(); wl_display *display; wl_compositor *compositor; @@ -67,6 +70,7 @@ static wl_cursor_image *cursorImage; static bool ready; static std::list monitors; static std::list seats; +static Monitor *selmon; static std::string lastStatus; static std::string statusFifoName; static int epoll {-1}; @@ -75,10 +79,6 @@ 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); @@ -212,6 +212,11 @@ static const struct znet_tapesoftware_dwl_wm_v1_listener dwlWmListener = { static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorListener { .selected = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t selected) { auto mon = static_cast(mv); + if (selected) { + selmon = mon; + } else if (selmon == mon) { + selmon = nullptr; + } mon->bar->setSelected(selected); }, .tag = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t tag, uint32_t state, uint32_t numClients, int32_t focusedClient) { @@ -228,11 +233,8 @@ static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorLis }, .frame = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*) { auto mon = static_cast(mv); - if (mon->bar->visible()) { - mon->bar->invalidate(); - } else { - mon->bar->show(mon->wlOutput.get()); - } + mon->hasData = true; + updatemon(*mon); } }; @@ -240,9 +242,23 @@ static void setupMonitor(Monitor &monitor) { monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get())); 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); + znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor); +} + +static void updatemon(Monitor &mon) +{ + if (!mon.hasData) return; + if (mon.desiredVisibility) { + if (mon.bar->visible()) { + mon.bar->invalidate(); + } else { + mon.bar->show(mon.wlOutput.get()); + } + } else if (mon.bar->visible()) { + mon.bar->hide(); + } } // called after we have received the initial batch of globals @@ -305,13 +321,27 @@ static void updateVisibility(const std::string &name, T updater) { auto isCurrent = name == argCurrent; auto isAll = name == argAll; + for (auto& mon : monitors) { + if (isAll || + isCurrent && &mon == selmon || + mon.xdgName == name) { + auto newVisibility = updater(mon.desiredVisibility); + if (newVisibility != mon.desiredVisibility) { + mon.desiredVisibility = newVisibility; + updatemon(mon); + } + } + } } static void onStatus() { + // this doesn't handle cases where there's multiple or partial lines in the buffer char buffer[512]; auto n = read(statusFifoFd, buffer, sizeof(buffer)); auto str = std::string {buffer, (unsigned long) n}; + auto trailer = str.rfind('\n'); + if (trailer != std::string::npos) str.erase(trailer); if (str.rfind(prefixStatus, 0) == 0) { lastStatus = str.substr(prefixStatus.size()); for (auto &monitor : monitors) { @@ -454,24 +484,14 @@ int main(int argc, char **argv) cleanup(); } -void die(const char *why) { - fprintf(stderr, "%s\n", why); +void requireGlobal(const void *p, const char *name) +{ + if (p) return; + fprintf(stderr, "Wayland compositor does not export required global %s, aborting.\n", name); cleanup(); exit(1); } -void diesys(const char *why) { - perror(why); - cleanup(); - exit(1); -} - -void cleanup() { - if (!statusFifoName.empty()) { - unlink(statusFifoName.c_str()); - } -} - void waylandFlush() { wl_display_dispatch_pending(display); @@ -485,10 +505,19 @@ void waylandFlush() } } -static void requireGlobal(const void *p, const char *name) -{ - if (p) return; - fprintf(stderr, "Wayland compositor does not export required global %s, aborting.\n", name); +void die(const char *why) { cleanup(); exit(1); } + +void diesys(const char *why) { + perror(why); + cleanup(); + exit(1); +} + +void cleanup() { + if (!statusFifoName.empty()) { + unlink(statusFifoName.c_str()); + } +}