summaryrefslogtreecommitdiff
path: root/src/xcb_colors.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/xcb_colors.cc')
-rw-r--r--src/xcb_colors.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/xcb_colors.cc b/src/xcb_colors.cc
new file mode 100644
index 0000000..f4caca4
--- /dev/null
+++ b/src/xcb_colors.cc
@@ -0,0 +1,93 @@
+#include "common.hh"
+
+#include "xcb_colors.hh"
+#include "xcb_connection.hh"
+#include "xcb_event.hh"
+
+#include <map>
+#include <vector>
+#include <xcb/xproto.h>
+
+namespace xcb {
+
+namespace {
+
+class ColorsImpl : public Colors {
+public:
+ ColorsImpl(shared_conn conn, xcb_colormap_t colormap)
+ : conn_(conn), colormap_(colormap),
+ storage_(std::make_shared<StorageImpl>()) {}
+
+ Color get_with_fallback(uint8_t r, uint8_t g, uint8_t b,
+ uint32_t fallback) override {
+ auto key = make_key(r, g, b);
+ auto it = index_.find(key);
+ size_t index;
+ if (it == index_.end()) {
+ index = cookie_.size();
+ cookie_.push_back(xcb_alloc_color(conn_.get(), colormap_,
+ static_cast<uint16_t>(r) << 8,
+ static_cast<uint16_t>(g) << 8,
+ static_cast<uint16_t>(b) << 8));
+ fallback_.push_back(fallback);
+ index_.emplace(key, index);
+ } else {
+ index = it->second;
+ }
+ return Color(storage_, index);
+ }
+
+ bool sync() override {
+ std::vector<uint32_t> colors;
+ colors.reserve(cookie_.size());
+ for (size_t i = 0; i < cookie_.size(); ++i) {
+ xcb::reply<xcb_alloc_color_reply_t> reply(
+ xcb_alloc_color_reply(conn_.get(), cookie_[i], nullptr));
+ if (reply) {
+ colors.push_back(reply->pixel);
+ } else {
+ colors.push_back(fallback_[i]);
+ }
+ }
+ storage_->set(std::move(colors));
+ return true;
+ }
+
+private:
+ class StorageImpl : public Storage {
+ public:
+ uint32_t get(size_t id) const override {
+ assert(id < resolved_.size());
+ return resolved_[id];
+ }
+
+ void set(std::vector<uint32_t> resolved) {
+ resolved_ = std::move(resolved);
+ }
+
+ private:
+ std::vector<uint32_t> resolved_;
+ };
+
+ static uint32_t make_key(uint8_t r, uint8_t g, uint8_t b) {
+ return static_cast<uint32_t>(r) << 16 |
+ static_cast<uint32_t>(g) << 8 | b;
+ }
+
+ shared_conn conn_;
+ xcb_colormap_t colormap_;
+ std::map<uint32_t, size_t> index_;
+ std::vector<xcb_alloc_color_cookie_t> cookie_;
+ std::vector<uint32_t> fallback_;
+ std::shared_ptr<StorageImpl> storage_;
+};
+
+} // namespace
+
+std::unique_ptr<Colors> Colors::create(shared_conn conn,
+ xcb_colormap_t colormap) {
+ return std::make_unique<ColorsImpl>(conn, colormap);
+}
+
+} // namespace xcb
+