From 3de914abcab18426ed1b6af26fd7bbbbef2c039d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benno=20F=C3=BCnfst=C3=BCck?= Date: Tue, 23 May 2017 21:32:34 +0200 Subject: [PATCH] feat(render): support pseudo-transparency This adds pseudo-transparency for the background of the bar and the background of the systray. --- include/cairo/font.hpp | 2 +- include/components/controller.hpp | 4 +- include/components/ipc.hpp | 2 +- include/components/renderer.hpp | 4 +- include/events/signal.hpp | 3 + include/events/signal_fwd.hpp | 1 + include/x11/background_manager.hpp | 52 +++++++++++ include/x11/connection.hpp | 1 + include/x11/tray_manager.hpp | 15 +-- src/components/controller.cpp | 6 ++ src/components/parser.cpp | 2 +- src/components/renderer.cpp | 32 +++++-- src/x11/background_manager.cpp | 143 +++++++++++++++++++++++++++++ src/x11/connection.cpp | 13 +++ src/x11/tray_manager.cpp | 121 +++++++++++------------- 15 files changed, 315 insertions(+), 86 deletions(-) create mode 100644 include/x11/background_manager.hpp create mode 100644 src/x11/background_manager.cpp diff --git a/include/cairo/font.hpp b/include/cairo/font.hpp index 71f7e4f1..1a904e95 100644 --- a/include/cairo/font.hpp +++ b/include/cairo/font.hpp @@ -243,7 +243,7 @@ namespace cairo { /** * Match and create font from given fontconfig pattern */ - decltype(auto) make_font(cairo_t* cairo, string&& fontname, double offset, double dpi_x, double dpi_y) { + inline decltype(auto) make_font(cairo_t* cairo, string&& fontname, double offset, double dpi_x, double dpi_y) { static bool fc_init{false}; if (!fc_init && !(fc_init = FcInit())) { throw application_error("Could not load fontconfig"); diff --git a/include/components/controller.hpp b/include/components/controller.hpp index 3b25b099..981f3380 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -35,7 +35,8 @@ using modulemap_t = std::map>; class controller : public signal_receiver { + signals::ipc::command, signals::ipc::hook, signals::ui::ready, signals::ui::button_press, + signals::ui::update_background> { public: using make_type = unique_ptr; static make_type make(unique_ptr&& ipc, unique_ptr&& config_watch); @@ -65,6 +66,7 @@ class controller : public signal_receiver m_fd{}; + unique_ptr m_fd; }; POLYBAR_NS_END diff --git a/include/components/renderer.hpp b/include/components/renderer.hpp index c4c14fab..aff9d714 100644 --- a/include/components/renderer.hpp +++ b/include/components/renderer.hpp @@ -17,6 +17,7 @@ POLYBAR_NS class connection; class config; class logger; +class background_manager; // }}} using std::map; @@ -39,7 +40,7 @@ class renderer static make_type make(const bar_settings& bar); explicit renderer( - connection& conn, signal_emitter& sig, const config&, const logger& logger, const bar_settings& bar); + connection& conn, signal_emitter& sig, const config&, const logger& logger, const bar_settings& bar, background_manager& background_manager); ~renderer(); xcb_window_t window() const; @@ -95,6 +96,7 @@ class renderer const config& m_conf; const logger& m_log; const bar_settings& m_bar; + background_manager& m_background; int m_depth{32}; xcb_window_t m_window; diff --git a/include/events/signal.hpp b/include/events/signal.hpp index 986a6125..40807b4a 100644 --- a/include/events/signal.hpp +++ b/include/events/signal.hpp @@ -120,6 +120,9 @@ namespace signals { struct request_snapshot : public detail::value_signal { using base_type::base_type; }; + struct update_background : public detail::base_signal { + using base_type::base_type; + }; } namespace ui_tray { diff --git a/include/events/signal_fwd.hpp b/include/events/signal_fwd.hpp index f7da2f89..dac45782 100644 --- a/include/events/signal_fwd.hpp +++ b/include/events/signal_fwd.hpp @@ -38,6 +38,7 @@ namespace signals { struct shade_window; struct unshade_window; struct request_snapshot; + struct update_background; } namespace ui_tray { struct mapped_clients; diff --git a/include/x11/background_manager.hpp b/include/x11/background_manager.hpp new file mode 100644 index 00000000..3ebea680 --- /dev/null +++ b/include/x11/background_manager.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "common.hpp" +#include "events/signal_fwd.hpp" +#include "x11/extensions/fwd.hpp" +#include "x11/types.hpp" + +POLYBAR_NS + +class logger; + +namespace cairo { + class surface; + class xcb_surface; +} + +class background_manager : public xpp::event::sink { + public: + using make_type = background_manager&; + static make_type make(); + + explicit background_manager(connection& conn, signal_emitter& sig, const logger& log); + ~background_manager(); + + void activate(xcb_window_t window, xcb_rectangle_t rect); + void deactivate(); + + cairo::surface* get_surface() const; + + void handle(const evt::property_notify& evt); + private: + connection& m_connection; + signal_emitter& m_sig; + const logger& m_log; + xcb_window_t m_window; + + xcb_rectangle_t m_rect{0, 0, 0U, 0U}; + + xcb_visualtype_t* m_visual = nullptr; + xcb_gcontext_t m_gcontext = XCB_NONE; + xcb_pixmap_t m_pixmap = XCB_NONE; + unique_ptr m_surface; + + bool m_attached = false; + + void allocate_resources(); + void free_resources(); + void fetch_root_pixmap(); + +}; + +POLYBAR_NS_END diff --git a/include/x11/connection.hpp b/include/x11/connection.hpp index 71ad3032..8931ac83 100644 --- a/include/x11/connection.hpp +++ b/include/x11/connection.hpp @@ -126,6 +126,7 @@ class connection : public detail::connection_base +#include "cairo/context.hpp" +#include "cairo/surface.hpp" #include "common.hpp" #include "components/logger.hpp" #include "components/types.hpp" @@ -32,6 +34,7 @@ using namespace std::chrono_literals; // fwd declarations class connection; struct xembed_data; +class background_manager; struct tray_settings { tray_settings() = default; @@ -61,12 +64,12 @@ class tray_manager : public xpp::event::sink, - public signal_receiver { + public signal_receiver { public: using make_type = unique_ptr; static make_type make(); - explicit tray_manager(connection& conn, signal_emitter& emitter, const logger& logger); + explicit tray_manager(connection& conn, signal_emitter& emitter, const logger& logger, background_manager& back); ~tray_manager(); @@ -127,21 +130,21 @@ class tray_manager bool on(const signals::ui::visibility_change& evt); bool on(const signals::ui::dim_window& evt); + bool on(const signals::ui::update_background& evt); private: connection& m_connection; signal_emitter& m_sig; const logger& m_log; + background_manager& m_background; vector> m_clients; tray_settings m_opts{}; xcb_gcontext_t m_gc{0}; xcb_pixmap_t m_pixmap{0}; - - xcb_pixmap_t m_rootpixmap{0}; - int m_rootpixmap_depth{0}; - xcb_rectangle_t m_rootpixmap_geom{0, 0, 0U, 0U}; + unique_ptr m_surface; + unique_ptr m_context; unsigned int m_prevwidth{0U}; unsigned int m_prevheight{0U}; diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 5aa5c3a0..e7b47e80 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -686,4 +686,10 @@ bool controller::on(const signals::ipc::hook& evt) { return true; } +bool controller::on(const signals::ui::update_background&) { + enqueue(make_update_evt(true)); + + return false; +} + POLYBAR_NS_END diff --git a/src/components/parser.cpp b/src/components/parser.cpp index c5231928..48b9cb12 100644 --- a/src/components/parser.cpp +++ b/src/components/parser.cpp @@ -77,7 +77,7 @@ void parser::codeblock(string&& data, const bar_settings& bar) { switch (tag) { case 'B': - m_sig.emit(change_background{parse_color(value, bar.background)}); + m_sig.emit(change_background{parse_color(value, 0x0)}); break; case 'F': diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index 2c7840e5..f51546fc 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -7,6 +7,7 @@ #include "utils/file.hpp" #include "utils/math.hpp" #include "x11/atoms.hpp" +#include "x11/background_manager.hpp" #include "x11/connection.hpp" #include "x11/extensions/all.hpp" #include "x11/winspec.hpp" @@ -25,7 +26,8 @@ renderer::make_type renderer::make(const bar_settings& bar) { signal_emitter::make(), config::make(), logger::make(), - forward(bar)); + forward(bar), + background_manager::make()); // clang-format on } @@ -33,13 +35,15 @@ renderer::make_type renderer::make(const bar_settings& bar) { * Construct renderer instance */ renderer::renderer( - connection& conn, signal_emitter& sig, const config& conf, const logger& logger, const bar_settings& bar) + connection& conn, signal_emitter& sig, const config& conf, const logger& logger, const bar_settings& bar, background_manager& background) : m_connection(conn) , m_sig(sig) , m_conf(conf) , m_log(logger) , m_bar(forward(bar)) + , m_background(background) , m_rect(m_bar.inner_area()) { + m_sig.attach(this); m_log.trace("renderer: Get TrueColor visual"); { @@ -160,6 +164,9 @@ renderer::renderer( m_log.info("Loaded font \"%s\" (name=%s, offset=%i, file=%s)", pattern, font->name(), offset, font->file()); *m_context << move(font); } + + m_log.trace("Activate root background manager"); + m_background.activate(m_window, m_bar.inner_area(true)); } m_comp_bg = m_conf.get("settings", "compositing-background", m_comp_bg); @@ -205,7 +212,7 @@ void renderer::begin(xcb_rectangle_t rect) { m_align = alignment::NONE; // Reset colors - m_bg = m_bar.background; + m_bg = 0x0; m_fg = m_bar.foreground; m_ul = m_bar.underline.color; m_ol = m_bar.overline.color; @@ -214,6 +221,11 @@ void renderer::begin(xcb_rectangle_t rect) { m_context->save(); m_context->clear(); + // Draw the background on the new layer to make up for + // the areas not covered by the alignment blocks + fill_background(); + + // Create corner mask if (m_bar.radius && m_cornermask == nullptr) { m_context->save(); @@ -261,10 +273,6 @@ void renderer::end() { // so that it can be masked with the corner pattern m_context->push(); - // Draw the background on the new layer to make up for - // the areas not covered by the alignment blocks - fill_background(); - for (auto&& b : m_blocks) { flush(b.first); } @@ -495,6 +503,14 @@ void renderer::fill_background() { m_context->save(); *m_context << m_comp_bg; + auto root_bg = m_background.get_surface(); + if(root_bg != nullptr) { + m_log.trace_x("renderer: root background"); + *m_context << *root_bg; + m_context->paint(); + *m_context << CAIRO_OPERATOR_OVER; + } + if (!m_bar.background_steps.empty()) { m_log.trace_x("renderer: gradient background (steps=%lu)", m_bar.background_steps.size()); *m_context << cairo::linear_gradient{0.0, 0.0 + m_rect.y, 0.0, 0.0 + m_rect.height, m_bar.background_steps}; @@ -718,8 +734,6 @@ bool renderer::on(const signals::parser::change_alignment& evt) { m_blocks[m_align].y = 0.0; m_context->push(); m_log.trace_x("renderer: push(%i)", static_cast(m_align)); - - fill_background(); } return true; } diff --git a/src/x11/background_manager.cpp b/src/x11/background_manager.cpp new file mode 100644 index 00000000..491b1a10 --- /dev/null +++ b/src/x11/background_manager.cpp @@ -0,0 +1,143 @@ +#include "cairo/surface.hpp" +#include "events/signal.hpp" +#include "components/logger.hpp" +#include "x11/atoms.hpp" +#include "x11/connection.hpp" +#include "x11/background_manager.hpp" +#include "utils/factory.hpp" +#include "utils/math.hpp" + +POLYBAR_NS + +background_manager& background_manager::make() { + return *factory_util::singleton(connection::make(), signal_emitter::make(), logger::make()); +} + +background_manager::background_manager( + connection& conn, signal_emitter& sig, const logger& log) + : m_connection(conn) + , m_sig(sig) + , m_log(log) { +} + +background_manager::~background_manager() { + free_resources(); +} + +cairo::surface* background_manager::get_surface() const { + return m_surface.get(); +} + +void background_manager::activate(xcb_window_t window, xcb_rectangle_t rect) { + // ensure that we start from a clean state + // + // the size of the pixmap may need to be changed, etc. + // so the easiest way is to just re-allocate everything. + // it may be possible to be more clever here, but activate is + // not supposed to be called often so this shouldn't be a problem. + free_resources(); + + // make sure that we receive a notification when the background changes + if(!m_attached) { + m_connection.ensure_event_mask(m_connection.root(), XCB_EVENT_MASK_PROPERTY_CHANGE); + m_connection.flush(); + m_connection.attach_sink(this, SINK_PRIORITY_SCREEN); + } + + m_window = window; + m_rect = rect; + fetch_root_pixmap(); +} + +void background_manager::deactivate() { + free_resources(); +} + + +void background_manager::allocate_resources() { + if(!m_visual) { + m_log.trace("background_manager: Finding root visual"); + m_visual = m_connection.visual_type_for_id(m_connection.screen(), m_connection.screen()->root_visual); + m_log.trace("background_manager: Got root visual with depth %d", m_connection.screen()->root_depth); + } + + if(m_pixmap == XCB_NONE) { + m_log.trace("background_manager: Allocating pixmap"); + m_pixmap = m_connection.generate_id(); + m_connection.create_pixmap(m_connection.screen()->root_depth, m_pixmap, m_window, m_rect.width, m_rect.height); + } + + if(m_gcontext == XCB_NONE) { + m_log.trace("background_manager: Allocating graphics context"); + unsigned int mask = XCB_GC_GRAPHICS_EXPOSURES; + unsigned int value_list[1] = {0}; + m_gcontext = m_connection.generate_id(); + m_connection.create_gc(m_gcontext, m_pixmap, mask, value_list); + } + + if(!m_surface) { + m_log.trace("background_manager: Allocating cairo surface"); + m_surface = make_unique(m_connection, m_pixmap, m_visual, m_rect.width, m_rect.height); + } + + if(m_attached) { + m_connection.detach_sink(this, SINK_PRIORITY_SCREEN); + m_attached = false; + } + +} + +void background_manager::free_resources() { + m_surface.release(); + m_visual = nullptr; + + if(m_pixmap != XCB_NONE) { + m_connection.free_pixmap(m_pixmap); + m_pixmap = XCB_NONE; + } + + if(m_gcontext != XCB_NONE) { + m_connection.free_gc(m_gcontext); + m_gcontext = XCB_NONE; + } +} + +void background_manager::fetch_root_pixmap() { + allocate_resources(); + m_log.trace("background_manager: Fetching pixmap"); + + int pixmap_depth; + xcb_pixmap_t pixmap; + xcb_rectangle_t pixmap_geom; + + if (!m_connection.root_pixmap(&pixmap, &pixmap_depth, &pixmap_geom)) { + free_resources(); + return m_log.err("background_manager: Failed to get root pixmap for background (realloc=%i)", realloc); + }; + + auto src_x = math_util::cap(m_rect.x, pixmap_geom.x, int16_t(pixmap_geom.x + pixmap_geom.width)); + auto src_y = math_util::cap(m_rect.y, pixmap_geom.y, int16_t(pixmap_geom.y + pixmap_geom.height)); + auto h = math_util::min(m_rect.height, pixmap_geom.height); + auto w = math_util::min(m_rect.width, pixmap_geom.width); + + m_log.trace("background_manager: Copying from root pixmap (%d) %dx%d+%dx%d", pixmap, w, h, src_x, src_y); + try { + m_connection.copy_area_checked(pixmap, m_pixmap, m_gcontext, src_x, src_y, 0, 0, w, h); + } catch (const exception& err) { + m_log.err("background_manager: Failed to copy slice of root pixmap (%s)", err.what()); + free_resources(); + return; + } +} + +void background_manager::handle(const evt::property_notify& evt) { + // if region that we should observe is empty, don't do anything + if(m_rect.width == 0 || m_rect.height == 0) return; + + if (evt->atom == _XROOTMAP_ID || evt->atom == _XSETROOT_ID || evt->atom == ESETROOT_PMAP_ID) { + fetch_root_pixmap(); + m_sig.emit(signals::ui::update_background()); + } +} + +POLYBAR_NS_END diff --git a/src/x11/connection.cpp b/src/x11/connection.cpp index 4174eed1..fc4d57fc 100644 --- a/src/x11/connection.cpp +++ b/src/x11/connection.cpp @@ -165,6 +165,19 @@ xcb_visualtype_t* connection::visual_type(xcb_screen_t* screen, int match_depth) return nullptr; } + +xcb_visualtype_t* connection::visual_type_for_id(xcb_screen_t* screen, xcb_visualid_t visual_id) { + xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen); + if (depth_iter.data) { + for (; depth_iter.rem; xcb_depth_next(&depth_iter)) { + for (auto it = xcb_depth_visuals_iterator(depth_iter.data); it.rem; xcb_visualtype_next(&it)) { + if(it.data->visual_id == visual_id) return it.data; + } + } + } + return nullptr; +} + /** * Query root window pixmap */ diff --git a/src/x11/tray_manager.cpp b/src/x11/tray_manager.cpp index c297aeff..89059883 100644 --- a/src/x11/tray_manager.cpp +++ b/src/x11/tray_manager.cpp @@ -1,6 +1,8 @@ #include #include +#include "cairo/context.hpp" +#include "cairo/surface.hpp" #include "components/config.hpp" #include "errors.hpp" #include "events/signal.hpp" @@ -9,6 +11,7 @@ #include "utils/math.hpp" #include "utils/memory.hpp" #include "utils/process.hpp" +#include "x11/background_manager.hpp" #include "x11/ewmh.hpp" #include "x11/icccm.hpp" #include "x11/tray_manager.hpp" @@ -37,11 +40,11 @@ POLYBAR_NS * Create instance */ tray_manager::make_type tray_manager::make() { - return factory_util::unique(connection::make(), signal_emitter::make(), logger::make()); + return factory_util::unique(connection::make(), signal_emitter::make(), logger::make(), background_manager::make()); } -tray_manager::tray_manager(connection& conn, signal_emitter& emitter, const logger& logger) - : m_connection(conn), m_sig(emitter), m_log(logger) { +tray_manager::tray_manager(connection& conn, signal_emitter& emitter, const logger& logger, background_manager& back) + : m_connection(conn), m_sig(emitter), m_log(logger), m_background(back) { m_connection.attach_sink(this, SINK_PRIORITY_TRAY); } @@ -131,9 +134,9 @@ void tray_manager::setup(const bar_settings& bar_opts) { m_opts.background = bar_opts.background; } - if (color_util::alpha_channel(m_opts.background) == 0) { + if (color_util::alpha_channel(m_opts.background) != 1) { m_opts.transparent = true; - m_opts.background = 0; + //m_opts.background = 0; } } @@ -257,6 +260,8 @@ void tray_manager::deactivate(bool clear_selection) { m_log.trace("tray: Destroy window"); m_connection.destroy_window(m_tray); } + m_context.release(); + m_surface.release(); if (m_pixmap) { m_connection.free_pixmap(m_pixmap); } @@ -267,7 +272,6 @@ void tray_manager::deactivate(bool clear_selection) { m_tray = 0; m_pixmap = 0; m_gc = 0; - m_rootpixmap = 0; m_prevwidth = 0; m_prevheight = 0; m_opts.configured_x = 0; @@ -384,75 +388,30 @@ void tray_manager::reconfigure_clients() { void tray_manager::reconfigure_bg(bool realloc) { if (!m_opts.transparent || m_clients.empty() || !m_mapped) { return; - } else if (!m_rootpixmap) { - realloc = true; - } - - auto w = calculate_w(); - auto h = calculate_h(); - - if ((!w || (w == m_prevwidth && h == m_prevheight)) && !realloc) { - return; - } + }; m_log.trace("tray: Reconfigure bg (realloc=%i)", realloc); - if (realloc && !m_connection.root_pixmap(&m_rootpixmap, &m_rootpixmap_depth, &m_rootpixmap_geom)) { - return m_log.err("Failed to get root pixmap for tray background (realloc=%i)", realloc); - } else if (realloc) { - // clang-format off - m_log.info("Tray root pixmap (rootpmap=%s, geom=%dx%d+%d+%d, tray=%s, pmap=%s, gc=%s)", - m_connection.id(m_rootpixmap), - m_rootpixmap_geom.width, - m_rootpixmap_geom.height, - m_rootpixmap_geom.x, - m_rootpixmap_geom.y, - m_connection.id(m_tray), - m_connection.id(m_pixmap), - m_connection.id(m_gc)); - // clang-format on - } - - m_prevwidth = w; - m_prevheight = h; + auto w = calculate_w(); auto x = calculate_x(w); auto y = calculate_y(); - auto px = math_util::max(0, m_rootpixmap_geom.x + x); - auto py = math_util::max(0, m_rootpixmap_geom.y + y); - // Make sure we don't try to copy void content - if (px + w > m_rootpixmap_geom.width) { - w -= px + w - m_rootpixmap_geom.width; - } - if (py + h > m_rootpixmap_geom.height) { - h -= py + h - m_rootpixmap_geom.height; + if(!m_context) { + return m_log.err("tray: no context for drawing the background"); } - if (realloc) { - vector image_data; - unsigned char image_depth; - - try { - auto image_reply = m_connection.get_image(XCB_IMAGE_FORMAT_Z_PIXMAP, m_rootpixmap, px, py, w, h, XCB_COPY_PLANE); - image_depth = image_reply->depth; - std::back_insert_iterator back_it(image_data); - std::copy(image_reply.data().begin(), image_reply.data().end(), back_it); - } catch (const exception& err) { - m_log.err("Failed to get slice of root pixmap (%s)", err.what()); - return; - } - - try { - m_connection.put_image_checked( - XCB_IMAGE_FORMAT_Z_PIXMAP, m_pixmap, m_gc, w, h, 0, 0, 0, image_depth, image_data.size(), image_data.data()); - } catch (const exception& err) { - m_log.err("Failed to store slice of root pixmap (%s)", err.what()); - return; - } + cairo::surface* surface = m_background.get_surface(); + if(!surface) { + return m_log.err("tray: no root surface"); } - m_connection.copy_area_checked(m_rootpixmap, m_pixmap, m_gc, px, py, 0, 0, w, h); + m_context->clear(); + *m_context << CAIRO_OPERATOR_SOURCE << *m_surface; + cairo_set_source_surface(*m_context, *surface, -x, -y); + m_context->paint(); + *m_context << CAIRO_OPERATOR_OVER << m_opts.background; + m_context->paint(); } /** @@ -470,11 +429,13 @@ void tray_manager::refresh_window() { auto width = calculate_w(); auto height = calculate_h(); - if (m_opts.transparent && !m_rootpixmap) { + if (m_opts.transparent && !m_context) { xcb_rectangle_t rect{0, 0, static_cast(width), static_cast(height)}; m_connection.poly_fill_rectangle(m_pixmap, m_gc, 1, &rect); } + if(m_surface) m_surface->flush(); + m_connection.clear_area(0, m_tray, 0, 0, width, height); for (auto&& client : m_clients) { @@ -546,7 +507,7 @@ void tray_manager::create_bg(bool realloc) { if (!m_opts.transparent) { return; } - if (!realloc && m_pixmap && m_gc && m_rootpixmap) { + if (!realloc && m_pixmap && m_gc && m_surface && m_context) { return; } if (realloc && m_pixmap) { @@ -558,6 +519,13 @@ void tray_manager::create_bg(bool realloc) { m_gc = 0; } + if(realloc && m_surface) { + m_surface.release(); + } + if(realloc && m_context) { + m_context.release(); + } + auto w = m_opts.width_max; auto h = calculate_h(); @@ -584,6 +552,21 @@ void tray_manager::create_bg(bool realloc) { } } + if(!m_surface) { + xcb_visualtype_t* visual = m_connection.visual_type_for_id(m_connection.screen(), m_connection.screen()->root_visual); + if(!visual) { + return m_log.err("Failed to get root visual for tray background"); + } + m_surface = make_unique(m_connection, m_pixmap, visual, w, h); + } + + if(!m_context) { + m_context = make_unique(*m_surface, m_log); + m_context->clear(); + *m_context << CAIRO_OPERATOR_SOURCE << m_opts.background; + m_context->paint(); + } + try { m_connection.change_window_attributes_checked(m_tray, XCB_CW_BACK_PIXMAP, &m_pixmap); } catch (const exception& err) { @@ -1155,4 +1138,10 @@ bool tray_manager::on(const signals::ui::dim_window& evt) { return false; } +bool tray_manager::on(const signals::ui::update_background&) { + redraw_window(true); + + return false; +} + POLYBAR_NS_END