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(BUILD_TESTS "Build testsuite" OFF)
option(DEBUG_LOGGER "Enable extra debug logging" OFF) option(DEBUG_LOGGER "Enable extra debug logging" OFF)
option(VERBOSE_TRACELOG "Enable verbose trace logs" 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_CCACHE "Enable ccache support" OFF)
option(ENABLE_ALSA "Enable alsa support" ON) 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" set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp"
CACHE STRING "Path to file containing the current temperature") 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 " 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 " 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 " 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") colored_option(STATUS " Enable ccache ${ENABLE_CCACHE}" ENABLE_CCACHE "32;1" "37;2")
message(STATUS "--------------------------") message(STATUS "--------------------------")
colored_option(STATUS " Enable alsa ${ENABLE_ALSA}" ENABLE_ALSA "32;1" "37;2") 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 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") colored_option(STATUS " Enable X Damage ${ENABLE_DAMAGE_EXT}" ENABLE_DAMAGE_EXT "32;1" "37;2")
message(STATUS "--------------------------") 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 attribute : uint8_t;
enum class mousebtn : uint8_t; enum class mousebtn : uint8_t;
DEFINE_ERROR(unrecognized_token); DEFINE_ERROR(parser_error);
DEFINE_ERROR(unrecognized_attribute); DEFINE_CHILD_ERROR(unrecognized_token, parser_error);
DEFINE_CHILD_ERROR(unrecognized_attribute, parser_error);
DEFINE_CHILD_ERROR(unclosed_actionblocks, parser_error);
class parser { class parser {
public: public:

View File

@ -21,7 +21,7 @@ class renderer {
void begin(); void begin();
void end(); void end();
void redraw(); void flush(bool clear);
void reserve_space(edge side, uint16_t w); void reserve_space(edge side, uint16_t w);
@ -36,7 +36,6 @@ class renderer {
bool check_attribute(const attribute attr); bool check_attribute(const attribute attr);
void fill_background(); 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_overline(int16_t x, uint16_t w);
void fill_underline(int16_t x, uint16_t w); void fill_underline(int16_t x, uint16_t w);
void fill_shift(const int16_t px); void fill_shift(const int16_t px);
@ -49,10 +48,13 @@ class renderer {
const vector<action_block> get_actions(); const vector<action_block> get_actions();
protected: 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); 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: private:
connection& m_connection; connection& m_connection;
@ -61,6 +63,8 @@ class renderer {
const bar_settings& m_bar; const bar_settings& m_bar;
xcb_rectangle_t m_rect{0, 0, 0U, 0U};
xcb_window_t m_window; xcb_window_t m_window;
xcb_colormap_t m_colormap; xcb_colormap_t m_colormap;
xcb_visualtype_t* m_visual; xcb_visualtype_t* m_visual;
@ -79,9 +83,6 @@ class renderer {
int8_t m_fontindex{DEFAULT_FONT_INDEX}; int8_t m_fontindex{DEFAULT_FONT_INDEX};
xcb_font_t m_gcfont{XCB_NONE}; 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); 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}; bool force_docking{false};
const xcb_rectangle_t inner_area(bool local_coords = false) const { const xcb_rectangle_t inner_area(bool abspos = false) const {
xcb_rectangle_t rect{pos.x, pos.y, size.w, size.h}; xcb_rectangle_t rect{0, 0, size.w, size.h};
if (local_coords) {
rect.x = 0; if (abspos) {
rect.y = 0; rect.x = pos.x;
rect.y = pos.y;
} }
rect.y += borders.at(edge::TOP).size; rect.y += borders.at(edge::TOP).size;
rect.height -= borders.at(edge::TOP).size; rect.height -= borders.at(edge::TOP).size;
rect.height -= borders.at(edge::BOTTOM).size; rect.height -= borders.at(edge::BOTTOM).size;
@ -126,9 +128,10 @@ struct action_block {
mousebtn button{mousebtn::NONE}; mousebtn button{mousebtn::NONE};
string command; string command;
bool active{true}; bool active{true};
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
xcb_window_t hint; uint16_t width() const {
#endif return end_x - start_x;
}
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

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

View File

@ -80,10 +80,6 @@ namespace modules {
chrono::system_clock::time_point m_lastsync; chrono::system_clock::time_point m_lastsync;
float m_synctime = 1.0f; 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 // This flag is used to let thru a broadcast once every time
// the connection state changes // the connection state changes
mpd::connection_state m_statebroadcasted; mpd::connection_state m_statebroadcasted;

View File

@ -8,7 +8,7 @@ struct cached_atom {
xcb_atom_t* 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_SUPPORTED;
extern xcb_atom_t _NET_CURRENT_DESKTOP; 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 _XROOTMAP_ID;
extern xcb_atom_t _XSETROOT_ID; extern xcb_atom_t _XSETROOT_ID;
extern xcb_atom_t ESETROOT_PMAP_ID; extern xcb_atom_t ESETROOT_PMAP_ID;
extern xcb_atom_t _COMPTON_SHADOW;

View File

@ -6,11 +6,11 @@
POLYBAR_NS POLYBAR_NS
namespace draw_util { namespace draw_util {
void fill(connection& c, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w, void fill(connection& conn, xcb_drawable_t d, xcb_gcontext_t g, const xcb_rectangle_t rect);
uint16_t h); 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_void_cookie_t xcb_poly_text_16_patched(
xcb_gcontext_t gc, int16_t x, int16_t y, uint8_t len, uint16_t* str); 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 POLYBAR_NS_END

View File

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

View File

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

View File

@ -49,7 +49,9 @@ bar::bar(connection& conn, const config& config, const logger& logger, unique_pt
*/ */
bar::~bar() { bar::~bar() {
std::lock_guard<std::mutex> guard(m_mutex); std::lock_guard<std::mutex> guard(m_mutex);
g_signals::tray::report_slotcount = nullptr;
m_connection.detach_sink(this, 1); 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_renderer = configure_renderer(m_opts, m_conf.get_list<string>(bs, "font", {})).create<unique_ptr<renderer>>();
m_window = m_renderer->window(); m_window = m_renderer->window();
m_log.info("Bar window: %s", m_connection.id(m_window));
restack_window(); restack_window();
reconfigure_window(); reconfigure_window();
@ -173,11 +177,10 @@ void bar::bootstrap(bool nodraw) {
try { try {
m_renderer->begin(); m_renderer->begin();
m_renderer->end(); m_renderer->end();
m_renderer->flush(false);
} catch (const exception& err) { } catch (const exception& err) {
throw application_error("Failed to output empty bar window (reason: " + string{err.what()} + ")"); 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) { } else if (settings.align == alignment::LEFT) {
settings.orig_x = m_opts.pos.x + m_opts.borders.at(edge::LEFT).size; settings.orig_x = m_opts.pos.x + m_opts.borders.at(edge::LEFT).size;
} else if (settings.align == alignment::CENTER) { } 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 // Set user-defined background color
@ -357,6 +360,8 @@ void bar::parse(string data, bool force) {
m_lastinput = data; m_lastinput = data;
m_renderer->begin();
if (m_trayclients) { if (m_trayclients) {
if (m_tray && m_trayalign == alignment::LEFT) if (m_tray && m_trayalign == alignment::LEFT)
m_renderer->reserve_space(edge::LEFT, m_tray->settings().configured_w); 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->reserve_space(edge::RIGHT, m_tray->settings().configured_w);
} }
m_renderer->begin(); m_renderer->fill_background();
try { try {
parser parser{m_log, m_opts}; parser parser{m_log, m_opts};
parser(data); parser(data);
} catch (const unrecognized_token& err) { } catch (const parser_error& err) {
m_log.err("Unrecognized syntax token '%s'", err.what()); m_log.err("Failed to parse contents (reason: %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());
} }
m_renderer->end(); 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.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.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.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.y += m_opts.borders[edge::TOP].size;
m_opts.center.x /= 2;
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); 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()) { for (auto&& action : m_renderer->get_actions()) {
if (action.active) { if (action.active) {
@ -584,11 +590,11 @@ void bar::handle(const evt::button_press& evt) {
} else if (action.button != button) { } else if (action.button != button) {
m_log.trace_x("bar: Ignoring action: button mismatch"); m_log.trace_x("bar: Ignoring action: button mismatch");
continue; continue;
} else if (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, evt->event_x); m_log.trace_x("bar: Ignoring action: start_x(%i) > event_x(%i)", action.start_x, event_x);
continue; continue;
} else if (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, evt->event_x); m_log.trace_x("bar: Ignoring action: end_x(%i) < event_x(%i)", action.end_x, event_x);
continue; continue;
} }
@ -617,7 +623,7 @@ void bar::handle(const evt::button_press& evt) {
void bar::handle(const evt::expose& evt) { void bar::handle(const evt::expose& evt) {
if (evt->window == m_window) { if (evt->window == m_window) {
m_log.trace("bar: Received expose event"); 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 * This will also close any unclosed tags
*/ */
string builder::flush() { string builder::flush() {
if (m_tags[syntaxtag::A])
cmd_close();
if (m_tags[syntaxtag::B]) if (m_tags[syntaxtag::B])
background_close(); background_close();
if (m_tags[syntaxtag::F]) if (m_tags[syntaxtag::F])
@ -29,11 +27,15 @@ string builder::flush() {
if ((m_attributes >> static_cast<uint8_t>(attribute::OVERLINE)) & 1U) if ((m_attributes >> static_cast<uint8_t>(attribute::OVERLINE)) & 1U)
overline_close(); overline_close();
while (m_tags[syntaxtag::A]) {
cmd_close();
}
string output = m_output.data(); string output = m_output.data();
// reset values // reset values
for (auto& counter : m_tags) counter.second = 0; m_tags.clear();
for (auto& value : m_colors) value.second = ""; m_colors.clear();
m_output.clear(); m_output.clear();
m_fontindex = 1; m_fontindex = 1;
@ -478,7 +480,9 @@ string builder::foreground_hex() {
* Insert directive to change value of given tag * Insert directive to change value of given tag
*/ */
void builder::tag_open(syntaxtag tag, string value) { void builder::tag_open(syntaxtag tag, string value) {
if (m_tags.find(tag) != m_tags.end()) if (m_tags.find(tag) == m_tags.end())
m_tags[tag] = 0;
m_tags[tag]++; m_tags[tag]++;
switch (tag) { switch (tag) {
@ -536,7 +540,7 @@ void builder::tag_open(attribute attr) {
* Insert directive to reset given tag if it's open and closable * Insert directive to reset given tag if it's open and closable
*/ */
void builder::tag_close(syntaxtag tag) { 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; return;
m_tags[tag]--; m_tags[tag]--;

View File

@ -48,6 +48,10 @@ void parser::operator()(string data) {
data.erase(0, text(data.substr(0, pos))); 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; break;
default: default:
throw unrecognized_token(string{tag}); throw unrecognized_token("Unrecognized token '" + string{tag} + "'");
} }
if (!data.empty()) if (!data.empty())
@ -232,7 +236,7 @@ attribute parser::parse_attr(const char attr) {
case 'u': case 'u':
return attribute::UNDERLINE; return attribute::UNDERLINE;
default: 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/connection.hpp"
#include "x11/draw.hpp" #include "x11/draw.hpp"
#include "x11/fonts.hpp" #include "x11/fonts.hpp"
#include "x11/winspec.hpp"
#include "x11/xlib.hpp" #include "x11/xlib.hpp"
#include "x11/xutils.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, renderer::renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager,
const bar_settings& bar, const vector<string>& fonts) 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) { : m_connection(conn)
auto screen = m_connection.screen(); , 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_log.trace("renderer: Allocate colormap");
m_visual = m_connection.visual_type(screen, 32).get();
m_log.trace("renderer: Create colormap");
m_colormap = m_connection.generate_id(); 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: Allocate output window");
m_log.trace("renderer: Create window (xid=%s)", m_connection.id(m_window));
{ {
uint32_t mask{0}; // clang-format off
uint32_t values[16]{0}; m_window = winspec(m_connection)
xcb_params_cw_t params; << cw_size(m_bar.size)
<< cw_pos(m_bar.pos)
XCB_AUX_ADD_PARAM(&mask, &params, back_pixel, 0); << cw_depth(32)
XCB_AUX_ADD_PARAM(&mask, &params, border_pixel, 0); << cw_visual(m_visual->visual_id)
XCB_AUX_ADD_PARAM(&mask, &params, backing_store, XCB_BACKING_STORE_WHEN_MAPPED); << cw_class(XCB_WINDOW_CLASS_INPUT_OUTPUT)
XCB_AUX_ADD_PARAM(&mask, &params, colormap, m_colormap); << cw_params_back_pixel(0)
XCB_AUX_ADD_PARAM(&mask, &params, override_redirect, m_bar.force_docking); << cw_params_border_pixel(0)
XCB_AUX_ADD_PARAM(&mask, &params, event_mask, << cw_params_backing_store(XCB_BACKING_STORE_WHEN_MAPPED)
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS); << cw_params_colormap(m_colormap)
<< cw_params_event_mask(XCB_EVENT_MASK_PROPERTY_CHANGE
xutils::pack_values(mask, &params, values); |XCB_EVENT_MASK_EXPOSURE
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_EVENT_MASK_BUTTON_PRESS)
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_visual->visual_id, mask, values); << 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_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_rect.width, m_rect.height);
m_connection.create_pixmap(32, m_pixmap, m_window, m_bar.size.w, m_bar.size.h);
m_log.trace("renderer: Create gcontexts"); m_log.trace("renderer: Allocate graphic contexts");
{ {
// clang-format off // clang-format off
vector<uint32_t> colors { 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++) { for (int i = 0; i < 8; i++) {
uint32_t mask{0}; uint32_t mask{0};
uint32_t value_list[32]{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, foreground, colors[i]);
XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 0); XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 0);
xutils::pack_values(mask, &params, value_list); xutils::pack_values(mask, &params, value_list);
m_gcontexts.emplace(gc(i), m_connection.generate_id());
m_colors.emplace(gc(i), colors[i]); 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); 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() { void renderer::begin() {
m_log.trace_x("renderer: begin"); m_log.trace_x("renderer: begin");
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS m_rect = m_bar.inner_area();
for (auto&& action : m_actions) { m_alignment = alignment::NONE;
m_connection.destroy_window(action.hint); m_currentx = 0;
}
#endif
m_currentx = m_bar.inner_area(true).x;
m_attributes = 0; m_attributes = 0;
m_actions.clear(); m_actions.clear();
fill_border(m_bar.borders, edge::ALL);
fill_background();
m_fontmanager->create_xftdraw(m_pixmap, m_colormap); m_fontmanager->create_xftdraw(m_pixmap, m_colormap);
} }
@ -160,33 +156,64 @@ void renderer::begin() {
void renderer::end() { void renderer::end() {
m_log.trace_x("renderer: end"); m_log.trace_x("renderer: end");
redraw();
m_fontmanager->destroy_xftdraw(); m_fontmanager->destroy_xftdraw();
#ifdef DEBUG #ifdef DEBUG_HINTS
debughints(); debug_hints();
#endif #endif
m_reserve = 0; flush(false);
m_reserve_at = edge::NONE;
} }
/** /**
* Redraw window contents * Redraw window contents
*/ */
void renderer::redraw() { void renderer::flush(bool clear) {
m_log.info("Redrawing"); 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) { xcb_rectangle_t bottom{0, 0, 0U, 0U};
r.x += m_reserve; bottom.x += m_bar.borders.at(edge::LEFT).size;
r.width -= m_reserve; bottom.y += m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size;
} else if (m_reserve_at == edge::RIGHT) { bottom.width += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::RIGHT).size;
r.width -= m_reserve; 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) { 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_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)); 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_log.trace_x("renderer: set_alignment(%i)", static_cast<uint8_t>(align));
m_alignment = align; m_alignment = align;
m_currentx = 0;
} }
/** /**
@ -319,52 +356,7 @@ bool renderer::check_attribute(const attribute attr) {
*/ */
void renderer::fill_background() { void renderer::fill_background() {
m_log.trace_x("renderer: fill_background"); m_log.trace_x("renderer: fill_background");
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::BG), 0, 0, m_rect.width, m_rect.height);
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;
}
}
} }
/** /**
@ -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)"); 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]); 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, 0, w, m_bar.overline.size);
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::OL), x, inner.y, 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)"); 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]); 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>(m_rect.height - m_bar.underline.size)};
int16_t y{static_cast<int16_t>(inner.height - m_bar.underline.size)};
draw_util::fill(m_connection, m_pixmap, m_gcontexts.at(gc::UL), x, y, w, 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 * Draw character glyph
*/ */
void renderer::draw_character(uint16_t character) { 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); auto& font = m_fontmanager->match_char(character);
@ -428,7 +418,7 @@ void renderer::draw_character(uint16_t character) {
width++; width++;
auto x = shift_content(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) { if (font->xft != nullptr) {
auto color = m_fontmanager->xftcolor(); auto color = m_fontmanager->xftcolor();
@ -473,7 +463,7 @@ void renderer::draw_textstring(const char* text, size_t len) {
width++; width++;
auto x = shift_content(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) { if (font->xft != nullptr) {
auto color = m_fontmanager->xftcolor(); 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 * End action block at the current position
*/ */
void renderer::end_action(const mousebtn btn) { void renderer::end_action(const mousebtn btn) {
for (auto action = m_actions.rbegin(); action != m_actions.rend(); action++) { int16_t clickable_width{0};
if (!action->active || action->button != btn)
continue;
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; action->active = false;
if (action->align == alignment::LEFT) { switch (action->align) {
case alignment::NONE:
break;
case alignment::LEFT:
action->end_x = m_currentx; action->end_x = m_currentx;
} else if (action->align == alignment::CENTER) { break;
int base_x{m_bar.size.w}; case alignment::CENTER:
int clickable_width{m_currentx - action->start_x}; clickable_width = m_currentx - action->start_x;
base_x -= m_bar.borders.at(edge::RIGHT).size; action->start_x = m_rect.width / 2 - clickable_width / 2 + action->start_x / 2;
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; action->end_x = action->start_x + clickable_width;
} else if (action->align == alignment::RIGHT) { break;
int base_x{m_bar.size.w - m_bar.borders.at(edge::RIGHT).size}; case alignment::RIGHT:
if (m_reserve_at == edge::RIGHT) action->start_x = m_rect.width - m_currentx + action->start_x;
base_x -= m_reserve; action->end_x = m_rect.width;
action->start_x = base_x - m_currentx + action->start_x; break;
action->end_x = base_x;
} }
m_log.trace_x("renderer: end_action(%i, %s, %i)", static_cast<uint8_t>(btn), action->command, action->width());
return; return;
} }
} }
@ -550,30 +541,33 @@ const vector<action_block> renderer::get_actions() {
/** /**
* Shift contents by given pixel value * 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); m_log.trace_x("renderer: shift_content(%i)", shift_x);
int delta = shift_x; int16_t delta{shift_x};
int x2{x}; int16_t base_x{0};
if (m_alignment == alignment::CENTER) { switch (m_alignment) {
int base_x = m_bar.size.w; case alignment::NONE:
base_x -= m_bar.borders.at(edge::RIGHT).size; break;
base_x /= 2; case alignment::LEFT:
base_x += m_bar.borders.at(edge::LEFT).size; break;
m_connection.copy_area( case alignment::CENTER:
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); base_x = static_cast<int16_t>(m_rect.width / 2);
x2 = base_x - (x + shift_x) / 2 + x; 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; delta /= 2;
} else if (m_alignment == alignment::RIGHT) { break;
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, case alignment::RIGHT:
0, x, m_bar.size.h); base_x = static_cast<int16_t>(m_rect.width - x);
x2 = m_bar.size.w - shift_x - m_bar.borders.at(edge::RIGHT).size; m_connection.copy_area(
if (m_reserve_at == edge::RIGHT) m_pixmap, m_pixmap, m_gcontexts.at(gc::FG), base_x, 0, base_x - shift_x, 0, x, m_rect.height);
x2 -= m_reserve; 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 // Translate pos of clickable areas
if (m_alignment != alignment::LEFT) { 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; m_currentx += shift_x;
fill_underline(x2, shift_x); fill_underline(x, shift_x);
fill_overline(x2, 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); return shift_content(m_currentx, shift_x);
} }
#ifdef DEBUG_HINTS
/** /**
* Draw debugging hints onto the output window * Draw debugging hints onto the output window
*/ */
void renderer::debughints() { void renderer::debug_hints() {
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS uint16_t border_width{1};
m_log.info("Drawing debug hints");
map<alignment, int> hint_num{{ 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) { for (auto&& action : m_actions) {
if (action.active) { if (action.active) {
continue; 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; x += num * DEBUG_HINTS_OFFSET_X;
auto y = m_bar.y + hint_num[action.align]++ * DRAW_CLICKABLE_AREA_HINTS_OFFSET_Y; y += num * DEBUG_HINTS_OFFSET_Y;
auto w = action.end_x - action.start_x - 2;
auto h = m_bar.size.h - 2;
const uint32_t mask = XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT; xcb_window_t hintwin{m_connection.generate_id()};
const uint32_t border_color = hint_num[action.align] % 2 ? 0xff0000 : 0x00ff00; m_debughints.emplace_back(hintwin);
const uint32_t values[2]{border_color, true};
action.hint = m_connection.generate_id(); // clang-format off
m_connection.create_window(m_screen->root_depth, action.hint, m_screen->root, x, y, w, h, 1, winspec(m_connection, hintwin)
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_screen->root_visual, mask, values); << cw_size(w, h)
m_connection.map_window(action.hint); << 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 POLYBAR_NS_END

View File

@ -150,7 +150,7 @@ namespace modules {
if (!m_muted && m_volume > 0) if (!m_muted && m_volume > 0)
m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_VOLUME_DOWN); 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(); return m_builder->flush();
} }

View File

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

View File

@ -36,9 +36,10 @@ xcb_atom_t BACKLIGHT;
xcb_atom_t _XROOTMAP_ID; xcb_atom_t _XROOTMAP_ID;
xcb_atom_t _XSETROOT_ID; xcb_atom_t _XSETROOT_ID;
xcb_atom_t ESETROOT_PMAP_ID; xcb_atom_t ESETROOT_PMAP_ID;
xcb_atom_t _COMPTON_SHADOW;
// clang-format off // clang-format off
cached_atom ATOMS[33] = { cached_atom ATOMS[34] = {
{"_NET_SUPPORTED", sizeof("_NET_SUPPORTED") - 1, &_NET_SUPPORTED}, {"_NET_SUPPORTED", sizeof("_NET_SUPPORTED") - 1, &_NET_SUPPORTED},
{"_NET_CURRENT_DESKTOP", sizeof("_NET_CURRENT_DESKTOP") - 1, &_NET_CURRENT_DESKTOP}, {"_NET_CURRENT_DESKTOP", sizeof("_NET_CURRENT_DESKTOP") - 1, &_NET_CURRENT_DESKTOP},
{"_NET_ACTIVE_WINDOW", sizeof("_NET_ACTIVE_WINDOW") - 1, &_NET_ACTIVE_WINDOW}, {"_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}, {"_XROOTMAP_ID", sizeof("_XROOTMAP_ID") - 1, &_XROOTMAP_ID},
{"_XSETROOT_ID", sizeof("_XSETROOT_ID") - 1, &_XSETROOT_ID}, {"_XSETROOT_ID", sizeof("_XSETROOT_ID") - 1, &_XSETROOT_ID},
{"ESETROOT_PMAP_ID", sizeof("ESETROOT_PMAP_ID") - 1, &ESETROOT_PMAP_ID}, {"ESETROOT_PMAP_ID", sizeof("ESETROOT_PMAP_ID") - 1, &ESETROOT_PMAP_ID},
{"_COMPTON_SHADOW", sizeof("_COMPTON_SHADOW") - 1, &_COMPTON_SHADOW},
}; };
// clang-format on // clang-format on

View File

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

View File

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