diff --git a/CHANGELOG.md b/CHANGELOG.md index fd6313a4..8955e4e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Waiting for double click interval on modules that don't have a double click action ([`#2663`](https://github.com/polybar/polybar/issues/2663), [`#2695`](https://github.com/polybar/polybar/pull/2695)) +## [3.6.3] - 2022-05-04 +### Fixed +- `custom/script`: Output clearing when `exec-if` fails ([`#2674`](https://github.com/polybar/polybar/issues/2674)) +- `internal/battery`: `poll-interval` not working ([`#2649`](https://github.com/polybar/polybar/issues/2649), [`#2677`](https://github.com/polybar/polybar/pull/2677)) +- ipc: Polybar failing to open IPC channel after another user already ran polybar, if `XDG_RUNTIME_DIR` is not set ([`#2683`](https://github.com/polybar/polybar/issues/2683), [`#2684`](https://github.com/polybar/polybar/pull/2684)) +- No overlines/underlines being drawn when using offsets ([`#2685`](https://github.com/polybar/polybar/pull/2685)) +- Update struts (`_NET_WM_STRUT_PARTIAL`) when hiding the bar ([`#2702`](https://github.com/polybar/polybar/pull/2702)) +- `internal/pulseaudio`: Hanging during startup ([`#2707`](https://github.com/polybar/polybar/issues/2707), [`#2709`](https://github.com/polybar/polybar/pull/2709)) +- `internal/xworkspaces`: Updates of `_NET_DESKTOP_VIEWPORT` being ignored ([`#2693`](https://github.com/polybar/polybar/issues/2693), [`#2698`](https://github.com/polybar/polybar/pull/2698)) + ## [3.6.2] - 2022-04-03 ### Fixed - `format-offset` being ignored ([`#2643`](https://github.com/polybar/polybar/pull/2643)) @@ -191,7 +201,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Empty color values are no longer treated as invalid and no longer produce an error. -[Unreleased]: https://github.com/polybar/polybar/compare/3.6.2...HEAD +[Unreleased]: https://github.com/polybar/polybar/compare/3.6.3...HEAD +[3.6.3]: https://github.com/polybar/polybar/releases/tag/3.6.3 [3.6.2]: https://github.com/polybar/polybar/releases/tag/3.6.2 [3.6.1]: https://github.com/polybar/polybar/releases/tag/3.6.1 [3.6.0]: https://github.com/polybar/polybar/releases/tag/3.6.0 diff --git a/doc/user/actions.rst b/doc/user/actions.rst index 850a8c4a..24c6089f 100644 --- a/doc/user/actions.rst +++ b/doc/user/actions.rst @@ -406,20 +406,22 @@ Below you can see an example of a menu module: [module/apps] type = custom/menu + label-open = Apps + menu-0-0 = Browsers menu-0-0-exec = menu-open-1 menu-0-1 = Multimedia menu-0-1-exec = menu-open-2 menu-1-0 = Firefox - menu-1-0-exec = firefox & + menu-1-0-exec = firefox menu-1-1 = Chromium - menu-1-1-exec = chromium & + menu-1-1-exec = chromium menu-2-0 = Gimp - menu-2-0-exec = gimp & + menu-2-0-exec = gimp menu-2-1 = Scrot - menu-2-1-exec = scrot & + menu-2-1-exec = scrot This module uses two actions: ``menu-open-1`` and ``menu-open-2``. These are actions with data, the data specifies which level of the menu should @@ -437,17 +439,19 @@ likely not use ``apps``, but the name of your module. [module/apps] type = custom/menu + label-open = Apps + menu-0-0 = Browsers menu-0-0-exec = #apps.open.1 menu-0-1 = Multimedia menu-0-1-exec = #apps.open.2 menu-1-0 = Firefox - menu-1-0-exec = firefox & + menu-1-0-exec = firefox menu-1-1 = Chromium - menu-1-1-exec = chromium & + menu-1-1-exec = chromium menu-2-0 = Gimp - menu-2-0-exec = gimp & + menu-2-0-exec = gimp menu-2-1 = Scrot - menu-2-1-exec = scrot & + menu-2-1-exec = scrot diff --git a/include/adapters/pulseaudio.hpp b/include/adapters/pulseaudio.hpp index a5d23426..1ee10b52 100644 --- a/include/adapters/pulseaudio.hpp +++ b/include/adapters/pulseaudio.hpp @@ -2,6 +2,7 @@ #include +#include #include #include "common.hpp" @@ -58,6 +59,11 @@ class pulseaudio { const logger& m_log; + /** + * Has context_state_callback signalled the mainloop during connection. + */ + std::atomic_bool m_state_callback_signal{false}; + // used for temporary callback results int success{0}; pa_cvolume cv{}; diff --git a/include/components/renderer.hpp b/include/components/renderer.hpp index 500c7f08..78a92605 100644 --- a/include/components/renderer.hpp +++ b/include/components/renderer.hpp @@ -74,7 +74,7 @@ class renderer : public renderer_interface, void fill_overline(rgba color, double x, double w); void fill_underline(rgba color, double x, double w); void fill_borders(); - void draw_offset(rgba color, double x, double w); + void draw_offset(const tags::context& ctxt, rgba color, double x, double w); double block_x(alignment a) const; double block_y(alignment a) const; diff --git a/include/ipc/ipc.hpp b/include/ipc/ipc.hpp index 0ba8af1b..7e2e0068 100644 --- a/include/ipc/ipc.hpp +++ b/include/ipc/ipc.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include "common.hpp" @@ -94,6 +92,6 @@ namespace ipc { void receive_data(string buf); void receive_eof(); }; -} // namespace ipc +} // namespace ipc POLYBAR_NS_END diff --git a/src/adapters/pulseaudio.cpp b/src/adapters/pulseaudio.cpp index 1a6a15b8..8404cceb 100644 --- a/src/adapters/pulseaudio.cpp +++ b/src/adapters/pulseaudio.cpp @@ -24,6 +24,8 @@ pulseaudio::pulseaudio(const logger& logger, string&& sink_name, bool max_volume pa_context_set_state_callback(m_context, context_state_callback, this); + m_state_callback_signal = false; + if (pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) { pa_context_disconnect(m_context); pa_context_unref(m_context); @@ -42,7 +44,17 @@ pulseaudio::pulseaudio(const logger& logger, string&& sink_name, bool max_volume m_log.trace("pulseaudio: started mainloop"); - pa_threaded_mainloop_wait(m_mainloop); + /* + * Only wait for signal from the context state callback, if it has not + * already signalled the mainloop since pa_context_connect was called, + * otherwise, we would wait forever. + * + * The while loop ensures spurious wakeups are handled. + */ + while (!m_state_callback_signal) { + pa_threaded_mainloop_wait(m_mainloop); + } + if (pa_context_get_state(m_context) != PA_CONTEXT_READY) { pa_threaded_mainloop_unlock(m_mainloop); pa_threaded_mainloop_stop(m_mainloop); @@ -310,6 +322,7 @@ void pulseaudio::context_state_callback(pa_context* context, void* userdata) { case PA_CONTEXT_READY: case PA_CONTEXT_TERMINATED: case PA_CONTEXT_FAILED: + This->m_state_callback_signal = true; pa_threaded_mainloop_signal(This->m_mainloop, 0); break; diff --git a/src/adapters/script_runner.cpp b/src/adapters/script_runner.cpp index 2f924762..92dcbc11 100644 --- a/src/adapters/script_runner.cpp +++ b/src/adapters/script_runner.cpp @@ -46,7 +46,10 @@ script_runner::interval script_runner::process() { } void script_runner::clear_output() { - set_output(""); + auto changed = set_output(""); + if (changed) { + m_on_update(m_data); + } } void script_runner::stop() { diff --git a/src/components/bar.cpp b/src/components/bar.cpp index 28a85c1e..aaabc391 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -433,10 +433,11 @@ void bar::hide() { try { m_log.info("Hiding bar window"); + m_visible = false; + reconfigure_struts(); m_sig.emit(visibility_change{false}); m_connection.unmap_window_checked(m_opts.window); m_connection.flush(); - m_visible = false; } catch (const exception& err) { m_log.err("Failed to unmap bar window (err=%s", err.what()); } @@ -549,42 +550,46 @@ void bar::reconfigure_pos() { * Reconfigure window strut values */ void bar::reconfigure_struts() { - auto geom = m_connection.get_geometry(m_screen->root()); - int h = m_opts.size.h + m_opts.offset.y; + window win{m_connection, m_opts.window}; + if (m_visible) { + auto geom = m_connection.get_geometry(m_screen->root()); + int h = m_opts.size.h + m_opts.offset.y; - // Apply user-defined margins - if (m_opts.bottom) { - h += m_opts.strut.top; - } else { - h += m_opts.strut.bottom; - } - - h = std::max(h, 0); - - int correction = 0; - - // Only apply correction if any space is requested - if (h > 0) { - /* - * Strut coordinates have to be relative to root window and not any monitor. - * If any monitor is not aligned at the top or bottom - */ + // Apply user-defined margins if (m_opts.bottom) { - /* - * For bottom-algined bars, the correction is the number of pixels between - * the root window's bottom edge and the monitor's bottom edge - */ - correction = geom->height - (m_opts.monitor->y + m_opts.monitor->h); + h += m_opts.strut.top; } else { - // For top-aligned bars, we simply add the monitor's y-position - correction = m_opts.monitor->y; + h += m_opts.strut.bottom; } - correction = std::max(correction, 0); - } + h = std::max(h, 0); - window win{m_connection, m_opts.window}; - win.reconfigure_struts(m_opts.size.w, h + correction, m_opts.pos.x, m_opts.bottom); + int correction = 0; + + // Only apply correction if any space is requested + if (h > 0) { + /* + * Strut coordinates have to be relative to root window and not any monitor. + * If any monitor is not aligned at the top or bottom + */ + if (m_opts.bottom) { + /* + * For bottom-algined bars, the correction is the number of pixels between + * the root window's bottom edge and the monitor's bottom edge + */ + correction = geom->height - (m_opts.monitor->y + m_opts.monitor->h); + } else { + // For top-aligned bars, we simply add the monitor's y-position + correction = m_opts.monitor->y; + } + + correction = std::max(correction, 0); + } + win.reconfigure_struts(m_opts.size.w, h + correction, m_opts.pos.x, m_opts.bottom); + } else { + // Set struts to 0 for invisible bars + win.reconfigure_struts(0, 0, 0, m_opts.bottom); + } } /** @@ -627,6 +632,8 @@ void bar::broadcast_visibility() { } void bar::map_window() { + m_visible = true; + /** * First reconfigures the window so that WMs that discard some information * when unmapping have the correct window properties (geometry etc). @@ -641,8 +648,6 @@ void bar::map_window() { * mapping. Additionally updating the window position after mapping seems to fix that. */ reconfigure_pos(); - - m_visible = true; } void bar::trigger_click(mousebtn btn, int pos) { diff --git a/src/components/controller.cpp b/src/components/controller.cpp index ec856766..77681e1c 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -1,7 +1,5 @@ #include "components/controller.hpp" -#include - #include #include diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index 4e1b4504..474cf389 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -729,8 +729,12 @@ void renderer::render_text(const tags::context& ctxt, const string&& contents) { } } -void renderer::draw_offset(rgba color, double x, double w) { - if (w > 0 && color != m_bar.background) { +void renderer::draw_offset(const tags::context& ctxt, rgba color, double x, double w) { + if (w <= 0) { + return; + } + + if (color != m_bar.background) { m_log.trace_x("renderer: offset(x=%f, w=%f)", x, w); m_context->save(); *m_context << m_comp_bg; @@ -740,6 +744,14 @@ void renderer::draw_offset(rgba color, double x, double w) { m_context->fill(); m_context->restore(); } + + if (ctxt.has_underline()) { + fill_underline(ctxt.get_ul(), x, w); + } + + if (ctxt.has_overline()) { + fill_overline(ctxt.get_ol(), x, w); + } } void renderer::render_offset(const tags::context& ctxt, const extent_val offset) { @@ -748,7 +760,7 @@ void renderer::render_offset(const tags::context& ctxt, const extent_val offset) int offset_width = units_utils::extent_to_pixel(offset, m_bar.dpi_x); rgba bg = ctxt.get_bg(); - draw_offset(bg, m_blocks[m_align].x, offset_width); + draw_offset(ctxt, bg, m_blocks[m_align].x, offset_width); increase_x(offset_width); } diff --git a/src/ipc/util.cpp b/src/ipc/util.cpp index b93cd36e..0a1d2315 100644 --- a/src/ipc/util.cpp +++ b/src/ipc/util.cpp @@ -1,6 +1,7 @@ #include "ipc/util.hpp" #include +#include #include "errors.hpp" #include "utils/env.hpp" @@ -12,8 +13,14 @@ POLYBAR_NS namespace ipc { static constexpr auto SUFFIX = ".sock"; + static constexpr auto XDG_RUNTIME_DIR = "XDG_RUNTIME_DIR"; string get_runtime_path() { + if (env_util::has(XDG_RUNTIME_DIR)) { + return env_util::get("XDG_RUNTIME_DIR") + "/polybar"; + } else { + return "/tmp/polybar-" + to_string(getuid()); + } return env_util::get("XDG_RUNTIME_DIR", "/tmp") + "/polybar"; } @@ -59,6 +66,6 @@ namespace ipc { return -1; } } -} // namespace ipc +} // namespace ipc POLYBAR_NS_END diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 5d6dcdca..ea7aa13e 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -199,7 +199,7 @@ namespace modules { if (chrono::duration_cast(now - m_lastpoll) > m_interval) { m_lastpoll = now; m_log.info("%s: Polling values (inotify fallback)", name()); - read(*m_capacity_reader); + on_event(nullptr); } } diff --git a/src/modules/xworkspaces.cpp b/src/modules/xworkspaces.cpp index 9fb04dec..f1123238 100644 --- a/src/modules/xworkspaces.cpp +++ b/src/modules/xworkspaces.cpp @@ -108,7 +108,8 @@ namespace modules { if (evt->atom == m_ewmh->_NET_CLIENT_LIST || evt->atom == m_ewmh->_NET_WM_DESKTOP) { rebuild_clientlist(); rebuild_desktop_states(); - } else if (evt->atom == m_ewmh->_NET_DESKTOP_NAMES || evt->atom == m_ewmh->_NET_NUMBER_OF_DESKTOPS) { + } else if (evt->atom == m_ewmh->_NET_DESKTOP_NAMES || evt->atom == m_ewmh->_NET_NUMBER_OF_DESKTOPS || + evt->atom == m_ewmh->_NET_DESKTOP_VIEWPORT) { m_desktop_names = get_desktop_names(); rebuild_desktops(); rebuild_clientlist(); diff --git a/src/x11/window.cpp b/src/x11/window.cpp index 0c31505a..601cc003 100644 --- a/src/x11/window.cpp +++ b/src/x11/window.cpp @@ -57,14 +57,16 @@ window window::reconfigure_pos(short int x, short int y) { window window::reconfigure_struts(uint32_t w, uint32_t strut, uint32_t x, bool bottom) { std::array values{}; + uint32_t end_x = std::max(0, x + w - 1); + if (bottom) { values[to_integral(strut::BOTTOM)] = strut; values[to_integral(strut::BOTTOM_START_X)] = x; - values[to_integral(strut::BOTTOM_END_X)] = x + w - 1; + values[to_integral(strut::BOTTOM_END_X)] = end_x; } else { values[to_integral(strut::TOP)] = strut; values[to_integral(strut::TOP_START_X)] = x; - values[to_integral(strut::TOP_END_X)] = x + w - 1; + values[to_integral(strut::TOP_END_X)] = end_x; } connection().change_property_checked( diff --git a/version.txt b/version.txt index dded6f39..da99c325 100644 --- a/version.txt +++ b/version.txt @@ -1,4 +1,4 @@ # Polybar version information # Update this on every release # This is used to create the version string if a git repo is not available -3.6.2 +3.6.3