fix(render): support stacked bars

We now take the bar position that the window manager gives us instead of trying
to calculate it ourselves. This is more correct when multiple bars are attached
to the same edge, as the window manager may move some of them in that
case (assuming override redirect is not enabled)
This commit is contained in:
Benno Fünfstück 2017-08-31 18:26:38 +02:00 committed by Patrick Ziegler
parent eb742e228b
commit 51d58e7518
7 changed files with 48 additions and 19 deletions

View File

@ -51,7 +51,7 @@ inline double geom_format_to_pixels(std::string str, double max) {
}
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message>,
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message, evt::configure_notify>,
public signal_receiver<SIGN_PRIORITY_BAR, signals::eventqueue::start, signals::ui::tick,
signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window
#if WITH_XCURSOR
@ -89,6 +89,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
void handle(const evt::button_press& evt);
void handle(const evt::expose& evt);
void handle(const evt::property_notify& evt);
void handle(const evt::configure_notify& evt);
bool on(const signals::eventqueue::start&);
bool on(const signals::ui::unshade_window&);

View File

@ -123,6 +123,9 @@ namespace signals {
struct update_background : public detail::base_signal<update_background> {
using base_type::base_type;
};
struct update_geometry : public detail::base_signal<update_geometry> {
using base_type::base_type;
};
}
namespace ui_tray {

View File

@ -39,6 +39,7 @@ namespace signals {
struct unshade_window;
struct request_snapshot;
struct update_background;
struct update_geometry;
}
namespace ui_tray {
struct mapped_clients;

View File

@ -2,6 +2,8 @@
#include "common.hpp"
#include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp"
#include "events/types.hpp"
#include "x11/extensions/fwd.hpp"
#include "x11/types.hpp"
@ -14,7 +16,9 @@ namespace cairo {
class xcb_surface;
}
class background_manager : public xpp::event::sink<evt::property_notify> {
class background_manager : public signal_receiver<SIGN_PRIORITY_SCREEN, signals::ui::update_geometry>,
public xpp::event::sink<evt::property_notify>
{
public:
using make_type = background_manager&;
static make_type make();
@ -28,6 +32,7 @@ class background_manager : public xpp::event::sink<evt::property_notify> {
cairo::surface* get_surface() const;
void handle(const evt::property_notify& evt);
bool on(const signals::ui::update_geometry&);
private:
connection& m_connection;
signal_emitter& m_sig;

View File

@ -761,9 +761,6 @@ void bar::handle(const evt::expose& evt) {
* state of the tray container even though the tray
* window restacking failed. Used as a fallback for
* tedious WM's, like i3.
*
* - Track the root pixmap atom to update the
* pseudo-transparent background when it changes
*/
void bar::handle(const evt::property_notify& evt) {
#ifdef DEBUG_LOGGER_VERBOSE
@ -776,6 +773,13 @@ void bar::handle(const evt::property_notify& evt) {
}
}
void bar::handle(const evt::configure_notify&) {
// The absolute position of the window in the root may be different after configuration is done
// (for example, because the parent is not positioned at 0/0 in the root window).
// Notify components that the geometry may have changed (used by the background manager for example).
m_sig.emit(signals::ui::update_geometry{});
}
bool bar::on(const signals::eventqueue::start&) {
m_log.trace("bar: Create renderer");
m_renderer = renderer::make(m_opts);
@ -789,6 +793,7 @@ bool bar::on(const signals::eventqueue::start&) {
if (!m_opts.cursor_click.empty() || !m_opts.cursor_scroll.empty() ) {
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_POINTER_MOTION);
}
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_STRUCTURE_NOTIFY);
m_log.info("Bar window: %s", m_connection.id(m_opts.window));
restack_window();
@ -800,6 +805,10 @@ bool bar::on(const signals::eventqueue::start&) {
m_log.trace("bar: Map window");
m_connection.map_window_checked(m_opts.window);
// With the mapping, the absolute position of our window may have changed (due to re-parenting for example).
// Notify all components that depend on the absolute bar position (such as the background manager).
m_sig.emit(signals::ui::update_geometry{});
// Reconfigure window position after mapping (required by Openbox)
// Required by Openbox
reconfigure_pos();

View File

@ -166,7 +166,7 @@ renderer::renderer(
}
m_log.trace("Activate root background manager");
m_background.activate(m_window, m_bar.outer_area(true));
m_background.activate(m_window, m_bar.outer_area(false));
}
m_comp_bg = m_conf.get<cairo_operator_t>("settings", "compositing-background", m_comp_bg);

View File

@ -18,9 +18,11 @@ background_manager::background_manager(
: m_connection(conn)
, m_sig(sig)
, m_log(log) {
m_sig.attach(this);
}
background_manager::~background_manager() {
m_sig.detach(this);
free_resources();
}
@ -110,24 +112,26 @@ void background_manager::fetch_root_pixmap() {
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 {
auto translated = m_connection.translate_coordinates(m_window, m_connection.screen()->root, m_rect.x, m_rect.y);
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(translated->dst_x, pixmap_geom.x, int16_t(pixmap_geom.x + pixmap_geom.width));
auto src_y = math_util::cap(translated->dst_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);
m_connection.copy_area_checked(pixmap, m_pixmap, m_gcontext, src_x, src_y, 0, 0, w, h);
} catch (const exception& err) {
} catch(const exception& err) {
m_log.err("background_manager: Failed to copy slice of root pixmap (%s)", err.what());
free_resources();
return;
throw;
}
}
void background_manager::handle(const evt::property_notify& evt) {
@ -140,4 +144,10 @@ void background_manager::handle(const evt::property_notify& evt) {
}
}
bool background_manager::on(const signals::ui::update_geometry&) {
fetch_root_pixmap();
m_sig.emit(signals::ui::update_background());
return false;
}
POLYBAR_NS_END