refactor: Cleanup

This commit is contained in:
Michael Carlberg 2016-12-21 23:22:02 +01:00
parent 185363056a
commit bc9b9f0d12
32 changed files with 276 additions and 311 deletions

View File

@ -70,3 +70,18 @@ endif()
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR) if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR include) set(CMAKE_INSTALL_INCLUDEDIR include)
endif() endif()
# Custom build type ; SANITIZE
SET(CMAKE_CXX_FLAGS_SANITIZE "-O1 -g -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls"
CACHE STRING "Flags used by the C++ compiler during sanitize builds." FORCE)
SET(CMAKE_C_FLAGS_SANITIZE ""
CACHE STRING "Flags used by the C compiler during sanitize builds." FORCE)
SET(CMAKE_EXE_LINKER_FLAGS_SANITIZE ""
CACHE STRING "Flags used for linking binaries during sanitize builds." FORCE)
SET(CMAKE_SHARED_LINKER_FLAGS_SANITIZE ""
CACHE STRING "Flags used by the shared libraries linker during sanitize builds." FORCE)
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_SANITIZE
CMAKE_C_FLAGS_SANITIZE
CMAKE_EXE_LINKER_FLAGS_SANITIZE
CMAKE_SHARED_LINKER_FLAGS_SANITIZE)

View File

@ -17,7 +17,8 @@ message(STATUS " Compiler C: ${CMAKE_C_COMPILER}")
message(STATUS " Compiler C++: ${CMAKE_CXX_COMPILER}") message(STATUS " Compiler C++: ${CMAKE_CXX_COMPILER}")
message(STATUS " Compiler flags: ${CMAKE_CXX_FLAGS}") message(STATUS " Compiler flags: ${CMAKE_CXX_FLAGS}")
if(CMAKE_BUILD_TYPE STREQUAL "Debug") string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if(CMAKE_BUILD_TYPE_LOWER STREQUAL "debug")
message(STATUS " debug flags: ${CMAKE_CXX_FLAGS_DEBUG}") message(STATUS " debug flags: ${CMAKE_CXX_FLAGS_DEBUG}")
if(NOT DEFINED ${DEBUG_LOGGER}) if(NOT DEFINED ${DEBUG_LOGGER})
set(DEBUG_LOGGER ON) set(DEBUG_LOGGER ON)
@ -25,11 +26,13 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(NOT DEFINED ${ENABLE_CCACHE}) if(NOT DEFINED ${ENABLE_CCACHE})
set(ENABLE_CCACHE ON) set(ENABLE_CCACHE ON)
endif() endif()
elseif(CMAKE_BUILD_TYPE STREQUAL "Release") elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "release")
message(STATUS " release: ${CMAKE_CXX_FLAGS_RELEASE}") message(STATUS " release: ${CMAKE_CXX_FLAGS_RELEASE}")
elseif(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel") elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "sanitize")
message(STATUS " sanitize: ${CMAKE_CXX_FLAGS_SANITIZE}")
elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "minsizerel")
message(STATUS " minsizerel: ${CMAKE_CXX_FLAGS_MINSIZEREL}") message(STATUS " minsizerel: ${CMAKE_CXX_FLAGS_MINSIZEREL}")
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "relwithdebinfo")
message(STATUS " relwithdebinfo: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") message(STATUS " relwithdebinfo: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
endif() endif()

View File

@ -48,4 +48,8 @@ using std::array;
using std::vector; using std::vector;
using std::to_string; using std::to_string;
constexpr size_t operator"" _z(unsigned long long n) {
return n;
}
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -79,6 +79,9 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, sig_ev::proc
unique_ptr<inotify_watch> m_confwatch; unique_ptr<inotify_watch> m_confwatch;
unique_ptr<command> m_command; unique_ptr<command> m_command;
shared_ptr<file_descriptor> m_fdevent_rd;
shared_ptr<file_descriptor> m_fdevent_wr;
/** /**
* @brief Controls weather the output gets printed to stdout * @brief Controls weather the output gets printed to stdout
*/ */

View File

@ -20,15 +20,15 @@ namespace modules {
// Warm up module output and // Warm up module output and
// send broadcast before entering // send broadcast before entering
// the update loop // the update loop
if (CONST_MOD(Impl).running()) { if (this->running()) {
CAST_MOD(Impl)->update(); CAST_MOD(Impl)->update();
CAST_MOD(Impl)->broadcast(); CAST_MOD(Impl)->broadcast();
} }
while (CONST_MOD(Impl).running()) { while (this->running()) {
CAST_MOD(Impl)->idle(); CAST_MOD(Impl)->idle();
if (!CONST_MOD(Impl).running()) { if (!this->running()) {
break; break;
} }
@ -36,7 +36,7 @@ namespace modules {
if (!CAST_MOD(Impl)->has_event()) { if (!CAST_MOD(Impl)->has_event()) {
continue; continue;
} else if (!CONST_MOD(Impl).running()) { } else if (!this->running()) {
break; break;
} else if (!CAST_MOD(Impl)->update()) { } else if (!CAST_MOD(Impl)->update()) {
continue; continue;

View File

@ -21,12 +21,12 @@ namespace modules {
// Warm up module output and // Warm up module output and
// send broadcast before entering // send broadcast before entering
// the update loop // the update loop
if (CONST_MOD(Impl).running()) { if (this->running()) {
CAST_MOD(Impl)->on_event(nullptr); CAST_MOD(Impl)->on_event(nullptr);
CAST_MOD(Impl)->broadcast(); CAST_MOD(Impl)->broadcast();
} }
while (CONST_MOD(Impl).running()) { while (this->running()) {
CAST_MOD(Impl)->poll_events(); CAST_MOD(Impl)->poll_events();
} }
} catch (const module_error& err) { } catch (const module_error& err) {
@ -37,7 +37,7 @@ namespace modules {
} }
void watch(string path, int mask = IN_ALL_EVENTS) { void watch(string path, int mask = IN_ALL_EVENTS) {
this->m_log.trace("%s: Attach inotify at %s", CONST_MOD(Impl).name(), path); this->m_log.trace("%s: Attach inotify at %s", this->name(), path);
m_watchlist.insert(make_pair(path, mask)); m_watchlist.insert(make_pair(path, mask));
} }
@ -55,16 +55,16 @@ namespace modules {
} }
} catch (const system_error& e) { } catch (const system_error& e) {
watches.clear(); watches.clear();
this->m_log.err("%s: Error while creating inotify watch (what: %s)", CONST_MOD(Impl).name(), e.what()); this->m_log.err("%s: Error while creating inotify watch (what: %s)", this->name(), e.what());
CAST_MOD(Impl)->sleep(0.1s); CAST_MOD(Impl)->sleep(0.1s);
return; return;
} }
while (CONST_MOD(Impl).running()) { while (this->running()) {
std::unique_lock<std::mutex> guard(this->m_updatelock); std::unique_lock<std::mutex> guard(this->m_updatelock);
{
for (auto&& w : watches) { for (auto&& w : watches) {
this->m_log.trace_x("%s: Poll inotify watch %s", CONST_MOD(Impl).name(), w->path()); this->m_log.trace_x("%s: Poll inotify watch %s", this->name(), w->path());
if (w->poll(1000 / watches.size())) { if (w->poll(1000 / watches.size())) {
auto event = w->get_event(); auto event = w->get_event();
@ -73,21 +73,21 @@ namespace modules {
try { try {
w->remove(); w->remove();
} catch (const system_error&) { } catch (const system_error&) {
// ignore
} }
} }
if (CAST_MOD(Impl)->on_event(event.get())) if (CAST_MOD(Impl)->on_event(event.get())) {
CAST_MOD(Impl)->broadcast(); CAST_MOD(Impl)->broadcast();
}
CAST_MOD(Impl)->idle(); CAST_MOD(Impl)->idle();
return; return;
} }
if (!CONST_MOD(Impl).running()) if (!this->running())
break; break;
} }
}
guard.unlock(); guard.unlock();
CAST_MOD(Impl)->idle(); CAST_MOD(Impl)->idle();
} }

View File

@ -1,13 +1,9 @@
#pragma once #pragma once
#include <chrono>
#include "modules/meta/base.hpp" #include "modules/meta/base.hpp"
POLYBAR_NS POLYBAR_NS
namespace chrono = std::chrono;
namespace modules { namespace modules {
using interval_t = chrono::duration<double>; using interval_t = chrono::duration<double>;
@ -21,27 +17,27 @@ namespace modules {
} }
protected: protected:
interval_t m_interval{1};
void runner() { void runner() {
try { try {
while (CONST_MOD(Impl).running()) { while (this->running()) {
{ std::unique_lock<std::mutex> guard(this->m_updatelock);
std::lock_guard<std::mutex> guard(this->m_updatelock);
if (CAST_MOD(Impl)->update()) if (CAST_MOD(Impl)->update()) {
this->broadcast(); this->broadcast();
} }
if (CONST_MOD(Impl).running()) {
if (this->running()) {
guard.unlock();
this->sleep(m_interval); this->sleep(m_interval);
} }
} }
} catch (const module_error& err) { } catch (const exception& err) {
this->halt(err.what());
} catch (const std::exception& err) {
this->halt(err.what()); this->halt(err.what());
} }
} }
protected:
interval_t m_interval{1};
}; };
} }

View File

@ -6,15 +6,16 @@
POLYBAR_NS POLYBAR_NS
template <typename T>
using malloc_ptr_t = shared_ptr<T>;
namespace memory_util { namespace memory_util {
/** /**
* Create a shared pointer using malloc/free * Create a shared pointer using malloc/free
*/ */
template <typename T, typename Deleter = decltype(free)> template <typename T, size_t Size = sizeof(T), typename Deleter = decltype(free)>
inline auto make_malloc_ptr(size_t size = sizeof(T), Deleter deleter = free) { inline malloc_ptr_t<T> make_malloc_ptr(Deleter deleter = free) {
shared_ptr<T> ptr{static_cast<T*>(malloc(size)), deleter}; return malloc_ptr_t<T>(static_cast<T*>(calloc(1, Size)), deleter);
memset(ptr.get(), 0, size);
return ptr;
} }
/** /**
@ -24,9 +25,6 @@ namespace memory_util {
inline auto countof(T& p) { inline auto countof(T& p) {
return sizeof(p) / sizeof(p[0]); return sizeof(p) / sizeof(p[0]);
} }
template <typename T>
using malloc_ptr_t = shared_ptr<T>;
} }
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -17,10 +17,9 @@ using xpp_connection = xpp::connection<XPP_EXTENSION_LIST>;
class connection : public xpp_connection { class connection : public xpp_connection {
public: public:
using make_type = connection&; using make_type = connection&;
static make_type make(xcb_connection_t* conn = nullptr, int conn_fd = 0); static make_type make(xcb_connection_t* conn = nullptr);
explicit connection(xcb_connection_t* conn) : connection(conn, 0) {}
explicit connection(xcb_connection_t* conn) : xpp_connection(conn) {}
explicit connection(xcb_connection_t* conn, int connection_fd) explicit connection(xcb_connection_t* conn, int connection_fd)
: xpp_connection(conn), m_connection_fd(file_util::make_file_descriptor(connection_fd)) {} : xpp_connection(conn), m_connection_fd(file_util::make_file_descriptor(connection_fd)) {}
@ -49,11 +48,11 @@ class connection : public xpp_connection {
static string error_str(int error_code); static string error_str(int error_code);
void dispatch_event(shared_ptr<xcb_generic_event_t>&& evt) const; void dispatch_event(const shared_ptr<xcb_generic_event_t>& evt) const;
template <typename Event, uint32_t ResponseType> template <typename Event, uint32_t ResponseType>
void wait_for_response(function<bool(const Event&)> check_event) { void wait_for_response(function<bool(const Event*)> check_event) {
shared_ptr<xcb_generic_event_t> evt; shared_ptr<xcb_generic_event_t> evt{};
while (!connection_has_error()) { while (!connection_has_error()) {
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
@ -61,11 +60,11 @@ class connection : public xpp_connection {
if (!select(*m_connection_fd + 1, &fds, nullptr, nullptr, nullptr)) { if (!select(*m_connection_fd + 1, &fds, nullptr, nullptr, nullptr)) {
continue; continue;
} else if ((evt = poll_for_event()) == nullptr) { } else if ((evt = shared_ptr<xcb_generic_event_t>(xcb_poll_for_event(*this), free)) == nullptr) {
continue; continue;
} else if (evt->response_type != ResponseType) { } else if (evt->response_type != ResponseType) {
continue; continue;
} else if (check_event(reinterpret_cast<const Event&>(*(evt.get())))) { } else if (check_event(reinterpret_cast<const Event*>(&*evt))) {
break; break;
} }
} }

View File

@ -6,14 +6,9 @@
POLYBAR_NS POLYBAR_NS
class connection;
namespace draw_util { namespace draw_util {
void fill(xcb_connection_t* c, xcb_drawable_t d, xcb_gcontext_t g, const xcb_rectangle_t rect); void fill(xcb_connection_t* c, xcb_drawable_t d, xcb_gcontext_t g, const xcb_rectangle_t rect);
void fill(xcb_connection_t* c, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w, uint16_t h); void fill(xcb_connection_t* c, 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);
} }
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -9,7 +9,7 @@ POLYBAR_NS
struct position; struct position;
using ewmh_connection_t = memory_util::malloc_ptr_t<xcb_ewmh_connection_t>; using ewmh_connection_t = malloc_ptr_t<xcb_ewmh_connection_t>;
namespace ewmh_util { namespace ewmh_util {
ewmh_connection_t initialize(); ewmh_connection_t initialize();

View File

@ -38,9 +38,7 @@ struct font_ref {
vector<xcb_charinfo_t> width_lut{}; vector<xcb_charinfo_t> width_lut{};
unordered_map<uint16_t, wchar_t> glyph_widths{}; unordered_map<uint16_t, wchar_t> glyph_widths{};
static struct _deleter { static struct _deleter { void operator()(font_ref* font); } deleter;
void operator()(font_ref* font);
} deleter;
}; };
class font_manager { class font_manager {
@ -48,14 +46,13 @@ class font_manager {
using make_type = unique_ptr<font_manager>; using make_type = unique_ptr<font_manager>;
static make_type make(); static make_type make();
explicit font_manager( explicit font_manager(connection& conn, const logger& logger, Display* dsp, Visual* vis, Colormap&& cm);
connection& conn, const logger& logger, shared_ptr<Display>&& dsp, shared_ptr<Visual>&& vis, Colormap&& cm);
~font_manager(); ~font_manager();
font_manager(const font_manager& o) = delete; font_manager(const font_manager& o) = delete;
font_manager& operator=(const font_manager& o) = delete; font_manager& operator=(const font_manager& o) = delete;
void set_visual(shared_ptr<Visual>&& v); void set_visual(Visual* v);
void cleanup(); void cleanup();
bool load(const string& name, uint8_t fontindex = 0, int8_t offset_y = 0); bool load(const string& name, uint8_t fontindex = 0, int8_t offset_y = 0);
@ -68,8 +65,6 @@ class font_manager {
void allocate_color(uint32_t color); void allocate_color(uint32_t color);
void allocate_color(XRenderColor color); void allocate_color(XRenderColor color);
void set_gcontext_font(const shared_ptr<font_ref>& font, xcb_gcontext_t, xcb_font_t*);
protected: protected:
bool open_xcb_font(const shared_ptr<font_ref>& font, string fontname); bool open_xcb_font(const shared_ptr<font_ref>& font, string fontname);
@ -79,12 +74,14 @@ class font_manager {
bool has_glyph_xft(const shared_ptr<font_ref>& font, const uint16_t chr); bool has_glyph_xft(const shared_ptr<font_ref>& font, const uint16_t chr);
bool has_glyph_xcb(const shared_ptr<font_ref>& font, const uint16_t chr); bool has_glyph_xcb(const shared_ptr<font_ref>& font, const uint16_t chr);
void xcb_poly_text_16(xcb_drawable_t d, xcb_gcontext_t gc, int16_t x, int16_t y, uint8_t len, uint16_t* str);
private: private:
connection& m_connection; connection& m_connection;
const logger& m_logger; const logger& m_logger;
shared_ptr<Display> m_display; Display* m_display{nullptr};
shared_ptr<Visual> m_visual; Visual* m_visual{nullptr};
Colormap m_colormap; Colormap m_colormap;
map<uint8_t, shared_ptr<font_ref>> m_fonts{}; map<uint8_t, shared_ptr<font_ref>> m_fonts{};

View File

@ -17,33 +17,32 @@ class tray_client {
tray_client(const tray_client& c) = default; tray_client(const tray_client& c) = default;
tray_client& operator=(tray_client& c) = default; tray_client& operator=(tray_client& c) = default;
~tray_client(); ~tray_client();
uint16_t width() const; uint16_t width() const;
uint16_t height() const; uint16_t height() const;
void clear_window() const; void clear_window() const;
bool match(const xcb_window_t& win) const; bool match(const xcb_window_t& win) const;
bool mapped() const; bool mapped() const;
void mapped(bool state); void mapped(bool state);
xcb_window_t window() const; xcb_window_t window() const;
xembed_data* xembed() const; xembed_data* xembed() const;
void ensure_state() const; void ensure_state() const;
void reconfigure(int16_t x, int16_t y) const; void reconfigure(int16_t x, int16_t y) const;
void configure_notify(int16_t x, int16_t y) const; void configure_notify(int16_t x, int16_t y) const;
protected: protected:
connection& m_connection; connection& m_connection;
xcb_window_t m_window{0}; xcb_window_t m_window{0};
shared_ptr<xembed_data> m_xembed; shared_ptr<xembed_data> m_xembed;
bool m_mapped{false}; bool m_mapped{false};
uint16_t m_width; uint16_t m_width;
uint16_t m_height; uint16_t m_height;
} };
;
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -7,23 +7,23 @@
POLYBAR_NS POLYBAR_NS
namespace xlib { namespace xlib {
shared_ptr<Display> get_display(); namespace detail {
shared_ptr<Visual> get_visual(int screen = 0, uint8_t depth = 32);
Colormap create_colormap(int screen = 0);
/** /**
* RAII wrapper for Xlib display locking * RAII wrapper for Xlib display locking
*/ */
class display_lock { class display_lock {
public: public:
explicit display_lock(shared_ptr<Display>&& display); explicit display_lock(Display* display);
~display_lock(); ~display_lock();
protected: protected:
shared_ptr<Display> m_display; Display* m_display;
}; };
}
Display* get_display();
Visual* get_visual(int screen = 0, uint8_t depth = 32);
Colormap create_colormap(int screen = 0);
inline auto make_display_lock(); inline auto make_display_lock();
} }

View File

@ -12,7 +12,7 @@ class xresource_manager {
using make_type = const xresource_manager&; using make_type = const xresource_manager&;
static make_type make(); static make_type make();
explicit xresource_manager(shared_ptr<Display>&&); explicit xresource_manager(Display*);
~xresource_manager(); ~xresource_manager();
xresource_manager(const xresource_manager& o) = delete; xresource_manager(const xresource_manager& o) = delete;
@ -26,7 +26,7 @@ class xresource_manager {
string load_value(const string& key, const string& res_type, size_t n) const; string load_value(const string& key, const string& res_type, size_t n) const;
private: private:
shared_ptr<Display> m_display; Display* m_display{nullptr};
XrmDatabase m_db; XrmDatabase m_db;
char* m_manager{nullptr}; char* m_manager{nullptr};
}; };

View File

@ -17,8 +17,7 @@ namespace xutils {
} }
}; };
shared_ptr<xcb_connection_t> get_connection(); xcb_connection_t* get_connection();
int get_connection_fd();
void pack_values(uint32_t mask, const uint32_t* src, uint32_t* dest); void pack_values(uint32_t mask, const uint32_t* src, uint32_t* dest);
void pack_values(uint32_t mask, const xcb_params_cw_t* src, uint32_t* dest); void pack_values(uint32_t mask, const xcb_params_cw_t* src, uint32_t* dest);

View File

@ -62,6 +62,9 @@ controller::controller(connection& conn, signal_emitter& emitter, const logger&
throw system_error("Failed to create event channel pipes"); throw system_error("Failed to create event channel pipes");
} }
m_fdevent_rd = file_util::make_file_descriptor(g_eventpipe[PIPE_READ]);
m_fdevent_wr = file_util::make_file_descriptor(g_eventpipe[PIPE_WRITE]);
m_log.trace("controller: Install signal handler"); m_log.trace("controller: Install signal handler");
struct sigaction act {}; struct sigaction act {};
memset(&act, 0, sizeof(act)); memset(&act, 0, sizeof(act));
@ -99,18 +102,13 @@ controller::controller(connection& conn, signal_emitter& emitter, const logger&
throw application_error("Inter-process messaging needs to be enabled"); throw application_error("Inter-process messaging needs to be enabled");
} }
auto module = make_module(move(type), m_bar->settings(), module_name); m_modules[align].emplace_back(make_module(move(type), m_bar->settings(), module_name));
module->set_update_cb([&] { enqueue(make_update_evt(false)); });
module->set_stop_cb([&] { enqueue(make_check_evt()); });
input_handler* module_input_handler{nullptr}; input_handler* module_input_handler{nullptr};
if ((module_input_handler = dynamic_cast<input_handler*>(module)) != nullptr) { if ((module_input_handler = dynamic_cast<input_handler*>(&*m_modules[align].back())) != nullptr) {
m_sig.attach(module_input_handler); m_sig.attach(module_input_handler);
} }
m_modules[align].emplace_back(move(module));
created_modules++; created_modules++;
} catch (const runtime_error& err) { } catch (const runtime_error& err) {
m_log.err("Disabling module \"%s\" (reason: %s)", module_name, err.what()); m_log.err("Disabling module \"%s\" (reason: %s)", module_name, err.what());
@ -157,7 +155,6 @@ bool controller::run(bool writeback) {
m_writeback = writeback; m_writeback = writeback;
m_log.info("Starting application"); m_log.info("Starting application");
m_sig.attach(this);
size_t started_modules{0}; size_t started_modules{0};
for (const auto& block : m_modules) { for (const auto& block : m_modules) {
@ -165,6 +162,8 @@ bool controller::run(bool writeback) {
try { try {
m_log.info("Starting %s", module->name()); m_log.info("Starting %s", module->name());
module->start(); module->start();
module->set_update_cb([&] { enqueue(make_update_evt(false)); });
module->set_stop_cb([&] { enqueue(make_check_evt()); });
started_modules++; started_modules++;
} catch (const application_error& err) { } catch (const application_error& err) {
m_log.err("Failed to start '%s' (reason: %s)", module->name(), err.what()); m_log.err("Failed to start '%s' (reason: %s)", module->name(), err.what());
@ -178,6 +177,8 @@ bool controller::run(bool writeback) {
m_connection.flush(); m_connection.flush();
m_sig.attach(this);
read_events(); read_events();
m_log.warn("Termination signal received, shutting down..."); m_log.warn("Termination signal received, shutting down...");
@ -218,14 +219,13 @@ bool controller::enqueue(string&& input_data) {
* Read events from configured file descriptors * Read events from configured file descriptors
*/ */
void controller::read_events() { void controller::read_events() {
int fd_connection{m_connection.get_file_descriptor()};
int fd_confwatch{0}; int fd_confwatch{0};
int fd_connection{0};
int fd_event{0};
int fd_ipc{0}; int fd_ipc{0};
vector<int> fds; vector<int> fds;
fds.emplace_back((fd_event = g_eventpipe[PIPE_READ])); fds.emplace_back(*m_fdevent_rd);
fds.emplace_back((fd_connection = m_connection.get_file_descriptor())); fds.emplace_back(fd_connection);
if (m_confwatch) { if (m_confwatch) {
m_log.trace("controller: Attach config watch"); m_log.trace("controller: Attach config watch");
@ -237,6 +237,8 @@ void controller::read_events() {
fds.emplace_back((fd_ipc = m_ipc->get_file_descriptor())); fds.emplace_back((fd_ipc = m_ipc->get_file_descriptor()));
} }
m_sig.emit(sig_ev::process_update{make_update_evt(true)});
while (!g_terminate) { while (!g_terminate) {
fd_set readfds{}; fd_set readfds{};
FD_ZERO(&readfds); FD_ZERO(&readfds);
@ -256,10 +258,10 @@ void controller::read_events() {
} }
// Process event on the internal fd // Process event on the internal fd
if (fd_event && FD_ISSET(fd_event, &readfds)) { if (m_fdevent_rd && FD_ISSET(*m_fdevent_rd, &readfds)) {
process_eventqueue(); process_eventqueue();
char buffer[BUFSIZ]{'\0'}; char buffer[BUFSIZ]{'\0'};
if (read(fd_event, &buffer, BUFSIZ) == -1) { if (read(*m_fdevent_rd, &buffer, BUFSIZ) == -1) {
m_log.err("Failed to read from eventpipe (err: %s)", strerror(errno)); m_log.err("Failed to read from eventpipe (err: %s)", strerror(errno));
} }
} }
@ -273,14 +275,17 @@ void controller::read_events() {
// Process event on the xcb connection fd // Process event on the xcb connection fd
if (fd_connection && FD_ISSET(fd_connection, &readfds)) { if (fd_connection && FD_ISSET(fd_connection, &readfds)) {
shared_ptr<xcb_generic_event_t> evt{};
while ((evt = shared_ptr<xcb_generic_event_t>(xcb_poll_for_event(m_connection), free)) != nullptr) {
try { try {
m_connection.dispatch_event(m_connection.wait_for_event()); m_connection.dispatch_event(evt);
} catch (xpp::connection_error& err) { } catch (xpp::connection_error& err) {
m_log.err("X connection error, terminating... (what: %s)", m_connection.error_str(err.code())); m_log.err("X connection error, terminating... (what: %s)", m_connection.error_str(err.code()));
} catch (const exception& err) { } catch (const exception& err) {
m_log.err("Error in X event loop: %s", err.what()); m_log.err("Error in X event loop: %s", err.what());
} }
} }
}
// Process event on the ipc fd // Process event on the ipc fd
if (fd_ipc && FD_ISSET(fd_ipc, &readfds)) { if (fd_ipc && FD_ISSET(fd_ipc, &readfds)) {

View File

@ -40,6 +40,8 @@ ipc::ipc(signal_emitter& emitter, const logger& logger) : m_sig(emitter), m_log(
* Deconstruct ipc handler * Deconstruct ipc handler
*/ */
ipc::~ipc() { ipc::~ipc() {
m_fd.reset();
if (!m_path.empty()) { if (!m_path.empty()) {
m_log.trace("ipc: Removing file handle"); m_log.trace("ipc: Removing file handle");
unlink(m_path.c_str()); unlink(m_path.c_str());
@ -55,7 +57,7 @@ void ipc::receive_message() {
char buffer[BUFSIZ]{'\0'}; char buffer[BUFSIZ]{'\0'};
ssize_t bytes_read{0}; ssize_t bytes_read{0};
if ((bytes_read = read(*m_fd.get(), &buffer, BUFSIZ)) == -1) { if ((bytes_read = read(*m_fd, &buffer, BUFSIZ)) == -1) {
m_log.err("Failed to read from ipc channel (err: %s)", strerror(errno)); m_log.err("Failed to read from ipc channel (err: %s)", strerror(errno));
} }
@ -88,7 +90,7 @@ void ipc::receive_message() {
* Get the file descriptor to the ipc channel * Get the file descriptor to the ipc channel
*/ */
int ipc::get_file_descriptor() const { int ipc::get_file_descriptor() const {
return *m_fd.get(); return *m_fd;
} }
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -164,6 +164,7 @@ void parser::codeblock(string&& data, const bar_settings& bar) {
size_t parser::text(string&& data) { size_t parser::text(string&& data) {
const uint8_t* utf{reinterpret_cast<const uint8_t*>(&data[0])}; const uint8_t* utf{reinterpret_cast<const uint8_t*>(&data[0])};
// clang-format off
if (utf[0] < 0x80) { if (utf[0] < 0x80) {
size_t pos{0}; size_t pos{0};
@ -188,23 +189,27 @@ size_t parser::text(string&& data) {
if (pos > 0) { if (pos > 0) {
return pos; return pos;
} }
} else if ((utf[0] & 0xe0) == 0xc0) { // 2 byte utf-8 sequence } else if ((utf[0] & 0xe0) == 0xc0) { // 2 byte utf-8 sequence
m_sig.emit(write_text_unicode{static_cast<uint16_t>((utf[0] & 0x1f) << 6 | (utf[1] & 0x3f))}); m_sig.emit(write_text_unicode{static_cast<uint16_t>(((utf[0] & 0x1f) << 6) | (utf[1] & 0x3f))});
return 2; return 2;
} else if ((utf[0] & 0xf0) == 0xe0) { // 3 byte utf-8 sequence } else if ((utf[0] & 0xf0) == 0xe0) { // 3 byte utf-8 sequence
m_sig.emit( m_sig.emit(write_text_unicode{static_cast<uint16_t>(((utf[0] & 0x0f) << 12) | ((utf[1] & 0x3f) << 6) | (utf[2] & 0x3f))});
write_text_unicode{static_cast<uint16_t>((utf[0] & 0xf) << 12 | (utf[1] & 0x3f) << 6 | (utf[2] & 0x3f))});
return 3; return 3;
} else if ((utf[0] & 0xf8) == 0xf0) { // 4 byte utf-8 sequence } else if ((utf[0] & 0xf8) == 0xf0) { // 4 byte utf-8 sequence
// m_sig.emit(write_text_unicode{((utf[0] & 0x07) << 18) | ((utf[1] & 0x3f) << 12) | ((utf[2] & 0x3f) << 6) | (utf[3] & 0x3f)});
m_sig.emit(write_text_unicode{static_cast<uint16_t>(0xfffd)}); m_sig.emit(write_text_unicode{static_cast<uint16_t>(0xfffd)});
return 4; return 4;
} else if ((utf[0] & 0xfc) == 0xf8) { // 5 byte utf-8 sequence } else if ((utf[0] & 0xfc) == 0xf8) { // 5 byte utf-8 sequence
// m_sig.emit(write_text_unicode{((utf[0] & 0x03) << 24) | ((utf[1] & 0x3f) << 18) | ((utf[2] & 0x3f) << 12) | ((utf[3] & 0x3f) << 6) | (utf[4] & 0x3f)});
m_sig.emit(write_text_unicode{static_cast<uint16_t>(0xfffd)}); m_sig.emit(write_text_unicode{static_cast<uint16_t>(0xfffd)});
return 5; return 5;
} else if ((utf[0] & 0xfe) == 0xfc) { // 6 byte utf-8 sequence } else if ((utf[0] & 0xfe) == 0xfc) { // 6 byte utf-8 sequence
// m_sig.emit(write_text_unicode{((utf[0] & 0x01) << 30) | ((utf[1] & 0x3f) << 24) | ((utf[2] & 0x3f) << 18) | ((utf[3] & 0x3f) << 12) | ((utf[4] & 0x3f) << 6) | (utf[5] & 0x3f)});
m_sig.emit(write_text_unicode{static_cast<uint16_t>(0xfffd)}); m_sig.emit(write_text_unicode{static_cast<uint16_t>(0xfffd)});
return 6; return 6;
} }
// clang-format on
if (utf[0] < 0x80) { if (utf[0] < 0x80) {
m_sig.emit(write_text_ascii{utf[0]}); m_sig.emit(write_text_ascii{utf[0]});

View File

@ -404,7 +404,9 @@ void renderer::draw_textstring(const uint16_t* text, size_t len) {
auto y = m_rect.height / 2 + font->height / 2 - font->descent + font->offset_y; auto y = m_rect.height / 2 + font->height / 2 - font->descent + font->offset_y;
if (font->ptr != XCB_NONE && m_gcfont != font->ptr) { if (font->ptr != XCB_NONE && m_gcfont != font->ptr) {
m_fontmanager->set_gcontext_font(font, m_gcontexts.at(gc::FG), &m_gcfont); const uint32_t v[1]{font->ptr};
m_connection.change_gc(m_gcontexts.at(gc::FG), XCB_GC_FONT, v);
m_gcfont = font->ptr;
} }
m_fontmanager->drawtext(font, m_pixmap, m_gcontexts.at(gc::FG), x, y, chars.data(), chars.size()); m_fontmanager->drawtext(font, m_pixmap, m_gcontexts.at(gc::FG), x, y, chars.data(), chars.size());

View File

@ -58,7 +58,7 @@ screen::screen(connection& conn, signal_emitter& emitter, const logger& logger,
// Wait until the proxy window has been mapped // Wait until the proxy window has been mapped
using evt = xcb_map_notify_event_t; using evt = xcb_map_notify_event_t;
m_connection.wait_for_response<evt, XCB_MAP_NOTIFY>([&](const evt& evt) -> bool { return evt.window == m_proxy; }); m_connection.wait_for_response<evt, XCB_MAP_NOTIFY>([&](const evt* evt) -> bool { return evt->window == m_proxy; });
m_connection.clear_event_mask(m_root); m_connection.clear_event_mask(m_root);
// Finally attach the sink the process randr events // Finally attach the sink the process randr events

View File

@ -47,14 +47,14 @@ int main(int argc, char** argv) {
XInitThreads(); XInitThreads();
// Store the xcb connection pointer with a disconnect deleter // Store the xcb connection pointer with a disconnect deleter
shared_ptr<xcb_connection_t> xcbconn{xutils::get_connection().get(), xutils::xcb_connection_deleter{}}; shared_ptr<xcb_connection_t> xcbconn{xutils::get_connection(), xutils::xcb_connection_deleter{}};
if (!xcbconn) { if (!xcbconn) {
logger.err("A connection to X could not be established... "); logger.err("A connection to X could not be established... ");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
connection& conn{connection::make(xcbconn.get())}; connection& conn{connection::make(&*xcbconn)};
conn.preload_atoms(); conn.preload_atoms();
conn.query_extensions(); conn.query_extensions();

View File

@ -114,7 +114,7 @@ namespace modules {
* charging animation when the module is started * charging animation when the module is started
*/ */
void battery_module::start() { void battery_module::start() {
inotify_module::start(); this->inotify_module::start();
m_threads.emplace_back(thread(&battery_module::subthread, this)); m_threads.emplace_back(thread(&battery_module::subthread, this));
} }
@ -145,7 +145,7 @@ namespace modules {
} }
} }
inotify_module::idle(); this->inotify_module::idle();
} }
/** /**

View File

@ -13,15 +13,12 @@ POLYBAR_NS
/** /**
* Create instance * Create instance
*/ */
connection::make_type connection::make(xcb_connection_t* conn, int conn_fd) { connection::make_type connection::make(xcb_connection_t* conn) {
if (conn == nullptr) { if (conn == nullptr) {
conn = xutils::get_connection().get(); conn = &*xutils::get_connection();
}
if (conn_fd == 0) {
conn_fd = xutils::get_connection_fd();
} }
return static_cast<connection::make_type>( return static_cast<connection::make_type>(
*factory_util::singleton<std::remove_reference_t<connection::make_type>>(conn, conn_fd)); *factory_util::singleton<std::remove_reference_t<connection::make_type>>(conn, xcb_get_file_descriptor(conn)));
} }
/** /**
@ -109,7 +106,7 @@ void connection::clear_event_mask(xcb_window_t win) {
* Creates an instance of shared_ptr<xcb_client_message_event_t> * Creates an instance of shared_ptr<xcb_client_message_event_t>
*/ */
shared_ptr<xcb_client_message_event_t> connection::make_client_message(xcb_atom_t type, xcb_window_t target) const { shared_ptr<xcb_client_message_event_t> connection::make_client_message(xcb_atom_t type, xcb_window_t target) const {
auto client_message = memory_util::make_malloc_ptr<xcb_client_message_event_t>(size_t{32}); auto client_message = memory_util::make_malloc_ptr<xcb_client_message_event_t, 32_z>();
client_message->response_type = XCB_CLIENT_MESSAGE; client_message->response_type = XCB_CLIENT_MESSAGE;
client_message->format = 32; client_message->format = 32;
@ -131,8 +128,7 @@ shared_ptr<xcb_client_message_event_t> connection::make_client_message(xcb_atom_
*/ */
void connection::send_client_message(const shared_ptr<xcb_client_message_event_t>& message, xcb_window_t target, void connection::send_client_message(const shared_ptr<xcb_client_message_event_t>& message, xcb_window_t target,
uint32_t event_mask, bool propagate) const { uint32_t event_mask, bool propagate) const {
const char* data = reinterpret_cast<decltype(data)>(message.get()); send_event(propagate, target, event_mask, reinterpret_cast<const char*>(&*message));
send_event(propagate, target, event_mask, data);
flush(); flush();
} }
@ -184,8 +180,8 @@ string connection::error_str(int error_code) {
/** /**
* Dispatch event through the registry * Dispatch event through the registry
*/ */
void connection::dispatch_event(shared_ptr<xcb_generic_event_t>&& evt) const { void connection::dispatch_event(const shared_ptr<xcb_generic_event_t>& evt) const {
m_registry.dispatch(forward<decltype(evt)>(evt)); m_registry.dispatch(evt);
} }
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -1,9 +1,5 @@
#include <xcb/xcbext.h>
#include "utils/string.hpp"
#include "x11/color.hpp"
#include "x11/connection.hpp"
#include "x11/draw.hpp" #include "x11/draw.hpp"
#include "x11/connection.hpp"
POLYBAR_NS POLYBAR_NS
@ -21,44 +17,6 @@ namespace draw_util {
void fill(xcb_connection_t* c, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w, uint16_t h) { void fill(xcb_connection_t* c, xcb_drawable_t d, xcb_gcontext_t g, int16_t x, int16_t y, uint16_t w, uint16_t h) {
fill(c, d, g, {x, y, w, h}); fill(c, d, g, {x, y, w, h});
} }
/**
* The xcb version of this function does not compose the correct request
*
* 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) {
static const xcb_protocol_request_t xcb_req = {
5, // count
nullptr, // ext
XCB_POLY_TEXT_16, // opcode
1 // isvoid
};
struct iovec xcb_parts[7];
uint8_t xcb_lendelta[2];
xcb_void_cookie_t xcb_ret{};
xcb_poly_text_8_request_t xcb_out{};
xcb_out.pad0 = 0;
xcb_out.drawable = d;
xcb_out.gc = gc;
xcb_out.x = x;
xcb_out.y = y;
xcb_lendelta[0] = len;
xcb_lendelta[1] = 0;
xcb_parts[2].iov_base = reinterpret_cast<char*>(&xcb_out);
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = nullptr;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
xcb_parts[4].iov_base = xcb_lendelta;
xcb_parts[4].iov_len = sizeof(xcb_lendelta);
xcb_parts[5].iov_base = reinterpret_cast<char*>(str);
xcb_parts[5].iov_len = len * sizeof(int16_t);
xcb_parts[6].iov_base = nullptr;
xcb_parts[6].iov_len = -(xcb_parts[4].iov_len + xcb_parts[5].iov_len) & 3;
xcb_ret.sequence = xcb_send_request(conn, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
} }
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -5,18 +5,15 @@
POLYBAR_NS POLYBAR_NS
namespace ewmh_util { namespace ewmh_util {
ewmh_connection_t g_ewmh_connection{nullptr}; ewmh_connection_t g_connection{nullptr};
ewmh_connection_t initialize() { ewmh_connection_t initialize() {
if (!g_ewmh_connection) { if (!g_connection) {
g_ewmh_connection = memory_util::make_malloc_ptr<xcb_ewmh_connection_t>( g_connection = memory_util::make_malloc_ptr<xcb_ewmh_connection_t>(
sizeof(xcb_ewmh_connection_t), [=](xcb_ewmh_connection_t* c) { xcb_ewmh_connection_wipe(c); }); [=](xcb_ewmh_connection_t* c) { xcb_ewmh_connection_wipe(c); });
xcb_ewmh_init_atoms_replies(
auto* conn = g_ewmh_connection.get(); &*g_connection, xcb_ewmh_init_atoms(xutils::get_connection(), &*g_connection), nullptr);
xcb_ewmh_init_atoms_replies(conn, xcb_ewmh_init_atoms(xutils::get_connection().get(), conn), nullptr);
} }
return g_connection;
return g_ewmh_connection;
} }
bool supports(xcb_ewmh_connection_t* ewmh, xcb_atom_t atom, int screen) { bool supports(xcb_ewmh_connection_t* ewmh, xcb_atom_t atom, int screen) {

View File

@ -18,10 +18,10 @@ void font_ref::_deleter::operator()(font_ref* font) {
font->width_lut.clear(); font->width_lut.clear();
if (font->xft != nullptr) { if (font->xft != nullptr) {
XftFontClose(xlib::get_display().get(), font->xft); XftFontClose(&*xlib::get_display(), font->xft);
} }
if (font->ptr != XCB_NONE) { if (font->ptr != XCB_NONE) {
xcb_close_font(xutils::get_connection().get(), font->ptr); xcb_close_font(&*xutils::get_connection(), font->ptr);
} }
delete font; delete font;
} }
@ -34,8 +34,7 @@ font_manager::make_type font_manager::make() {
connection::make(), logger::make(), xlib::get_display(), xlib::get_visual(), xlib::create_colormap()); connection::make(), logger::make(), xlib::get_display(), xlib::get_visual(), xlib::create_colormap());
} }
font_manager::font_manager( font_manager::font_manager(connection& conn, const logger& logger, Display* dsp, Visual* vis, Colormap&& cm)
connection& conn, const logger& logger, shared_ptr<Display>&& dsp, shared_ptr<Visual>&& vis, Colormap&& cm)
: m_connection(conn) : m_connection(conn)
, m_logger(logger) , m_logger(logger)
, m_display(forward<decltype(dsp)>(dsp)) , m_display(forward<decltype(dsp)>(dsp))
@ -50,14 +49,14 @@ font_manager::~font_manager() {
cleanup(); cleanup();
if (m_display) { if (m_display) {
if (m_xftcolor_allocated) { if (m_xftcolor_allocated) {
XftColorFree(m_display.get(), m_visual.get(), m_colormap, &m_xftcolor); XftColorFree(m_display, m_visual, m_colormap, &m_xftcolor);
} }
XFreeColormap(m_display.get(), m_colormap); XFreeColormap(m_display, m_colormap);
} }
} }
void font_manager::set_visual(shared_ptr<Visual>&& v) { void font_manager::set_visual(Visual* v) {
m_visual = forward<decltype(v)>(v); m_visual = v;
} }
void font_manager::cleanup() { void font_manager::cleanup() {
@ -90,7 +89,7 @@ bool font_manager::load(const string& name, uint8_t fontindex, int8_t offset_y)
} }
if (font->ptr == XCB_NONE && if (font->ptr == XCB_NONE &&
(font->xft = XftFontOpenName(m_display.get(), m_connection.default_screen(), name.c_str())) != nullptr) { (font->xft = XftFontOpenName(m_display, m_connection.default_screen(), name.c_str())) != nullptr) {
font->ascent = font->xft->ascent; font->ascent = font->xft->ascent;
font->descent = font->xft->descent; font->descent = font->xft->descent;
font->height = font->ascent + font->descent; font->height = font->ascent + font->descent;
@ -174,16 +173,16 @@ uint8_t font_manager::glyph_width(const shared_ptr<font_ref>& font, const uint16
void font_manager::drawtext(const shared_ptr<font_ref>& font, xcb_pixmap_t pm, xcb_gcontext_t gc, int16_t x, int16_t y, void font_manager::drawtext(const shared_ptr<font_ref>& font, xcb_pixmap_t pm, xcb_gcontext_t gc, int16_t x, int16_t y,
const uint16_t* chars, size_t num_chars) { const uint16_t* chars, size_t num_chars) {
if (m_xftdraw == nullptr) { if (m_xftdraw == nullptr) {
m_xftdraw = XftDrawCreate(m_display.get(), pm, m_visual.get(), m_colormap); m_xftdraw = XftDrawCreate(m_display, pm, m_visual, m_colormap);
} }
if (font->xft != nullptr) { if (font->xft != nullptr) {
XftDrawString16(m_xftdraw, &m_xftcolor, font->xft, x, y, chars, num_chars); XftDrawString16(m_xftdraw, &m_xftcolor, font->xft, x, y, chars, num_chars);
} else if (font->ptr != XCB_NONE) { } else if (font->ptr != XCB_NONE) {
uint16_t* ucs = static_cast<uint16_t*>(calloc(num_chars, sizeof(uint16_t))); vector<uint16_t> ucs(num_chars);
for (size_t i = 0; i < num_chars; i++) { for (size_t i = 0; i < num_chars; i++) {
ucs[i] = ((chars[i] >> 8) | (chars[i] << 8)); ucs[i] = (chars[i] >> 8) | (chars[i] << 8);
} }
draw_util::xcb_poly_text_16_patched(m_connection, pm, gc, x, y, num_chars, ucs); xcb_poly_text_16(pm, gc, x, y, num_chars, ucs.data());
} }
} }
@ -200,20 +199,14 @@ void font_manager::allocate_color(uint32_t color) {
void font_manager::allocate_color(XRenderColor color) { void font_manager::allocate_color(XRenderColor color) {
if (m_xftcolor_allocated) { if (m_xftcolor_allocated) {
XftColorFree(m_display.get(), m_visual.get(), m_colormap, &m_xftcolor); XftColorFree(m_display, m_visual, m_colormap, &m_xftcolor);
} }
if (!(m_xftcolor_allocated = XftColorAllocValue(m_display.get(), m_visual.get(), m_colormap, &color, &m_xftcolor))) { if (!(m_xftcolor_allocated = XftColorAllocValue(m_display, m_visual, m_colormap, &color, &m_xftcolor))) {
m_logger.err("Failed to allocate color"); m_logger.err("Failed to allocate color");
} }
} }
void font_manager::set_gcontext_font(const shared_ptr<font_ref>& font, xcb_gcontext_t gc, xcb_font_t* xcb_font) {
const uint32_t val[1]{*xcb_font};
m_connection.change_gc(gc, XCB_GC_FONT, val);
*xcb_font = font->ptr;
}
bool font_manager::open_xcb_font(const shared_ptr<font_ref>& font, string fontname) { bool font_manager::open_xcb_font(const shared_ptr<font_ref>& font, string fontname) {
try { try {
uint32_t font_id{m_connection.generate_id()}; uint32_t font_id{m_connection.generate_id()};
@ -253,11 +246,11 @@ uint8_t font_manager::glyph_width_xft(const shared_ptr<font_ref>& font, const ui
} }
XGlyphInfo extents{}; XGlyphInfo extents{};
FT_UInt glyph{XftCharIndex(m_display.get(), font->xft, static_cast<FcChar32>(chr))}; FT_UInt glyph{XftCharIndex(m_display, font->xft, static_cast<FcChar32>(chr))};
XftFontLoadGlyphs(m_display.get(), font->xft, FcFalse, &glyph, 1); XftFontLoadGlyphs(m_display, font->xft, FcFalse, &glyph, 1);
XftGlyphExtents(m_display.get(), font->xft, &glyph, 1, &extents); XftGlyphExtents(m_display, font->xft, &glyph, 1, &extents);
XftFontUnloadGlyphs(m_display.get(), font->xft, &glyph, 1); XftFontUnloadGlyphs(m_display, font->xft, &glyph, 1);
font->glyph_widths.emplace_hint(it, chr, extents.xOff); //.emplace_back(chr, extents.xOff); font->glyph_widths.emplace_hint(it, chr, extents.xOff); //.emplace_back(chr, extents.xOff);
@ -277,7 +270,7 @@ uint8_t font_manager::glyph_width_xcb(const shared_ptr<font_ref>& font, const ui
bool font_manager::has_glyph_xft(const shared_ptr<font_ref>& font, const uint16_t chr) { bool font_manager::has_glyph_xft(const shared_ptr<font_ref>& font, const uint16_t chr) {
if (!font || font->xft == nullptr) { if (!font || font->xft == nullptr) {
return false; return false;
} else if (XftCharExists(m_display.get(), font->xft, static_cast<FcChar32>(chr)) == FcFalse) { } else if (XftCharExists(m_display, font->xft, static_cast<FcChar32>(chr)) == FcFalse) {
return false; return false;
} else { } else {
return true; return true;
@ -298,4 +291,23 @@ bool font_manager::has_glyph_xcb(const shared_ptr<font_ref>& font, const uint16_
} }
} }
void font_manager::xcb_poly_text_16(
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, nullptr, XCB_POLY_TEXT_16, 1};
xcb_poly_text_16_request_t req{XCB_POLY_TEXT_16, 0, len, d, gc, x, y};
uint8_t xcb_lendelta[2]{len, 0};
struct iovec xcb_parts[7]{};
xcb_parts[2].iov_base = reinterpret_cast<char*>(&req);
xcb_parts[2].iov_len = sizeof(req);
xcb_parts[3].iov_base = nullptr;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
xcb_parts[4].iov_base = xcb_lendelta;
xcb_parts[4].iov_len = sizeof(xcb_lendelta);
xcb_parts[5].iov_base = reinterpret_cast<char*>(str);
xcb_parts[5].iov_len = len * sizeof(int16_t);
xcb_parts[6].iov_base = nullptr;
xcb_parts[6].iov_len = -(xcb_parts[4].iov_len + xcb_parts[5].iov_len) & 3;
xcb_send_request(m_connection, 0, xcb_parts + 2, &xcb_req);
}
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -103,7 +103,7 @@ void tray_client::reconfigure(int16_t x, int16_t y) const {
* Respond to client resize requests * Respond to client resize requests
*/ */
void tray_client::configure_notify(int16_t x, int16_t y) const { void tray_client::configure_notify(int16_t x, int16_t y) const {
auto notify = memory_util::make_malloc_ptr<xcb_configure_notify_event_t>(32); auto notify = memory_util::make_malloc_ptr<xcb_configure_notify_event_t, 32_z>();
notify->response_type = XCB_CONFIGURE_NOTIFY; notify->response_type = XCB_CONFIGURE_NOTIFY;
notify->event = m_window; notify->event = m_window;
notify->window = m_window; notify->window = m_window;

View File

@ -222,13 +222,16 @@ void tray_manager::activate() {
// notify clients waiting for a manager. // notify clients waiting for a manager.
acquire_selection(); acquire_selection();
if (!m_acquired_selection) {
deactivate();
return;
}
// Send delayed notification // Send delayed notification
if (!m_firstactivation) { if (!m_firstactivation) {
notify_clients_delayed();
} else if (m_othermanager != XCB_NONE && m_othermanager != m_tray) {
notify_clients_delayed();
} else {
notify_clients(); notify_clients();
} else {
notify_clients_delayed();
} }
m_firstactivation = false; m_firstactivation = false;
@ -679,7 +682,6 @@ void tray_manager::set_tray_colors() {
*/ */
void tray_manager::acquire_selection() { void tray_manager::acquire_selection() {
m_othermanager = XCB_NONE; m_othermanager = XCB_NONE;
;
xcb_window_t owner; xcb_window_t owner;
try { try {
@ -691,21 +693,17 @@ void tray_manager::acquire_selection() {
if (owner == m_tray) { if (owner == m_tray) {
m_log.trace("tray: Already managing the systray selection"); m_log.trace("tray: Already managing the systray selection");
m_acquired_selection = true; m_acquired_selection = true;
return; } else if ((m_othermanager = owner) != XCB_NONE) {
} m_log.warn("Systray selection already managed (window=%s)", m_connection.id(owner));
track_selection_owner(m_othermanager);
if ((m_othermanager = owner) != XCB_NONE) { } else {
m_log.info("Replacing selection manager %s", m_connection.id(owner));
}
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));
m_connection.set_selection_owner_checked(m_tray, m_atom, XCB_CURRENT_TIME); m_connection.set_selection_owner_checked(m_tray, m_atom, XCB_CURRENT_TIME);
if (m_connection.get_selection_owner_unchecked(m_atom)->owner != m_tray) { if (m_connection.get_selection_owner_unchecked(m_atom)->owner != m_tray) {
throw application_error("Failed to get control of the systray selection"); throw application_error("Failed to get control of the systray selection");
} }
m_acquired_selection = true; m_acquired_selection = true;
}
} }
/** /**
@ -1072,7 +1070,7 @@ void tray_manager::handle(const evt::destroy_notify& evt) {
if (m_activated && evt->window == m_tray) { if (m_activated && evt->window == m_tray) {
deactivate(); deactivate();
} else if (!m_activated && evt->window == m_othermanager) { } else if (!m_activated && evt->window == m_othermanager) {
m_log.info("Tray selection available... re-activating"); m_log.info("Systray selection unmanaged... re-activating");
activate(); activate();
} else if (m_activated && is_embedded(evt->window)) { } else if (m_activated && is_embedded(evt->window)) {
m_log.trace("tray: Received destroy_notify for client, remove..."); m_log.trace("tray: Received destroy_notify for client, remove...");

View File

@ -1,44 +1,43 @@
#include <X11/X.h>
#include "x11/xlib.hpp" #include "x11/xlib.hpp"
#include "utils/factory.hpp" #include "utils/factory.hpp"
POLYBAR_NS POLYBAR_NS
namespace xlib { namespace xlib {
shared_ptr<Display> g_display_ptr; namespace detail {
shared_ptr<Visual> g_visual_ptr; display_lock::display_lock(Display* display) : m_display(forward<decltype(display)>(display)) {
XLockDisplay(m_display);
shared_ptr<Display> get_display() {
if (!g_display_ptr) {
g_display_ptr = shared_ptr<Display>(XOpenDisplay(nullptr), factory_util::null_deleter);
}
return g_display_ptr;
}
shared_ptr<Visual> get_visual(int screen, uint8_t depth) {
if (!g_visual_ptr) {
XVisualInfo info{};
if (XMatchVisualInfo(get_display().get(), screen, depth, TrueColor, &info)) {
g_visual_ptr = shared_ptr<Visual>(info.visual, [=](Visual* v) { XFree(v); });
}
}
return g_visual_ptr;
}
Colormap create_colormap(int screen) {
return XDefaultColormap(get_display().get(), screen);
}
display_lock::display_lock(shared_ptr<Display>&& display) : m_display(forward<decltype(display)>(display)) {
XLockDisplay(m_display.get());
} }
display_lock::~display_lock() { display_lock::~display_lock() {
XUnlockDisplay(m_display.get()); XUnlockDisplay(m_display);
}
}
Display* get_display() {
static Display* display{XOpenDisplay(nullptr)};
return display;
}
Visual* get_visual(int screen, uint8_t depth) {
static shared_ptr<Visual> visual;
if (!visual) {
XVisualInfo info{};
if (XMatchVisualInfo(get_display(), screen, depth, TrueColor, &info)) {
visual = shared_ptr<Visual>(info.visual, [=](Visual* v) { XFree(v); });
}
}
return &*visual;
}
Colormap create_colormap(int screen) {
return XDefaultColormap(get_display(), screen);
} }
inline auto make_display_lock() { inline auto make_display_lock() {
return make_unique<display_lock>(get_display()); return make_unique<detail::display_lock>(get_display());
} }
} }

View File

@ -19,10 +19,10 @@ xresource_manager::make_type xresource_manager::make() {
/** /**
* Construct manager instance * Construct manager instance
*/ */
xresource_manager::xresource_manager(shared_ptr<Display>&& dsp) : m_display(forward<decltype(dsp)>(dsp)) { xresource_manager::xresource_manager(Display* dsp) : m_display(forward<decltype(dsp)>(dsp)) {
XrmInitialize(); XrmInitialize();
if ((m_manager = XResourceManagerString(m_display.get())) != nullptr) { if ((m_manager = XResourceManagerString(m_display)) != nullptr) {
m_db = XrmGetStringDatabase(m_manager); m_db = XrmGetStringDatabase(m_manager);
} }
} }

View File

@ -10,29 +10,13 @@
POLYBAR_NS POLYBAR_NS
namespace xutils { namespace xutils {
shared_ptr<int> g_connection_fd; xcb_connection_t* get_connection() {
shared_ptr<xcb_connection_t> g_connection_ptr; static xcb_connection_t* connection;
if (!connection) {
shared_ptr<xcb_connection_t> get_connection() { XSetEventQueueOwner(xlib::get_display(), XCBOwnsEventQueue);
if (!g_connection_ptr) { connection = XGetXCBConnection(xlib::get_display());
shared_ptr<Display> dsp{xlib::get_display()};
if (dsp) {
XSetEventQueueOwner(dsp.get(), XCBOwnsEventQueue);
g_connection_ptr = shared_ptr<xcb_connection_t>(XGetXCBConnection(dsp.get()), factory_util::null_deleter);
} }
} return connection;
return g_connection_ptr;
}
int get_connection_fd() {
if (!g_connection_fd) {
auto fd = xcb_get_file_descriptor(get_connection().get());
g_connection_fd = shared_ptr<int>(new int{fd}, factory_util::fd_deleter);
}
return *g_connection_fd.get();
} }
void pack_values(uint32_t mask, const uint32_t* src, uint32_t* dest) { void pack_values(uint32_t mask, const uint32_t* src, uint32_t* dest) {
@ -56,12 +40,11 @@ namespace xutils {
} }
void visibility_notify(connection& conn, const xcb_window_t& win, xcb_visibility_t state) { void visibility_notify(connection& conn, const xcb_window_t& win, xcb_visibility_t state) {
auto notify = memory_util::make_malloc_ptr<xcb_visibility_notify_event_t>(32); auto notify = memory_util::make_malloc_ptr<xcb_visibility_notify_event_t, 32_z>();
notify->response_type = XCB_VISIBILITY_NOTIFY; notify->response_type = XCB_VISIBILITY_NOTIFY;
notify->window = win; notify->window = win;
notify->state = state; notify->state = state;
const char* data = reinterpret_cast<const char*>(notify.get()); conn.send_event(true, win, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char*>(&*notify));
conn.send_event(true, win, XCB_EVENT_MASK_NO_EVENT, data);
} }
void compton_shadow_exclude(connection& conn, const xcb_window_t& win) { void compton_shadow_exclude(connection& conn, const xcb_window_t& win) {