refactor: Cleanup rendering

This commit is contained in:
Michael Carlberg 2016-11-25 04:10:26 +01:00
parent 7018357e47
commit 9fdc22843b
21 changed files with 612 additions and 461 deletions

View File

@ -43,6 +43,7 @@ option(CXXLIB_GCC "Link against stdlibc++" OFF)
option(BUILD_TESTS "Build testsuite" OFF)
option(DEBUG_LOGGER "Enable extra debug logging" OFF)
option(VERBOSE_TRACELOG "Enable verbose trace logs" OFF)
option(DEBUG_HINTS "Enable hints rendering" OFF)
option(ENABLE_CCACHE "Enable ccache support" OFF)
option(ENABLE_ALSA "Enable alsa support" ON)
@ -82,4 +83,7 @@ set(SETTING_PATH_MESSAGING_FIFO "/tmp/polybar_mqueue.%pid%"
set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp"
CACHE STRING "Path to file containing the current temperature")
set(DEBUG_HINTS_OFFSET_X 0 CACHE INTEGER "Debug hint offset x")
set(DEBUG_HINTS_OFFSET_Y 0 CACHE INTEGER "Debug hint offset y")
# }}}

View File

@ -47,6 +47,7 @@ message(STATUS "--------------------------")
colored_option(STATUS " Build testsuite ${BUILD_TESTS}" BUILD_TESTS "32;1" "37;2")
colored_option(STATUS " Debug logging ${DEBUG_LOGGER}" DEBUG_LOGGER "32;1" "37;2")
colored_option(STATUS " Verbose tracing ${VERBOSE_TRACELOG}" VERBOSE_TRACELOG "32;1" "37;2")
colored_option(STATUS " Draw debug hints ${DEBUG_HINTS}" DEBUG_HINTS "32;1" "37;2")
colored_option(STATUS " Enable ccache ${ENABLE_CCACHE}" ENABLE_CCACHE "32;1" "37;2")
message(STATUS "--------------------------")
colored_option(STATUS " Enable alsa ${ENABLE_ALSA}" ENABLE_ALSA "32;1" "37;2")
@ -58,20 +59,3 @@ colored_option(STATUS " Enable X RandR ${ENABLE_RANDR_EXT}" ENABLE_RANDR_E
colored_option(STATUS " Enable X Render ${ENABLE_RENDER_EXT}" ENABLE_RENDER_EXT "32;1" "37;2")
colored_option(STATUS " Enable X Damage ${ENABLE_DAMAGE_EXT}" ENABLE_DAMAGE_EXT "32;1" "37;2")
message(STATUS "--------------------------")
# message(STATUS " ALSA_SOUNDCARD ${SETTING_ALSA_SOUNDCARD}")
# message(STATUS " BSPWM_SOCKET_PATH ${SETTING_BSPWM_SOCKET_PATH}")
# message(STATUS " BSPWM_STATUS_PREFIX ${SETTING_BSPWM_STATUS_PREFIX}")
# message(STATUS " CONNECTION_TEST_IP ${SETTING_CONNECTION_TEST_IP}")
# message(STATUS " PATH_ADAPTER_STATUS ${SETTING_PATH_ADAPTER_STATUS}")
# message(STATUS " PATH_BACKLIGHT_VAL ${SETTING_PATH_BACKLIGHT_VAL}")
# message(STATUS " PATH_BACKLIGHT_MAX ${SETTING_PATH_BACKLIGHT_MAX}")
# message(STATUS " PATH_BATTERY_CAPACITY ${SETTING_PATH_BATTERY_CAPACITY}")
# message(STATUS " PATH_BATTERY_CAPACITY_MAX ${SETTING_PATH_BATTERY_CAPACITY_MAX}")
# message(STATUS " PATH_BATTERY_CAPACITY_PERC ${SETTING_PATH_BATTERY_CAPACITY_PERC}")
# message(STATUS " PATH_BATTERY_VOLTAGE ${SETTING_PATH_BATTERY_VOLTAGE}")
# message(STATUS " PATH_BATTERY_RATE ${SETTING_PATH_BATTERY_RATE}")
# message(STATUS " PATH_CPU_INFO ${SETTING_PATH_CPU_INFO}")
# message(STATUS " PATH_MEMORY_INFO ${SETTING_PATH_MEMORY_INFO}")
# message(STATUS " PATH_MESSAGING_FIFO ${SETTING_PATH_MESSAGING_FIFO}")
# message(STATUS " PATH_TEMPERATURE_INFO ${SETTING_PATH_TEMPERATURE_INFO}")
# message(STATUS "--------------------------")

View File

@ -9,8 +9,10 @@ struct bar_settings;
enum class attribute : uint8_t;
enum class mousebtn : uint8_t;
DEFINE_ERROR(unrecognized_token);
DEFINE_ERROR(unrecognized_attribute);
DEFINE_ERROR(parser_error);
DEFINE_CHILD_ERROR(unrecognized_token, parser_error);
DEFINE_CHILD_ERROR(unrecognized_attribute, parser_error);
DEFINE_CHILD_ERROR(unclosed_actionblocks, parser_error);
class parser {
public:

View File

@ -21,7 +21,7 @@ class renderer {
void begin();
void end();
void redraw();
void flush(bool clear);
void reserve_space(edge side, uint16_t w);
@ -36,7 +36,6 @@ class renderer {
bool check_attribute(const attribute attr);
void fill_background();
void fill_border(const map<edge, border_settings>& borders, edge border);
void fill_overline(int16_t x, uint16_t w);
void fill_underline(int16_t x, uint16_t w);
void fill_shift(const int16_t px);
@ -49,10 +48,13 @@ class renderer {
const vector<action_block> get_actions();
protected:
int16_t shift_content(const int16_t x, const int16_t shift_x);
int16_t shift_content(int16_t x, const int16_t shift_x);
int16_t shift_content(const int16_t shift_x);
void debughints();
#ifdef DEBUG_HINTS
vector<xcb_window_t> m_debughints;
void debug_hints();
#endif
private:
connection& m_connection;
@ -61,6 +63,8 @@ class renderer {
const bar_settings& m_bar;
xcb_rectangle_t m_rect{0, 0, 0U, 0U};
xcb_window_t m_window;
xcb_colormap_t m_colormap;
xcb_visualtype_t* m_visual;
@ -79,9 +83,6 @@ class renderer {
int8_t m_fontindex{DEFAULT_FONT_INDEX};
xcb_font_t m_gcfont{XCB_NONE};
edge m_reserve_at{edge::NONE};
uint16_t m_reserve;
};
di::injector<unique_ptr<renderer>> configure_renderer(const bar_settings& bar, const vector<string>& fonts);

View File

@ -103,12 +103,14 @@ struct bar_settings {
bool force_docking{false};
const xcb_rectangle_t inner_area(bool local_coords = false) const {
xcb_rectangle_t rect{pos.x, pos.y, size.w, size.h};
if (local_coords) {
rect.x = 0;
rect.y = 0;
const xcb_rectangle_t inner_area(bool abspos = false) const {
xcb_rectangle_t rect{0, 0, size.w, size.h};
if (abspos) {
rect.x = pos.x;
rect.y = pos.y;
}
rect.y += borders.at(edge::TOP).size;
rect.height -= borders.at(edge::TOP).size;
rect.height -= borders.at(edge::BOTTOM).size;
@ -126,9 +128,10 @@ struct action_block {
mousebtn button{mousebtn::NONE};
string command;
bool active{true};
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
xcb_window_t hint;
#endif
uint16_t width() const {
return end_x - start_x;
}
};
POLYBAR_NS_END

View File

@ -19,31 +19,28 @@
#cmakedefine DEBUG_LOGGER
#cmakedefine VERBOSE_TRACELOG
#cmakedefine DEBUG_HINTS
#ifdef DEBUG
#cmakedefine01 DRAW_CLICKABLE_AREA_HINTS
#cmakedefine DRAW_CLICKABLE_AREA_HINTS_OFFSET_Y @DRAW_CLICKABLE_AREA_HINTS_OFFSET_Y @
#ifndef DRAW_CLICKABLE_AREA_HINTS_OFFSET_Y
#define DRAW_CLICKABLE_AREA_HINTS_OFFSET_Y 0
#endif
#ifdef DEBUG_HINTS
static const int DEBUG_HINTS_OFFSET_X{@DEBUG_HINTS_OFFSET_X@};
static const int DEBUG_HINTS_OFFSET_Y{@DEBUG_HINTS_OFFSET_Y@};
#endif
static constexpr const char* ALSA_SOUNDCARD{"default"};
static constexpr const char* BSPWM_SOCKET_PATH{"/tmp/bspwm_0_0-socket"};
static constexpr const char* BSPWM_STATUS_PREFIX{"W"};
static constexpr const char* CONNECTION_TEST_IP{"8.8.8.8"};
static constexpr const char* PATH_ADAPTER{"/sys/class/power_supply/%adapter%"};
static constexpr const char* PATH_BACKLIGHT_MAX{"/sys/class/backlight/%card%/max_brightness"};
static constexpr const char* PATH_BACKLIGHT_VAL{"/sys/class/backlight/%card%/brightness"};
static constexpr const char* PATH_BATTERY{"/sys/class/power_supply/%battery%"};
static constexpr const char* PATH_CPU_INFO{"/proc/stat"};
static constexpr const char* PATH_MEMORY_INFO{"/proc/meminfo"};
static constexpr const char* PATH_MESSAGING_FIFO{"/tmp/polybar_mqueue.%pid%"};
static constexpr const char* PATH_TEMPERATURE_INFO{"/sys/class/thermal/thermal_zone%zone%/temp"};
static constexpr const char* BUILDER_SPACE_TOKEN{"%__"};
static constexpr const char* ALSA_SOUNDCARD{"@SETTING_ALSA_SOUNDCARD@"};
static constexpr const char* BSPWM_SOCKET_PATH{"@SETTING_BSPWM_SOCKET_PATH@"};
static constexpr const char* BSPWM_STATUS_PREFIX{"@SETTING_BSPWM_STATUS_PREFIX@"};
static constexpr const char* CONNECTION_TEST_IP{"@SETTING_CONNECTION_TEST_IP@"};
static constexpr const char* PATH_ADAPTER{"@SETTING_PATH_ADAPTER@"};
static constexpr const char* PATH_BACKLIGHT_MAX{"@SETTING_PATH_BACKLIGHT_MAX@"};
static constexpr const char* PATH_BACKLIGHT_VAL{"@SETTING_PATH_BACKLIGHT_VAL@"};
static constexpr const char* PATH_BATTERY{"@SETTING_PATH_BATTERY@"};
static constexpr const char* PATH_CPU_INFO{"@SETTING_PATH_CPU_INFO@"};
static constexpr const char* PATH_MEMORY_INFO{"@SETTING_PATH_MEMORY_INFO@"};
static constexpr const char* PATH_MESSAGING_FIFO{"@SETTING_PATH_MESSAGING_FIFO@"};
static constexpr const char* PATH_TEMPERATURE_INFO{"@SETTING_PATH_TEMPERATURE_INFO@"};
static const int8_t DEFAULT_FONT_INDEX{-1};
static constexpr const char* BUILDER_SPACE_TOKEN{"%__"};
auto version_details = [](const std::vector<std::string>& args) {
for (auto&& arg : args) {

View File

@ -80,10 +80,6 @@ namespace modules {
chrono::system_clock::time_point m_lastsync;
float m_synctime = 1.0f;
string m_progress_fill;
string m_progress_empty;
string m_progress_indicator;
// This flag is used to let thru a broadcast once every time
// the connection state changes
mpd::connection_state m_statebroadcasted;

View File

@ -8,7 +8,7 @@ struct cached_atom {
xcb_atom_t* atom;
};
extern cached_atom ATOMS[33];
extern cached_atom ATOMS[34];
extern xcb_atom_t _NET_SUPPORTED;
extern xcb_atom_t _NET_CURRENT_DESKTOP;
@ -43,3 +43,4 @@ extern xcb_atom_t BACKLIGHT;
extern xcb_atom_t _XROOTMAP_ID;
extern xcb_atom_t _XSETROOT_ID;
extern xcb_atom_t ESETROOT_PMAP_ID;
extern xcb_atom_t _COMPTON_SHADOW;

View File

@ -6,11 +6,11 @@
POLYBAR_NS
namespace draw_util {
void fill(connection& c, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w,
uint16_t h);
void fill(connection& conn, xcb_drawable_t d, xcb_gcontext_t g, const xcb_rectangle_t rect);
void fill(connection& conn, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w, uint16_t h);
xcb_void_cookie_t xcb_poly_text_16_patched(xcb_connection_t* conn, xcb_drawable_t d,
xcb_gcontext_t gc, int16_t x, int16_t y, uint8_t len, uint16_t* str);
xcb_void_cookie_t xcb_poly_text_16_patched(
xcb_connection_t* conn, xcb_drawable_t d, xcb_gcontext_t gc, int16_t x, int16_t y, uint8_t len, uint16_t* str);
}
POLYBAR_NS_END

View File

@ -6,6 +6,7 @@
#include "components/logger.hpp"
#include "components/types.hpp"
#include "utils/concurrency.hpp"
#include "x11/events.hpp"
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
@ -99,7 +100,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
void bootstrap(tray_settings settings);
void activate();
void deactivate();
void deactivate(bool clear_selection = true);
void reconfigure();
protected:
@ -167,7 +168,6 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
stateflag m_activated{false};
stateflag m_mapped{false};
stateflag m_hidden{false};
stateflag m_sinkattached{false};
thread m_delayed_activation;

View File

@ -1,6 +1,7 @@
#pragma once
#include "common.hpp"
#include "components/types.hpp"
#include "x11/connection.hpp"
POLYBAR_NS
@ -8,46 +9,108 @@ POLYBAR_NS
using connection_t = connection;
struct cw_size {
cw_size(uint16_t w, uint16_t h) : w(w), h(h) {}
uint16_t w;
uint16_t h;
explicit cw_size(uint16_t w, uint16_t h) : w(w), h(h) {}
explicit cw_size(struct size size) : w(size.w), h(size.h) {}
uint16_t w{1};
uint16_t h{1};
};
struct cw_pos {
cw_pos(int16_t x, int16_t y) : x(x), y(y) {}
int16_t x;
int16_t y;
explicit cw_pos(int16_t x, int16_t y) : x(x), y(y) {}
explicit cw_pos(struct position pos) : x(pos.x), y(pos.y) {}
int16_t x{0};
int16_t y{0};
};
struct cw_border {
cw_border(uint16_t border_width) : border_width(border_width) {}
uint16_t border_width;
explicit cw_border(uint16_t border_width) : border_width(border_width) {}
uint16_t border_width{0};
};
struct cw_class {
cw_class(uint16_t class_) : class_(class_) {}
uint16_t class_;
explicit cw_class(uint16_t class_) : class_(class_) {}
uint16_t class_{XCB_COPY_FROM_PARENT};
};
struct cw_parent {
cw_parent(xcb_window_t parent) : parent(parent) {}
xcb_window_t parent;
explicit cw_parent(xcb_window_t parent) : parent(parent) {}
xcb_window_t parent{XCB_NONE};
};
struct cw_depth {
cw_depth(uint8_t depth) : depth(depth) {}
uint8_t depth;
explicit cw_depth(uint8_t depth) : depth(depth) {}
uint8_t depth{XCB_COPY_FROM_PARENT};
};
struct cw_visual {
cw_visual(xcb_visualid_t visualid) : visualid(visualid) {}
xcb_visualid_t visualid;
explicit cw_visual(xcb_visualid_t visualid) : visualid(visualid) {}
xcb_visualid_t visualid{XCB_COPY_FROM_PARENT};
};
struct cw_mask {
cw_mask(uint32_t mask) : mask(mask) {}
const uint32_t mask;
explicit cw_mask(uint32_t mask) : mask(mask) {}
const uint32_t mask{0};
};
struct cw_params {
cw_params(const xcb_params_cw_t* params) : params(params) {}
const xcb_params_cw_t* params;
explicit cw_params(const xcb_params_cw_t* params) : params(params) {}
const xcb_params_cw_t* params{nullptr};
};
struct cw_params_back_pixel {
explicit cw_params_back_pixel(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_back_pixmap {
explicit cw_params_back_pixmap(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_backing_pixel {
explicit cw_params_backing_pixel(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_backing_planes {
explicit cw_params_backing_planes(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_backing_store {
explicit cw_params_backing_store(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_bit_gravity {
explicit cw_params_bit_gravity(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_border_pixel {
explicit cw_params_border_pixel(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_border_pixmap {
explicit cw_params_border_pixmap(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_colormap {
explicit cw_params_colormap(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_cursor {
explicit cw_params_cursor(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_dont_propagate {
explicit cw_params_dont_propagate(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_event_mask {
explicit cw_params_event_mask(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_override_redirect {
explicit cw_params_override_redirect(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_save_under {
explicit cw_params_save_under(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_params_win_gravity {
explicit cw_params_win_gravity(uint32_t value) : value(value) {}
uint32_t value{0};
};
struct cw_flush {
cw_flush(bool checked = true) : checked(checked) {}
bool checked;
explicit cw_flush(bool checked = false) : checked(checked) {}
bool checked{false};
};
/**
@ -55,7 +118,7 @@ struct cw_flush {
*
* Example usage:
* @code cpp
* auto win = winspec(conn)
* auto win = winspec(m_connection)
* << cw_size(100, 200)
* << cw_pos(10, -20)
* << cw_border(9)
@ -66,90 +129,52 @@ struct cw_flush {
*/
class winspec {
public:
explicit winspec(connection& conn, uint32_t id = XCB_NONE) : m_connection(conn), m_window(id) {}
explicit winspec(connection& conn);
explicit winspec(connection& conn, const xcb_window_t& window);
explicit operator xcb_window_t() const {
return m_window;
}
explicit operator xcb_window_t() const;
explicit operator xcb_rectangle_t() const;
explicit operator xcb_rectangle_t() const {
return {m_x, m_y, m_width, m_height};
}
xcb_window_t operator<<(const cw_flush& f);
winspec& operator<<(cw_size w) {
m_width = w.w;
m_height = w.h;
return *this;
}
winspec& operator<<(cw_pos p) {
m_x = p.x;
m_y = p.y;
return *this;
}
winspec& operator<<(cw_border b) {
m_border = b.border_width;
return *this;
}
winspec& operator<<(cw_class c) {
m_class = c.class_;
return *this;
}
winspec& operator<<(cw_parent p) {
m_parent = p.parent;
return *this;
}
winspec& operator<<(cw_depth d) {
m_depth = d.depth;
return *this;
}
winspec& operator<<(cw_visual v) {
m_visual = v.visualid;
return *this;
}
winspec& operator<<(cw_mask m) {
m_mask = m.mask;
return *this;
}
winspec& operator<<(cw_params p) {
m_params = p.params;
return *this;
}
xcb_window_t operator<<(cw_flush f) {
if (!m_window) {
m_window = m_connection.generate_id();
}
uint32_t values[16]{0};
if (m_params != nullptr) {
xutils::pack_values(m_mask, m_params, values);
}
if (f.checked) {
m_connection.create_window_checked(
m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, values);
} else {
m_connection.create_window(
m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, values);
}
return m_window;
}
winspec& operator<<(const cw_size& size);
winspec& operator<<(const cw_pos& p);
winspec& operator<<(const cw_border& b);
winspec& operator<<(const cw_class& c);
winspec& operator<<(const cw_parent& p);
winspec& operator<<(const cw_depth& d);
winspec& operator<<(const cw_visual& v);
winspec& operator<<(const cw_params_back_pixel& p);
winspec& operator<<(const cw_params_back_pixmap& p);
winspec& operator<<(const cw_params_backing_pixel& p);
winspec& operator<<(const cw_params_backing_planes& p);
winspec& operator<<(const cw_params_backing_store& p);
winspec& operator<<(const cw_params_bit_gravity& p);
winspec& operator<<(const cw_params_border_pixel& p);
winspec& operator<<(const cw_params_border_pixmap& p);
winspec& operator<<(const cw_params_colormap& p);
winspec& operator<<(const cw_params_cursor& p);
winspec& operator<<(const cw_params_dont_propagate& p);
winspec& operator<<(const cw_params_event_mask& p);
winspec& operator<<(const cw_params_override_redirect& p);
winspec& operator<<(const cw_params_save_under& p);
winspec& operator<<(const cw_params_win_gravity& p);
protected:
connection& m_connection;
uint32_t m_window;
uint32_t m_parent;
int16_t m_x;
int16_t m_y;
uint16_t m_width;
uint16_t m_height;
xcb_window_t m_window{XCB_NONE};
uint32_t m_parent{XCB_NONE};
uint8_t m_depth{XCB_COPY_FROM_PARENT};
uint16_t m_border{XCB_COPY_FROM_PARENT};
uint16_t m_class{XCB_COPY_FROM_PARENT};
xcb_visualid_t m_visual;
uint32_t m_mask;
const xcb_params_cw_t* m_params{nullptr};
xcb_visualid_t m_visual{XCB_COPY_FROM_PARENT};
int16_t m_x{0};
int16_t m_y{0};
uint16_t m_width{1U};
uint16_t m_height{1U};
uint16_t m_border{0};
uint32_t m_mask{0};
xcb_params_cw_t m_params{};
};
POLYBAR_NS_END

View File

@ -49,7 +49,9 @@ bar::bar(connection& conn, const config& config, const logger& logger, unique_pt
*/
bar::~bar() {
std::lock_guard<std::mutex> guard(m_mutex);
g_signals::tray::report_slotcount = nullptr;
m_connection.detach_sink(this, 1);
m_tray.reset();
}
/**
@ -147,6 +149,8 @@ void bar::bootstrap(bool nodraw) {
m_renderer = configure_renderer(m_opts, m_conf.get_list<string>(bs, "font", {})).create<unique_ptr<renderer>>();
m_window = m_renderer->window();
m_log.info("Bar window: %s", m_connection.id(m_window));
restack_window();
reconfigure_window();
@ -173,11 +177,10 @@ void bar::bootstrap(bool nodraw) {
try {
m_renderer->begin();
m_renderer->end();
m_renderer->flush(false);
} catch (const exception& err) {
throw application_error("Failed to output empty bar window (reason: " + string{err.what()} + ")");
}
m_connection.flush();
}
/**
@ -239,7 +242,7 @@ void bar::bootstrap_tray() {
} else if (settings.align == alignment::LEFT) {
settings.orig_x = m_opts.pos.x + m_opts.borders.at(edge::LEFT).size;
} else if (settings.align == alignment::CENTER) {
settings.orig_x = m_opts.center.x - (settings.width / 2);
settings.orig_x = m_opts.pos.x + m_opts.center.x - (settings.width / 2);
}
// Set user-defined background color
@ -357,6 +360,8 @@ void bar::parse(string data, bool force) {
m_lastinput = data;
m_renderer->begin();
if (m_trayclients) {
if (m_tray && m_trayalign == alignment::LEFT)
m_renderer->reserve_space(edge::LEFT, m_tray->settings().configured_w);
@ -364,21 +369,16 @@ void bar::parse(string data, bool force) {
m_renderer->reserve_space(edge::RIGHT, m_tray->settings().configured_w);
}
m_renderer->begin();
m_renderer->fill_background();
try {
parser parser{m_log, m_opts};
parser(data);
} catch (const unrecognized_token& err) {
m_log.err("Unrecognized syntax token '%s'", err.what());
} catch (const unrecognized_attribute& err) {
m_log.err("Unrecognized attribute '%s'", err.what());
} catch (const exception& err) {
m_log.err("Error parsing contents (err: %s)", err.what());
} catch (const parser_error& err) {
m_log.err("Failed to parse contents (reason: %s)", err.what());
}
m_renderer->end();
m_connection.flush();
}
/**
@ -432,12 +432,17 @@ void bar::configure_geom() {
m_opts.size.w = math_util::cap<int>(m_opts.size.w, 0, m_opts.monitor->w);
m_opts.size.h = math_util::cap<int>(m_opts.size.h, 0, m_opts.monitor->h);
m_opts.center.y = m_opts.size.h + m_opts.borders[edge::TOP].size - m_opts.borders[edge::BOTTOM].size;
m_opts.center.y = m_opts.size.h;
m_opts.center.y -= m_opts.borders[edge::BOTTOM].size;
m_opts.center.y /= 2;
m_opts.center.x = m_opts.pos.x + m_opts.size.w - m_opts.borders[edge::RIGHT].size + m_opts.borders[edge::LEFT].size;
m_opts.center.x /= 2;
m_opts.center.y += m_opts.borders[edge::TOP].size;
m_log.info("Bar geometry %ix%i+%i+%i", m_opts.size.w, m_opts.size.h, m_opts.pos.x, m_opts.pos.y);
m_opts.center.x = m_opts.size.w;
m_opts.center.x -= m_opts.borders[edge::RIGHT].size;
m_opts.center.x /= 2;
m_opts.center.x += m_opts.borders[edge::LEFT].size;
m_log.info("Bar geometry: %ix%i+%i+%i", m_opts.size.w, m_opts.size.h, m_opts.pos.x, m_opts.pos.y);
}
/**
@ -575,7 +580,8 @@ void bar::handle(const evt::button_press& evt) {
m_log.trace_x("bar: Received button press: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y);
mousebtn button = static_cast<mousebtn>(evt->detail);
const mousebtn button{static_cast<mousebtn>(evt->detail)};
const int16_t event_x{static_cast<int16_t>(evt->event_x - m_opts.inner_area().x)};
for (auto&& action : m_renderer->get_actions()) {
if (action.active) {
@ -584,11 +590,11 @@ void bar::handle(const evt::button_press& evt) {
} else if (action.button != button) {
m_log.trace_x("bar: Ignoring action: button mismatch");
continue;
} else if (action.start_x > evt->event_x) {
m_log.trace_x("bar: Ignoring action: start_x(%i) > event_x(%i)", action.start_x, evt->event_x);
} else if (action.start_x >= event_x) {
m_log.trace_x("bar: Ignoring action: start_x(%i) > event_x(%i)", action.start_x, event_x);
continue;
} else if (action.end_x < evt->event_x) {
m_log.trace_x("bar: Ignoring action: end_x(%i) < event_x(%i)", action.end_x, evt->event_x);
} else if (action.end_x <= event_x) {
m_log.trace_x("bar: Ignoring action: end_x(%i) < event_x(%i)", action.end_x, event_x);
continue;
}
@ -617,7 +623,7 @@ void bar::handle(const evt::button_press& evt) {
void bar::handle(const evt::expose& evt) {
if (evt->window == m_window) {
m_log.trace("bar: Received expose event");
m_renderer->redraw();
m_renderer->flush(false);
}
}

View File

@ -12,8 +12,6 @@ POLYBAR_NS
* This will also close any unclosed tags
*/
string builder::flush() {
if (m_tags[syntaxtag::A])
cmd_close();
if (m_tags[syntaxtag::B])
background_close();
if (m_tags[syntaxtag::F])
@ -29,11 +27,15 @@ string builder::flush() {
if ((m_attributes >> static_cast<uint8_t>(attribute::OVERLINE)) & 1U)
overline_close();
while (m_tags[syntaxtag::A]) {
cmd_close();
}
string output = m_output.data();
// reset values
for (auto& counter : m_tags) counter.second = 0;
for (auto& value : m_colors) value.second = "";
m_tags.clear();
m_colors.clear();
m_output.clear();
m_fontindex = 1;
@ -478,8 +480,10 @@ string builder::foreground_hex() {
* Insert directive to change value of given tag
*/
void builder::tag_open(syntaxtag tag, string value) {
if (m_tags.find(tag) != m_tags.end())
m_tags[tag]++;
if (m_tags.find(tag) == m_tags.end())
m_tags[tag] = 0;
m_tags[tag]++;
switch (tag) {
case syntaxtag::NONE:
@ -536,7 +540,7 @@ void builder::tag_open(attribute attr) {
* Insert directive to reset given tag if it's open and closable
*/
void builder::tag_close(syntaxtag tag) {
if (!m_tags[tag] || m_tags.find(tag) == m_tags.end())
if (m_tags.find(tag) == m_tags.end() || !m_tags[tag])
return;
m_tags[tag]--;

View File

@ -48,6 +48,10 @@ void parser::operator()(string data) {
data.erase(0, text(data.substr(0, pos)));
}
}
if (!m_actions.empty()) {
throw unclosed_actionblocks(to_string(m_actions.size()) + " unclosed action block(s)");
}
}
/**
@ -151,7 +155,7 @@ void parser::codeblock(string data) {
break;
default:
throw unrecognized_token(string{tag});
throw unrecognized_token("Unrecognized token '" + string{tag} + "'");
}
if (!data.empty())
@ -232,7 +236,7 @@ attribute parser::parse_attr(const char attr) {
case 'u':
return attribute::UNDERLINE;
default:
throw unrecognized_attribute(string{attr});
throw unrecognized_token("Unrecognized attribute '" + string{attr} + "'");
}
}

View File

@ -3,6 +3,7 @@
#include "x11/connection.hpp"
#include "x11/draw.hpp"
#include "x11/fonts.hpp"
#include "x11/winspec.hpp"
#include "x11/xlib.hpp"
#include "x11/xutils.hpp"
@ -27,41 +28,44 @@ di::injector<unique_ptr<renderer>> configure_renderer(const bar_settings& bar, c
*/
renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager,
const bar_settings& bar, const vector<string>& fonts)
: m_connection(conn), m_log(logger), m_fontmanager(forward<decltype(font_manager)>(font_manager)), m_bar(bar) {
auto screen = m_connection.screen();
: m_connection(conn)
, m_log(logger)
, m_fontmanager(forward<decltype(font_manager)>(font_manager))
, m_bar(bar)
, m_rect(bar.inner_area()) {
m_log.trace("renderer: Get TrueColor visual");
m_visual = m_connection.visual_type(m_connection.screen(), 32).get();
m_log.trace("renderer: Get true color visual");
m_visual = m_connection.visual_type(screen, 32).get();
m_log.trace("renderer: Create colormap");
m_log.trace("renderer: Allocate colormap");
m_colormap = m_connection.generate_id();
m_connection.create_colormap(XCB_COLORMAP_ALLOC_NONE, m_colormap, screen->root, m_visual->visual_id);
m_connection.create_colormap(XCB_COLORMAP_ALLOC_NONE, m_colormap, m_connection.screen()->root, m_visual->visual_id);
m_window = m_connection.generate_id();
m_log.trace("renderer: Create window (xid=%s)", m_connection.id(m_window));
m_log.trace("renderer: Allocate output window");
{
uint32_t mask{0};
uint32_t values[16]{0};
xcb_params_cw_t params;
XCB_AUX_ADD_PARAM(&mask, &params, back_pixel, 0);
XCB_AUX_ADD_PARAM(&mask, &params, border_pixel, 0);
XCB_AUX_ADD_PARAM(&mask, &params, backing_store, XCB_BACKING_STORE_WHEN_MAPPED);
XCB_AUX_ADD_PARAM(&mask, &params, colormap, m_colormap);
XCB_AUX_ADD_PARAM(&mask, &params, override_redirect, m_bar.force_docking);
XCB_AUX_ADD_PARAM(&mask, &params, event_mask,
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS);
xutils::pack_values(mask, &params, values);
m_connection.create_window(32, m_window, screen->root, m_bar.pos.x, m_bar.pos.y, m_bar.size.w, m_bar.size.h, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_visual->visual_id, mask, values);
// clang-format off
m_window = winspec(m_connection)
<< cw_size(m_bar.size)
<< cw_pos(m_bar.pos)
<< cw_depth(32)
<< cw_visual(m_visual->visual_id)
<< cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
<< cw_params_back_pixel(0)
<< cw_params_border_pixel(0)
<< cw_params_backing_store(XCB_BACKING_STORE_WHEN_MAPPED)
<< cw_params_colormap(m_colormap)
<< cw_params_event_mask(XCB_EVENT_MASK_PROPERTY_CHANGE
|XCB_EVENT_MASK_EXPOSURE
|XCB_EVENT_MASK_BUTTON_PRESS)
<< cw_params_override_redirect(m_bar.force_docking)
<< cw_flush(true);
// clang-format on
}
m_log.trace("renderer: Allocate window pixmap");
m_pixmap = m_connection.generate_id();
m_log.trace("renderer: Create pixmap (xid=%s)", m_connection.id(m_pixmap));
m_connection.create_pixmap(32, m_pixmap, m_window, m_bar.size.w, m_bar.size.h);
m_connection.create_pixmap(32, m_pixmap, m_window, m_rect.width, m_rect.height);
m_log.trace("renderer: Create gcontexts");
m_log.trace("renderer: Allocate graphic contexts");
{
// clang-format off
vector<uint32_t> colors {
@ -79,15 +83,14 @@ renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manag
for (int i = 0; i < 8; i++) {
uint32_t mask{0};
uint32_t value_list[32]{0};
xcb_params_gc_t params;
xcb_params_gc_t params;
XCB_AUX_ADD_PARAM(&mask, &params, foreground, colors[i]);
XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 0);
xutils::pack_values(mask, &params, value_list);
m_gcontexts.emplace(gc(i), m_connection.generate_id());
m_colors.emplace(gc(i), colors[i]);
m_log.trace("renderer: Create gcontext (gc=%i, xid=%s)", i, m_connection.id(m_gcontexts.at(gc(i))));
m_gcontexts.emplace(gc(i), m_connection.generate_id());
m_connection.create_gc(m_gcontexts.at(gc(i)), m_pixmap, mask, value_list);
}
}
@ -138,19 +141,12 @@ xcb_window_t renderer::window() const {
void renderer::begin() {
m_log.trace_x("renderer: begin");
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
for (auto&& action : m_actions) {
m_connection.destroy_window(action.hint);
}
#endif
m_currentx = m_bar.inner_area(true).x;
m_rect = m_bar.inner_area();
m_alignment = alignment::NONE;
m_currentx = 0;
m_attributes = 0;
m_actions.clear();
fill_border(m_bar.borders, edge::ALL);
fill_background();
m_fontmanager->create_xftdraw(m_pixmap, m_colormap);
}
@ -160,33 +156,64 @@ void renderer::begin() {
void renderer::end() {
m_log.trace_x("renderer: end");
redraw();
m_fontmanager->destroy_xftdraw();
#ifdef DEBUG
debughints();
#ifdef DEBUG_HINTS
debug_hints();
#endif
m_reserve = 0;
m_reserve_at = edge::NONE;
flush(false);
}
/**
* Redraw window contents
*/
void renderer::redraw() {
m_log.info("Redrawing");
void renderer::flush(bool clear) {
const xcb_rectangle_t& r = m_rect;
xcb_rectangle_t r{0, 0, m_bar.size.w, m_bar.size.h};
xcb_rectangle_t top{0, 0, 0U, 0U};
top.x += m_bar.borders.at(edge::LEFT).size;
top.width += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::RIGHT).size;
top.height += m_bar.borders.at(edge::TOP).size;
if (m_reserve_at == edge::LEFT) {
r.x += m_reserve;
r.width -= m_reserve;
} else if (m_reserve_at == edge::RIGHT) {
r.width -= m_reserve;
xcb_rectangle_t bottom{0, 0, 0U, 0U};
bottom.x += m_bar.borders.at(edge::LEFT).size;
bottom.y += m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size;
bottom.width += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::RIGHT).size;
bottom.height += m_bar.borders.at(edge::BOTTOM).size;
xcb_rectangle_t left{0, 0, 0U, 0U};
left.width += m_bar.borders.at(edge::LEFT).size;
left.height += m_bar.size.h;
xcb_rectangle_t right{0, 0, 0U, 0U};
right.x += m_bar.size.w - m_bar.borders.at(edge::RIGHT).size;
right.width += m_bar.borders.at(edge::RIGHT).size;
right.height += m_bar.size.h;
m_log.trace("renderer: clear window contents");
m_connection.clear_area(false, m_window, 0, 0, m_bar.size.w, m_bar.size.h);
m_log.trace("renderer: copy pixmap (clear=%i)", clear);
m_connection.copy_area(m_pixmap, m_window, m_gcontexts.at(gc::FG), 0, 0, r.x, r.y, r.width, r.height);
m_log.trace_x("renderer: draw top border (%lupx, %08x)", top.height, m_bar.borders.at(edge::TOP).color);
draw_util::fill(m_connection, m_window, m_gcontexts.at(gc::BT), top);
m_log.trace_x("renderer: draw bottom border (%lupx, %08x)", bottom.height, m_bar.borders.at(edge::BOTTOM).color);
draw_util::fill(m_connection, m_window, m_gcontexts.at(gc::BB), bottom);
m_log.trace_x("renderer: draw left border (%lupx, %08x)", left.width, m_bar.borders.at(edge::LEFT).color);
draw_util::fill(m_connection, m_window, m_gcontexts.at(gc::BL), left);
m_log.trace_x("renderer: draw right border (%lupx, %08x)", right.width, m_bar.borders.at(edge::RIGHT).color);
draw_util::fill(m_connection, m_window, m_gcontexts.at(gc::BR), right);
if (clear) {
m_connection.clear_area(false, m_pixmap, 0, 0, r.width, r.height);
}
m_connection.copy_area(m_pixmap, m_window, m_gcontexts.at(gc::FG), r.x, r.y, r.x, r.y, r.width, r.height);
m_connection.flush();
}
/**
@ -194,8 +221,31 @@ void renderer::redraw() {
*/
void renderer::reserve_space(edge side, uint16_t w) {
m_log.trace_x("renderer: reserve_space(%i, %i)", static_cast<uint8_t>(side), w);
m_reserve = w;
m_reserve_at = side;
switch (side) {
case edge::NONE:
break;
case edge::TOP:
m_rect.y += w;
m_rect.height -= w;
break;
case edge::BOTTOM:
m_rect.height -= w;
break;
case edge::LEFT:
m_rect.x += w;
m_rect.width -= w;
break;
case edge::RIGHT:
m_rect.width -= w;
break;
case edge::ALL:
m_rect.x += w;
m_rect.y += w;
m_rect.width -= w * 2;
m_rect.height -= w * 2;
break;
}
}
/**
@ -268,22 +318,9 @@ void renderer::set_alignment(const alignment align) {
return m_log.trace_x("renderer: ignoring unchanged alignment(%i)", static_cast<uint8_t>(align));
}
if (align == alignment::LEFT) {
m_currentx = m_bar.borders.at(edge::LEFT).size;
} else if (align == alignment::RIGHT) {
m_currentx = m_bar.borders.at(edge::RIGHT).size;
} else {
m_currentx = 0;
}
if (align == alignment::LEFT && m_reserve_at == edge::LEFT) {
m_currentx += m_reserve;
} else if (align == alignment::RIGHT && m_reserve_at == edge::RIGHT) {
m_currentx += m_reserve;
}
m_log.trace_x("renderer: set_alignment(%i)", static_cast<uint8_t>(align));
m_alignment = align;
m_currentx = 0;
}
/**
@ -319,52 +356,7 @@ bool renderer::check_attribute(const attribute attr) {
*/
void renderer::fill_background() {
m_log.trace_x("renderer: fill_background");
xcb_rectangle_t rect{0, 0, m_bar.size.w, m_bar.size.h};
if (m_reserve_at == edge::LEFT) {
rect.x += m_reserve;
rect.width -= m_reserve;
} else if (m_reserve_at == edge::RIGHT) {
rect.width -= m_reserve;
}
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), rect.x, rect.y, rect.width, rect.height);
}
/**
* Fill border area
*/
void renderer::fill_border(const map<edge, border_settings>& borders, edge border) {
m_log.trace_x("renderer: fill_border(%i)", static_cast<uint8_t>(border));
for (auto&& b : borders) {
if (!b.second.size || (border != edge::ALL && b.first != border))
continue;
switch (b.first) {
case edge::TOP:
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BT), borders.at(edge::LEFT).size, 0,
m_bar.size.w - borders.at(edge::LEFT).size - borders.at(edge::RIGHT).size, borders.at(edge::TOP).size);
break;
case edge::BOTTOM:
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BB), borders.at(edge::LEFT).size,
m_bar.size.h - borders.at(edge::BOTTOM).size,
m_bar.size.w - borders.at(edge::LEFT).size - borders.at(edge::RIGHT).size, borders.at(edge::BOTTOM).size);
break;
case edge::LEFT:
draw_util::fill(
m_connection, m_pixmap, m_gcontexts.at(gc::BL), 0, 0, borders.at(edge::LEFT).size, m_bar.size.h);
break;
case edge::RIGHT:
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BR), m_bar.size.w - borders.at(edge::RIGHT).size, 0,
borders.at(edge::RIGHT).size, m_bar.size.h);
break;
default:
break;
}
}
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), 0, 0, m_rect.width, m_rect.height);
}
/**
@ -377,8 +369,7 @@ void renderer::fill_overline(int16_t x, uint16_t w) {
return m_log.trace_x("renderer: not filling overline (size=0)");
}
m_log.trace_x("renderer: fill_overline(%i, #%08x)", m_bar.overline.size, m_colors[gc::OL]);
const xcb_rectangle_t inner{m_bar.inner_area(true)};
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, inner.y, w, m_bar.overline.size);
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, 0, w, m_bar.overline.size);
}
/**
@ -391,8 +382,7 @@ void renderer::fill_underline(int16_t x, uint16_t w) {
return m_log.trace_x("renderer: not filling underline (size=0)");
}
m_log.trace_x("renderer: fill_underline(%i, #%08x)", m_bar.underline.size, m_colors[gc::UL]);
const xcb_rectangle_t inner{m_bar.inner_area(true)};
int16_t y{static_cast<int16_t>(inner.height - m_bar.underline.size)};
int16_t y{static_cast<int16_t>(m_rect.height - m_bar.underline.size)};
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::UL), x, y, w, m_bar.underline.size);
}
@ -407,7 +397,7 @@ void renderer::fill_shift(const int16_t px) {
* Draw character glyph
*/
void renderer::draw_character(uint16_t character) {
m_log.trace_x("renderer: draw_character(\"%c\")", character);
m_log.trace_x("renderer: draw_character");
auto& font = m_fontmanager->match_char(character);
@ -428,7 +418,7 @@ void renderer::draw_character(uint16_t character) {
width++;
auto x = shift_content(width);
auto y = m_bar.center.y + font->height / 2 - font->descent + font->offset_y;
auto y = m_rect.height / 2 + font->height / 2 - font->descent + font->offset_y;
if (font->xft != nullptr) {
auto color = m_fontmanager->xftcolor();
@ -473,7 +463,7 @@ void renderer::draw_textstring(const char* text, size_t len) {
width++;
auto x = shift_content(width);
auto y = m_bar.center.y + font->height / 2 - font->descent + font->offset_y;
auto y = m_rect.height / 2 + font->height / 2 - font->descent + font->offset_y;
if (font->xft != nullptr) {
auto color = m_fontmanager->xftcolor();
@ -510,32 +500,33 @@ void renderer::begin_action(const mousebtn btn, const string cmd) {
* End action block at the current position
*/
void renderer::end_action(const mousebtn btn) {
for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) {
if (!action->active || action->button != btn)
continue;
int16_t clickable_width{0};
m_log.trace_x("renderer: end_action(%i, %s)", static_cast<uint8_t>(btn), action->command.c_str());
for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) {
if (!action->active || action->align != m_alignment || action->button != btn)
continue;
action->active = false;
if (action->align == alignment::LEFT) {
action->end_x = m_currentx;
} else if (action->align == alignment::CENTER) {
int base_x{m_bar.size.w};
int clickable_width{m_currentx - action->start_x};
base_x -= m_bar.borders.at(edge::RIGHT).size;
base_x /= 2;
base_x += m_bar.borders.at(edge::LEFT).size;
action->start_x = base_x - clickable_width / 2 + action->start_x / 2;
action->end_x = action->start_x + clickable_width;
} else if (action->align == alignment::RIGHT) {
int base_x{m_bar.size.w - m_bar.borders.at(edge::RIGHT).size};
if (m_reserve_at == edge::RIGHT)
base_x -= m_reserve;
action->start_x = base_x - m_currentx + action->start_x;
action->end_x = base_x;
switch (action->align) {
case alignment::NONE:
break;
case alignment::LEFT:
action->end_x = m_currentx;
break;
case alignment::CENTER:
clickable_width = m_currentx - action->start_x;
action->start_x = m_rect.width / 2 - clickable_width / 2 + action->start_x / 2;
action->end_x = action->start_x + clickable_width;
break;
case alignment::RIGHT:
action->start_x = m_rect.width - m_currentx + action->start_x;
action->end_x = m_rect.width;
break;
}
m_log.trace_x("renderer: end_action(%i, %s, %i)", static_cast<uint8_t>(btn), action->command, action->width());
return;
}
}
@ -550,30 +541,33 @@ const vector<action_block> renderer::get_actions() {
/**
* Shift contents by given pixel value
*/
int16_t renderer::shift_content(const int16_t x, const int16_t shift_x) {
int16_t renderer::shift_content(int16_t x, const int16_t shift_x) {
m_log.trace_x("renderer: shift_content(%i)", shift_x);
int delta = shift_x;
int x2{x};
int16_t delta{shift_x};
int16_t base_x{0};
if (m_alignment == alignment::CENTER) {
int base_x = m_bar.size.w;
base_x -= m_bar.borders.at(edge::RIGHT).size;
base_x /= 2;
base_x += m_bar.borders.at(edge::LEFT).size;
m_connection.copy_area(
m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), base_x - x / 2, 0, base_x - (x + shift_x) / 2, 0, x, m_bar.size.h);
x2 = base_x - (x + shift_x) / 2 + x;
delta /= 2;
} else if (m_alignment == alignment::RIGHT) {
m_connection.copy_area(m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), m_bar.size.w - x, 0, m_bar.size.w - x - shift_x,
0, x, m_bar.size.h);
x2 = m_bar.size.w - shift_x - m_bar.borders.at(edge::RIGHT).size;
if (m_reserve_at == edge::RIGHT)
x2 -= m_reserve;
switch (m_alignment) {
case alignment::NONE:
break;
case alignment::LEFT:
break;
case alignment::CENTER:
base_x = static_cast<int16_t>(m_rect.width / 2);
m_connection.copy_area(m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), base_x - x / 2, 0, base_x - (x + shift_x) / 2,
0, x, m_rect.height);
x = base_x - (x + shift_x) / 2 + x;
delta /= 2;
break;
case alignment::RIGHT:
base_x = static_cast<int16_t>(m_rect.width - x);
m_connection.copy_area(
m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), base_x, 0, base_x - shift_x, 0, x, m_rect.height);
x = m_rect.width - shift_x;
break;
}
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), x2, 0, m_bar.size.w - x, m_bar.size.h);
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), x, 0, m_rect.width - x, m_rect.height);
// Translate pos of clickable areas
if (m_alignment != alignment::LEFT) {
@ -587,10 +581,10 @@ int16_t renderer::shift_content(const int16_t x, const int16_t shift_x) {
m_currentx += shift_x;
fill_underline(x2, shift_x);
fill_overline(x2, shift_x);
fill_underline(x, shift_x);
fill_overline(x, shift_x);
return x2;
return x;
}
/**
@ -600,39 +594,59 @@ int16_t renderer::shift_content(const int16_t shift_x) {
return shift_content(m_currentx, shift_x);
}
#ifdef DEBUG_HINTS
/**
* Draw debugging hints onto the output window
*/
void renderer::debughints() {
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
m_log.info("Drawing debug hints");
void renderer::debug_hints() {
uint16_t border_width{1};
map<alignment, int> hint_num{{
{alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0},
// clang-format off
{alignment::LEFT, 0},
{alignment::CENTER, 0},
{alignment::RIGHT, 0},
// clang-format on
}};
for (auto&& hintwin : m_debughints) {
m_connection.destroy_window(hintwin);
}
m_debughints.clear();
for (auto&& action : m_actions) {
if (action.active) {
continue;
}
hint_num[action.align]++;
uint8_t num{static_cast<uint8_t>(hint_num.find(action.align)->second++)};
int16_t x{static_cast<int16_t>(m_bar.pos.x + m_rect.x + action.start_x)};
int16_t y{static_cast<int16_t>(m_bar.pos.y + m_rect.y)};
uint16_t w{static_cast<uint16_t>(action.width() - border_width * 2)};
uint16_t h{static_cast<uint16_t>(m_rect.height - border_width * 2)};
auto x = action.start_x;
auto y = m_bar.y + hint_num[action.align]++ * DRAW_CLICKABLE_AREA_HINTS_OFFSET_Y;
auto w = action.end_x - action.start_x - 2;
auto h = m_bar.size.h - 2;
x += num * DEBUG_HINTS_OFFSET_X;
y += num * DEBUG_HINTS_OFFSET_Y;
const uint32_t mask = XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT;
const uint32_t border_color = hint_num[action.align] % 2 ? 0xff0000 : 0x00ff00;
const uint32_t values[2]{border_color, true};
xcb_window_t hintwin{m_connection.generate_id()};
m_debughints.emplace_back(hintwin);
action.hint = m_connection.generate_id();
m_connection.create_window(m_screen->root_depth, action.hint, m_screen->root, x, y, w, h, 1,
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, mask, values);
m_connection.map_window(action.hint);
// clang-format off
winspec(m_connection, hintwin)
<< cw_size(w, h)
<< cw_pos(x, y)
<< cw_border(border_width)
<< cw_params_border_pixel(num % 2 ? 0xFFFF0000 : 0xFF00FF00)
<< cw_params_override_redirect(true)
<< cw_flush()
;
// clang-format on
xutils::compton_shadow_exclude(m_connection, hintwin);
m_connection.map_window(hintwin);
m_log.info("Debug hint created (x=%i width=%i)", action.start_x, action.width());
}
#endif
}
#endif
POLYBAR_NS_END

View File

@ -150,7 +150,7 @@ namespace modules {
if (!m_muted && m_volume > 0)
m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_VOLUME_DOWN);
m_builder->node(module::get_output());
m_builder->append(module::get_output());
return m_builder->flush();
}

View File

@ -133,21 +133,12 @@ namespace modules {
* Generate the module output
*/
string xbacklight_module::get_output() {
if (m_scroll) {
if (m_percentage < 100)
m_builder->cmd(mousebtn::SCROLL_UP, EVENT_SCROLLUP);
if (m_percentage > 0)
m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_SCROLLDOWN);
if (m_scroll && m_percentage < 100)
m_builder->cmd(mousebtn::SCROLL_UP, EVENT_SCROLLUP);
if (m_scroll && m_percentage > 0)
m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_SCROLLDOWN);
m_builder->node(static_module::get_output());
if (m_percentage < 100)
m_builder->cmd_close();
if (m_percentage > 0)
m_builder->cmd_close();
} else {
m_builder->node(static_module::get_output());
}
m_builder->append(static_module::get_output());
return m_builder->flush();
}

View File

@ -36,9 +36,10 @@ xcb_atom_t BACKLIGHT;
xcb_atom_t _XROOTMAP_ID;
xcb_atom_t _XSETROOT_ID;
xcb_atom_t ESETROOT_PMAP_ID;
xcb_atom_t _COMPTON_SHADOW;
// clang-format off
cached_atom ATOMS[33] = {
cached_atom ATOMS[34] = {
{"_NET_SUPPORTED", sizeof("_NET_SUPPORTED") - 1, &_NET_SUPPORTED},
{"_NET_CURRENT_DESKTOP", sizeof("_NET_CURRENT_DESKTOP") - 1, &_NET_CURRENT_DESKTOP},
{"_NET_ACTIVE_WINDOW", sizeof("_NET_ACTIVE_WINDOW") - 1, &_NET_ACTIVE_WINDOW},
@ -72,5 +73,6 @@ cached_atom ATOMS[33] = {
{"_XROOTMAP_ID", sizeof("_XROOTMAP_ID") - 1, &_XROOTMAP_ID},
{"_XSETROOT_ID", sizeof("_XSETROOT_ID") - 1, &_XSETROOT_ID},
{"ESETROOT_PMAP_ID", sizeof("ESETROOT_PMAP_ID") - 1, &ESETROOT_PMAP_ID},
{"_COMPTON_SHADOW", sizeof("_COMPTON_SHADOW") - 1, &_COMPTON_SHADOW},
};
// clang-format on

View File

@ -10,15 +10,15 @@ namespace draw_util {
/**
* Fill region of drawable with color defined by gcontext
*/
void fill(connection& c, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w,
uint16_t h) {
xcb_rectangle_t rect;
rect.x = x;
rect.y = y;
rect.width = w;
rect.height = h;
const xcb_rectangle_t rects[1]{rect};
c.poly_fill_rectangle(d, g, 1, rects);
void fill(connection& conn, xcb_drawable_t d, xcb_gcontext_t g, const xcb_rectangle_t rect) {
conn.poly_fill_rectangle(d, g, 1, &rect);
}
/**
* Fill region of drawable with color defined by gcontext
*/
void fill(connection& conn, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w, uint16_t h) {
fill(conn, d, g, {x, y, w, h});
}
/**
@ -26,8 +26,8 @@ namespace draw_util {
*
* Code: http://wmdia.sourceforge.net/
*/
xcb_void_cookie_t xcb_poly_text_16_patched(xcb_connection_t* conn, xcb_drawable_t d,
xcb_gcontext_t gc, int16_t x, int16_t y, uint8_t len, uint16_t* str) {
xcb_void_cookie_t xcb_poly_text_16_patched(
xcb_connection_t* conn, xcb_drawable_t d, xcb_gcontext_t gc, int16_t x, int16_t y, uint8_t len, uint16_t* str) {
static const xcb_protocol_request_t xcb_req = {
5, // count
0, // ext

View File

@ -12,10 +12,10 @@
#include "x11/color.hpp"
#include "x11/connection.hpp"
#include "x11/draw.hpp"
#include "x11/events.hpp"
#include "x11/graphics.hpp"
#include "x11/tray.hpp"
#include "x11/window.hpp"
#include "x11/winspec.hpp"
#include "x11/wm.hpp"
#include "x11/xembed.hpp"
@ -122,14 +122,11 @@ void tray_client::configure_notify(int16_t x, int16_t y) const { // {{{
tray_manager::tray_manager(connection& conn, const logger& logger) : m_connection(conn), m_log(logger) {
m_connection.attach_sink(this, 2);
m_sinkattached = true;
}
tray_manager::~tray_manager() {
if (m_activated)
deactivate();
if (m_sinkattached)
m_connection.detach_sink(this, 2);
m_connection.detach_sink(this, 2);
deactivate();
}
/**
@ -155,7 +152,7 @@ void tray_manager::activate() { // {{{
return;
}
m_log.info("Activating tray_manager");
m_log.info("Activating tray manager");
m_activated = true;
try {
@ -166,16 +163,11 @@ void tray_manager::activate() { // {{{
set_traycolors();
} catch (const exception& err) {
m_log.err(err.what());
m_log.err("Cannot activate tray_manager... failed to setup window");
m_log.err("Cannot activate tray manager... failed to setup window");
m_activated = false;
return;
}
if (!m_sinkattached) {
m_connection.attach_sink(this, 2);
m_sinkattached = true;
}
// Listen for visibility change events on the bar window
if (!m_restacked && !g_signals::bar::visibility_change) {
g_signals::bar::visibility_change = bind(&tray_manager::bar_visibility_change, this, std::placeholders::_1);
@ -185,12 +177,7 @@ void tray_manager::activate() { // {{{
// notify clients waiting for a manager.
acquire_selection();
// If replacing an existing manager or if re-activating from getting
// replaced, we delay the notification broadcast to allow the clients
// to get unembedded...
if (m_othermanager)
std::this_thread::sleep_for(std::chrono::seconds{1});
// Notify pending tray clients
notify_clients();
m_connection.flush();
@ -199,12 +186,12 @@ void tray_manager::activate() { // {{{
/**
* Deactivate systray management
*/
void tray_manager::deactivate() { // {{{
void tray_manager::deactivate(bool clear_selection) { // {{{
if (!m_activated) {
return;
}
m_log.info("Deactivating tray_manager");
m_log.info("Deactivating tray manager");
m_activated = false;
if (m_delayed_activation.joinable())
@ -219,11 +206,9 @@ void tray_manager::deactivate() { // {{{
g_signals::bar::visibility_change = nullptr;
}
if (!m_connection.connection_has_error()) {
if (m_connection.get_selection_owner_unchecked(m_atom).owner<xcb_window_t>() == m_tray) {
m_log.trace("tray: Unset selection owner");
m_connection.set_selection_owner(XCB_NONE, m_atom, XCB_CURRENT_TIME);
}
if (!m_connection.connection_has_error() && clear_selection) {
m_log.trace("tray: Unset selection owner");
m_connection.set_selection_owner(XCB_NONE, m_atom, XCB_CURRENT_TIME);
}
m_log.trace("tray: Unembed clients");
@ -255,6 +240,11 @@ void tray_manager::deactivate() { // {{{
m_rootpixmap.pixmap = 0;
m_prevwidth = 0;
m_prevheight = 0;
m_opts.configured_x = 0;
m_opts.configured_y = 0;
m_opts.configured_w = 0;
m_opts.configured_h = 0;
m_opts.configured_slots = 0;
m_connection.flush();
} // }}}
@ -497,36 +487,24 @@ void tray_manager::query_atom() { // {{{
* Create tray window
*/
void tray_manager::create_window() { // {{{
auto scr = m_connection.screen();
auto w = calculate_w();
auto h = calculate_h();
auto x = calculate_x(w);
auto y = calculate_y();
m_log.trace("tray: Create tray window");
if (w < 1) {
w = 1;
}
m_tray = m_connection.generate_id();
m_log.trace("tray: Create tray window %s, (%ix%i+%i+%i)", m_connection.id(m_tray), w, h, x, y);
uint32_t mask = 0;
uint32_t values[16];
xcb_params_cw_t params;
auto win = winspec(m_connection, m_tray)
<< cw_size(calculate_w(), calculate_h())
<< cw_pos(calculate_x(calculate_w()), calculate_y())
<< cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
<< cw_params_backing_store(XCB_BACKING_STORE_WHEN_MAPPED)
<< cw_params_event_mask(XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY)
<< cw_params_override_redirect(true)
;
if (!m_opts.transparent) {
XCB_AUX_ADD_PARAM(&mask, &params, back_pixel, m_opts.background);
XCB_AUX_ADD_PARAM(&mask, &params, border_pixel, m_opts.background);
win << cw_params_back_pixel(m_opts.background);
win << cw_params_border_pixel(m_opts.background);
}
XCB_AUX_ADD_PARAM(&mask, &params, backing_store, XCB_BACKING_STORE_WHEN_MAPPED);
XCB_AUX_ADD_PARAM(&mask, &params, override_redirect, true);
XCB_AUX_ADD_PARAM(&mask, &params, event_mask, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY);
xutils::pack_values(mask, &params, values);
m_connection.create_window_checked(
scr->root_depth, m_tray, scr->root, x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, mask, values);
m_tray = win << cw_flush();
m_log.info("Tray window: %s", m_connection.id(m_tray));
xutils::compton_shadow_exclude(m_connection, m_tray);
} // }}}
@ -662,13 +640,14 @@ void tray_manager::set_traycolors() { // {{{
* Acquire the systray selection
*/
void tray_manager::acquire_selection() { // {{{
xcb_window_t owner = m_connection.get_selection_owner_unchecked(m_atom)->owner;
xcb_window_t owner{m_connection.get_selection_owner_unchecked(m_atom)->owner};
if (owner == m_tray) {
m_log.info("tray: Already managing the systray selection");
return;
} else if ((m_othermanager = owner)) {
m_log.info("Replacing selection manager %s", m_connection.id(owner));
std::this_thread::sleep_for(std::chrono::seconds{1});
}
m_log.trace("tray: Change selection owner to %s", m_connection.id(m_tray));
@ -1011,7 +990,7 @@ void tray_manager::handle(const evt::selection_clear& evt) { // {{{
m_othermanager = 0;
}
deactivate();
deactivate(false);
} // }}}
/**
@ -1073,8 +1052,11 @@ void tray_manager::handle(const evt::reparent_notify& evt) { // {{{
* Event callback : XCB_DESTROY_NOTIFY
*/
void tray_manager::handle(const evt::destroy_notify& evt) { // {{{
if (!m_activated && evt->window == m_othermanager) {
if (m_activated && evt->window == m_tray) {
deactivate();
} else if (!m_activated && evt->window == m_othermanager && evt->window != m_tray) {
m_log.trace("tray: Received destroy_notify");
std::this_thread::sleep_for(std::chrono::seconds{1});
m_log.info("Tray selection available... re-activating");
activate();
window{m_connection, m_tray}.redraw();
@ -1131,8 +1113,10 @@ void tray_manager::handle(const evt::unmap_notify& evt) { // {{{
}
m_log.trace("tray: Update container mapped flag");
m_mapped = false;
m_opts.configured_w = 0;
m_opts.configured_x = 0;
if (!m_hidden) {
m_opts.configured_w = 0;
m_opts.configured_x = 0;
}
} else {
auto client = find_client(evt->window);
if (client) {

133
src/x11/winspec.cpp Normal file
View File

@ -0,0 +1,133 @@
#include "x11/winspec.hpp"
POLYBAR_NS
winspec::winspec(connection& conn) : m_connection(conn) {}
winspec::winspec(connection& conn, const xcb_window_t& window) : m_connection(conn), m_window(window) {}
winspec::operator xcb_window_t() const {
return m_window;
}
winspec::operator xcb_rectangle_t() const {
return {m_x, m_y, m_width, m_height};
}
xcb_window_t winspec::operator<<(const cw_flush& f) {
uint32_t values[16]{0};
if (m_window == XCB_NONE)
m_window = m_connection.generate_id();
if (m_parent == XCB_NONE)
m_parent = m_connection.screen()->root;
if (m_width <= 0)
m_width = 1;
if (m_height <= 0)
m_height = 1;
xutils::pack_values(m_mask, &m_params, values);
if (f.checked) {
m_connection.create_window_checked(
m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, values);
} else {
m_connection.create_window(
m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border, m_class, m_visual, m_mask, values);
}
return m_window;
}
winspec& winspec::operator<<(const cw_size& size) {
m_width = size.w;
m_height = size.h;
return *this;
}
winspec& winspec::operator<<(const cw_pos& p) {
m_x = p.x;
m_y = p.y;
return *this;
}
winspec& winspec::operator<<(const cw_border& b) {
m_border = b.border_width;
return *this;
}
winspec& winspec::operator<<(const cw_class& c) {
m_class = c.class_;
return *this;
}
winspec& winspec::operator<<(const cw_parent& p) {
m_parent = p.parent;
return *this;
}
winspec& winspec::operator<<(const cw_depth& d) {
m_depth = d.depth;
return *this;
}
winspec& winspec::operator<<(const cw_visual& v) {
m_visual = v.visualid;
return *this;
}
winspec& winspec::operator<<(const cw_params_back_pixel& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, back_pixel, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_back_pixmap& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, back_pixmap, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_backing_pixel& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, backing_pixel, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_backing_planes& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, backing_planes, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_backing_store& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, backing_store, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_bit_gravity& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, bit_gravity, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_border_pixel& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, border_pixel, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_border_pixmap& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, border_pixmap, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_colormap& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, colormap, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_cursor& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, cursor, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_dont_propagate& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, dont_propagate, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_event_mask& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, event_mask, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_override_redirect& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, override_redirect, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_save_under& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, save_under, p.value);
return *this;
}
winspec& winspec::operator<<(const cw_params_win_gravity& p) {
XCB_AUX_ADD_PARAM(&m_mask, &m_params, win_gravity, p.value);
return *this;
}
POLYBAR_NS_END