diff --git a/include/utils/color.hpp b/include/utils/color.hpp index 3961876f..491d48ee 100644 --- a/include/utils/color.hpp +++ b/include/utils/color.hpp @@ -37,6 +37,7 @@ class rgba { uint8_t blue_i() const; bool has_color() const; + bool is_transparent() const; rgba apply_alpha_to(rgba other) const; rgba try_apply_alpha_to(rgba other) const; diff --git a/include/x11/tray_client.hpp b/include/x11/tray_client.hpp index 2d0dfb9a..97e98924 100644 --- a/include/x11/tray_client.hpp +++ b/include/x11/tray_client.hpp @@ -25,7 +25,7 @@ namespace tray { class client : public non_copyable_mixin, public non_movable_mixin { public: explicit client( - const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, uint32_t desired_background); + const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, rgba desired_background); ~client(); string name() const; @@ -124,9 +124,10 @@ class client : public non_copyable_mixin, public non_movable_mixin { size m_size; position m_pos{0, 0}; - rgba m_desired_background; + const rgba m_desired_background; + const bool m_transparent{m_desired_background.is_transparent()}; background_manager& m_background_manager; - shared_ptr m_bg_slice; + shared_ptr m_bg_slice{nullptr}; unique_ptr m_context; unique_ptr m_surface; }; diff --git a/src/utils/color.cpp b/src/utils/color.cpp index bfff83dc..59fa59ae 100644 --- a/src/utils/color.cpp +++ b/src/utils/color.cpp @@ -154,6 +154,10 @@ bool rgba::has_color() const { return m_type != type::NONE; } +bool rgba::is_transparent() const { + return alpha_i() != 0xFF; +} + /** * Applies the alpha channel of this color to the given color. */ diff --git a/src/x11/tray_client.cpp b/src/x11/tray_client.cpp index 18438eba..3de60b25 100644 --- a/src/x11/tray_client.cpp +++ b/src/x11/tray_client.cpp @@ -33,7 +33,7 @@ namespace tray { * 3. Use background color */ client::client( - const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, uint32_t desired_background) + const logger& log, connection& conn, xcb_window_t parent, xcb_window_t win, size s, rgba desired_background) : m_log(log) , m_connection(conn) , m_name(ewmh_util::get_wm_name(win)) @@ -350,17 +350,16 @@ void client::configure_notify() const { void client::update_bg() const { m_log.trace("%s: Update background", name()); - // Composite background slice with background color. - m_context->clear(); - auto root_bg = m_bg_slice->get_surface(); - if (root_bg != nullptr) { - // TODO the compositing doesn't have to be done if the background color is not transparent. - // In that case, the bg slice can be completely skipped, we shouldn't event observe the background - *m_context << CAIRO_OPERATOR_SOURCE << *root_bg; - m_context->paint(); - *m_context << CAIRO_OPERATOR_OVER; + // Composite background slice with background color. + if (m_bg_slice) { + auto root_bg = m_bg_slice->get_surface(); + if (root_bg != nullptr) { + *m_context << CAIRO_OPERATOR_SOURCE << *root_bg; + m_context->paint(); + *m_context << CAIRO_OPERATOR_OVER; + } } *m_context << m_desired_background; m_context->paint(); @@ -372,6 +371,11 @@ void client::update_bg() const { } void client::observe_background() { + // Opaque backgrounds don't require pseudo-transparency + if (!m_transparent) { + return; + } + xcb_rectangle_t rect{0, 0, static_cast(m_size.w), static_cast(m_size.h)}; m_bg_slice = m_background_manager.observe(rect, embedder()); diff --git a/src/x11/tray_manager.cpp b/src/x11/tray_manager.cpp index b7b0dbf0..d271a0dd 100644 --- a/src/x11/tray_manager.cpp +++ b/src/x11/tray_manager.cpp @@ -122,6 +122,7 @@ void manager::activate() { try { set_tray_colors(); set_tray_orientation(); + // TODO // set_tray_visual(); } catch (const exception& err) { m_log.err(err.what()); @@ -353,7 +354,7 @@ void manager::set_tray_orientation() { XCB_ATOM_CARDINAL, 32, 1, &orientation); } -// TODO remove +// TODO remove, we should probably not set a visual at all (or only a 24-bit one) void manager::set_tray_visual() { // TODO use bar visual const uint32_t visualid = m_connection.visual_type(XCB_VISUAL_CLASS_TRUE_COLOR, 32)->visual_id; @@ -436,7 +437,7 @@ void manager::process_docking_request(xcb_window_t win) { try { auto cl = make_unique( - m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size, m_bar_opts.background.value()); + m_log, m_connection, m_opts.selection_owner, win, m_opts.client_size, m_opts.background); try { cl->query_xembed(); diff --git a/tests/unit_tests/utils/color.cpp b/tests/unit_tests/utils/color.cpp index 7b62969c..4f693cbc 100644 --- a/tests/unit_tests/utils/color.cpp +++ b/tests/unit_tests/utils/color.cpp @@ -88,6 +88,19 @@ TEST(Rgba, hasColor) { EXPECT_FALSE(v.has_color()); } +TEST(Rgba, isTransparent) { + rgba v(0x1243); + EXPECT_FALSE(v.is_transparent()); + + v = rgba(0xff1243); + + EXPECT_FALSE(v.is_transparent()); + + v = rgba(0xfe1243); + + EXPECT_TRUE(v.is_transparent()); +} + TEST(Rgba, channel) { rgba v{0xCC123456}; EXPECT_EQ(0xCC, v.alpha_i());