feat: init repo

This commit is contained in:
Alexis
2018-08-08 23:54:58 +02:00
parent 53ff4e0d60
commit fcb6a9aa8b
22 changed files with 2634 additions and 0 deletions

30
include/bar.hpp Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <gtkmm.h>
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
namespace waybar {
struct Client;
struct Bar {
Bar(Client& client, std::unique_ptr<struct wl_output *>&& output);
Bar(const Bar&) = delete;
Client& client;
Gtk::Window window;
struct wl_surface *surface;
struct zwlr_layer_surface_v1 *layer_surface;
std::unique_ptr<struct wl_output *> output;
bool visible = true;
auto set_width(int) -> void;
auto toggle() -> void;
private:
auto setup_widgets() -> void;
auto setup_css() -> void;
int width = 10;
Glib::RefPtr<Gtk::StyleContext> style_context;
Glib::RefPtr<Gtk::CssProvider> css_provider;
};
}

43
include/client.hpp Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <iostream>
#include <fmt/format.h>
#include <gdk/gdk.h>
#include <gtkmm.h>
#include <wayland-client.h>
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "util/ptr_vec.hpp"
#include <gdk/gdkwayland.h>
#include "bar.hpp"
namespace waybar {
struct Client {
uint32_t height = 30;
std::string css_file = "./resources/style.css";
Gtk::Main gtk_main;
Glib::RefPtr<Gdk::Display> gdk_display;
struct wl_display *wlDisplay;
struct wl_registry *registry;
struct zwlr_layer_shell_v1 *layer_shell;
util::ptr_vec<Bar> bars;
struct {
sigc::signal<void(int, int)> workspace_state;
sigc::signal<void(std::string)> focused_window_name;
} signals;
Client(int argc, char* argv[]);
void bind_interfaces();
auto setup_css();
int main(int argc, char* argv[]);
};
}

32
include/ipc/client.hpp Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <iostream>
#include "ipc.hpp"
/**
* IPC response including type of IPC response, size of payload and the json
* encoded payload string.
*/
struct ipc_response {
uint32_t size;
uint32_t type;
std::string payload;
};
/**
* Gets the path to the IPC socket from sway.
*/
std::string get_socketpath(void);
/**
* Opens the sway socket.
*/
int ipc_open_socket(std::string socket_path);
/**
* Issues a single IPC command and returns the buffer. len will be updated with
* the length of the buffer returned from sway.
*/
std::string ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len);
/**
* Receives a single IPC response and returns an ipc_response.
*/
struct ipc_response ipc_recv_response(int socketfd);

32
include/ipc/ipc.hpp Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#define event_mask(ev) (1 << (ev & 0x7F))
enum ipc_command_type {
// i3 command types - see i3's I3_REPLY_TYPE constants
IPC_COMMAND = 0,
IPC_GET_WORKSPACES = 1,
IPC_SUBSCRIBE = 2,
IPC_GET_OUTPUTS = 3,
IPC_GET_TREE = 4,
IPC_GET_MARKS = 5,
IPC_GET_BAR_CONFIG = 6,
IPC_GET_VERSION = 7,
IPC_GET_BINDING_MODES = 8,
IPC_GET_CONFIG = 9,
IPC_SEND_TICK = 10,
// sway-specific command types
IPC_GET_INPUTS = 100,
IPC_GET_SEATS = 101,
// Events sent from sway to clients. Events have the highest bits set.
IPC_EVENT_WORKSPACE = ((1<<31) | 0),
IPC_EVENT_OUTPUT = ((1<<31) | 1),
IPC_EVENT_MODE = ((1<<31) | 2),
IPC_EVENT_WINDOW = ((1<<31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
IPC_EVENT_BINDING = ((1<<31) | 5),
IPC_EVENT_SHUTDOWN = ((1<<31) | 6),
IPC_EVENT_TICK = ((1<<31) | 7),
};

View File

@ -0,0 +1,26 @@
#pragma once
#include <filesystem>
#include <fstream>
#include <gtkmm.h>
#include <iostream>
#include <fmt/format.h>
#include "util/chrono.hpp"
namespace waybar::modules {
namespace fs = std::filesystem;
class Battery {
public:
Battery();
auto update() -> void;
operator Gtk::Widget&();
private:
static inline const fs::path _data_dir = "/sys/class/power_supply/";
std::vector<fs::path> _batteries;
util::SleeperThread _thread;
Gtk::Label _label;
};
}

19
include/modules/clock.hpp Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <gtkmm.h>
#include <fmt/format.h>
#include <thread>
#include "util/chrono.hpp"
namespace waybar::modules {
class Clock {
public:
Clock();
operator Gtk::Widget &();
private:
Gtk::Label _label;
waybar::util::SleeperThread _thread;
};
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <json/json.h>
#include <fmt/format.h>
#include "bar.hpp"
#include "client.hpp"
#include "util/chrono.hpp"
namespace waybar::modules {
class WorkspaceSelector {
public:
WorkspaceSelector(waybar::Bar &bar);
auto update() -> void;
operator Gtk::Widget &();
private:
void _addWorkspace(Json::Value node);
Json::Value _getWorkspaces();
Bar &_bar;
Gtk::Box *_box;
std::unordered_map<int, Gtk::Button> _buttons;
util::SleeperThread _thread;
int _ipcSocketfd;
int _ipcEventSocketfd;
};
}

823
include/util/algorithm.hpp Normal file
View File

@ -0,0 +1,823 @@
#pragma once
#include <algorithm>
#include <functional>
#include <initializer_list>
#include <numeric>
#include <string>
#include <string_view>
namespace waybar::util {
/// Joins a sequence of strings, separating them using `js`
template<class StrIterator> // Models InputIterator<std::string>
std::string join_strings(StrIterator b, StrIterator e, std::string_view js = ", ")
{
std::string result;
std::for_each(b, e, [&](auto&& s) {
if (!result.empty()) {
result.append(js);
}
result.append(s);
});
return result;
}
inline const char* nonull(const char* str) {
if (str == nullptr) return "";
return str;
};
inline bool iequals(std::string_view a, std::string_view b)
{
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
[](char a, char b) { return tolower(a) == tolower(b); });
}
inline bool starts_with(std::string_view prefix, std::string_view a)
{
return a.compare(0, prefix.size(), prefix) == 0;
}
inline bool ends_with(std::string_view prefix, std::string_view a)
{
return a.compare(a.size() - prefix.size(), prefix.size(), prefix) == 0;
}
/// Return a closure which compares the adress any reference to T to the address of t
template<typename T>
constexpr auto addr_eq(T&& t) {
return [&t] (auto&& t2) {
return &t == &t2;
};
}
template<typename T>
bool erase_this(std::vector<T>& cont, T* el)
{
if (el < cont.data() && el >= cont.data() + cont.size()) return false;
cont.erase(cont.begin() + (el - cont.data()));
return true;
}
template<typename T>
bool erase_this(std::vector<T>& cont, T& el)
{
return erase_this(cont, &el);
}
namespace detail {
template<class Func, int... ns>
constexpr auto generate_array_impl(std::integer_sequence<int, ns...>&&, Func&& gen)
{
return std::array<std::decay_t<decltype(std::invoke(gen, std::declval<int>()))>,
sizeof...(ns)>{{std::invoke(gen, ns)...}};
}
} // namespace detail
template<int n, class Func>
constexpr auto generate_array(Func&& gen)
{
auto intseq = std::make_integer_sequence<int, n>();
return detail::generate_array_impl(std::move(intseq), std::forward<Func>(gen));
}
namespace view {
namespace detail {
template<typename T>
using store_or_ref_t = std::conditional_t<std::is_rvalue_reference_v<T>, std::decay_t<T>, T&>;
}
template<typename Cont>
struct reverse {
reverse(Cont&& cont) noexcept : _container(std::forward<Cont>(cont)) {}
auto begin()
{
return std::rbegin(_container);
}
auto end()
{
return std::rend(_container);
}
auto begin() const
{
return std::rbegin(_container);
}
auto end() const
{
return std::rend(_container);
}
auto cbegin() const
{
return std::crbegin(_container);
}
auto cend() const
{
return std::crend(_container);
}
detail::store_or_ref_t<Cont&&> _container;
};
template<typename ContRef>
reverse(ContRef&& cont) -> reverse<ContRef&&>;
template<typename Cont>
struct constant {
constant(Cont&& cont) noexcept : _container(std::forward<Cont>(cont)){};
auto begin() const
{
return std::cbegin(_container);
}
auto end() const
{
return std::cend(_container);
}
auto cbegin() const
{
return std::cbegin(_container);
}
auto cend() const
{
return std::cend(_container);
}
detail::store_or_ref_t<Cont&&> _container;
};
template<typename ContRef>
constant(ContRef&& cont) -> constant<ContRef&&>;
} // namespace view
/*
* Range algorithms
*/
template<typename InputIt, typename Size, typename F>
constexpr InputIt for_each_n(InputIt&& first, Size n, F&& f)
{
for (Size i = 0; i < n; ++first, ++i) {
std::invoke(f, *first);
}
return first;
}
/// `for_each` with access to an index value. Function called as `f(*it, i)`
///
/// For each item in range `[first, last)`, invoke `f` with args
/// `*iter, i` where `iter` is the current iterator, and `i` is
/// an incrementing value, starting at zero. Use this instead of
/// raw indexed loops wherever possible.
///
/// \param first Input iterator to the begining of the range
/// \param last Input iterator to the end of the range
/// \param f Must be invocable with arguments `value_type`, `std::size_t`
/// \returns The number of iterations performed
template<typename InputIt, typename F>
constexpr std::size_t indexed_for(InputIt&& first, InputIt&& last, F&& f)
{
std::size_t i = 0;
std::for_each(std::forward<InputIt>(first), std::forward<InputIt>(last), [&](auto&& a) {
std::invoke(f, a, i);
i++;
});
return i;
}
template<typename Rng, typename F>
constexpr std::size_t indexed_for(Rng&& rng, F&& f)
{
return indexed_for(std::begin(rng), std::end(rng), std::forward<F>(f));
}
/// `for_each_n` with access to an index value. Function called as `f(*it, i)`
///
/// for `n` iterations, invoke `f` with args `*iter, i`
/// where `iter` is the current iterator starting with `first`,
/// and `i` is an incrementing value, starting at zero.
/// Use this instead of raw indexed loops wherever possible.
///
/// \param first Input iterator to the begining of the range
/// \param n Number of iterations to go through
/// \param f Must be invocable with arguments `value_type`, `std::size_t`
/// \returns An iterator one past the last one visited
template<class InputIt, class Size, class F>
constexpr InputIt indexed_for_n(InputIt first, Size n, F&& f)
{
for (Size i = 0; i < n; ++first, ++i) {
std::invoke(f, *first, i);
}
return first;
}
template<class Rng, class Size, class F>
constexpr std::size_t indexed_for_n(Rng&& rng, Size n, F&& f)
{
return indexed_for_n(std::begin(rng), std::end(rng), n, std::forward<F>(f));
}
template<typename Iter1, typename Iter2, typename F>
constexpr void for_both(Iter1&& f1, Iter1&& l1, Iter2&& f2, Iter2&& l2, F&& f)
{
Iter1 i1 = std::forward<Iter1>(f1);
Iter2 i2 = std::forward<Iter2>(f2);
for (; i1 != l1 && i2 != l2; i1++, i2++) {
std::invoke(f, *i1, *i2);
}
}
template<typename Rng1, typename Rng2, typename F>
constexpr void for_both(Rng1&& r1, Rng2&& r2, F&& f)
{
for_both(std::begin(r1), std::end(r1), std::begin(r2), std::end(r2), std::forward<F>(f));
}
/*
* Range based standard algorithms
*
* Thanks, chris from SO!
*/
template<typename Cont, typename T>
constexpr auto accumulate(Cont&& cont, T&& init)
{
// TODO C++20: std::accumulate is constexpr
using std::begin, std::end;
auto first = begin(cont);
auto last = end(cont);
for (; first != last; ++first) init = init + *first;
return init;
}
template<typename Cont, typename T, typename BinaryOperation>
constexpr auto accumulate(Cont&& cont, T&& init, BinaryOperation&& op)
{
// TODO C++20: std::accumulate is constexpr
using std::begin, std::end;
auto first = begin(cont);
auto last = end(cont);
for (; first != last; ++first) init = op(init, *first);
return init;
}
template<typename Cont, typename OutputIterator>
decltype(auto) adjacent_difference(Cont&& cont, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::adjacent_difference(begin(cont), end(cont), std::forward<OutputIterator>(first));
}
template<typename Cont>
decltype(auto) prev_permutation(Cont&& cont)
{
using std::begin;
using std::end;
return std::prev_permutation(begin(cont), end(cont));
}
template<typename Cont, typename Compare>
decltype(auto) prev_permutation(Cont&& cont, Compare&& comp)
{
using std::begin;
using std::end;
return std::prev_permutation(begin(cont), end(cont), std::forward<Compare>(comp));
}
template<typename Cont>
decltype(auto) push_heap(Cont&& cont)
{
using std::begin;
using std::end;
return std::push_heap(begin(cont), end(cont));
}
template<typename Cont, typename Compare>
decltype(auto) push_heap(Cont&& cont, Compare&& comp)
{
using std::begin;
using std::end;
return std::push_heap(begin(cont), end(cont), std::forward<Compare>(comp));
}
template<typename Cont, typename T>
decltype(auto) remove(Cont&& cont, T&& value)
{
using std::begin;
using std::end;
return std::remove(begin(cont), end(cont), std::forward<T>(value));
}
template<typename Cont, typename OutputIterator, typename T>
decltype(auto) remove_copy(Cont&& cont, OutputIterator&& first, T&& value)
{
using std::begin;
using std::end;
return std::remove_copy(begin(cont), end(cont), std::forward<OutputIterator>(first),
std::forward<T>(value));
}
template<typename Cont, typename OutputIterator, typename UnaryPredicate>
decltype(auto) remove_copy_if(Cont&& cont, OutputIterator&& first, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::remove_copy_if(begin(cont), end(cont), std::forward<OutputIterator>(first),
std::forward<UnaryPredicate>(p));
}
template<typename Cont, typename UnaryPredicate>
decltype(auto) remove_if(Cont&& cont, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::remove_if(begin(cont), end(cont), std::forward<UnaryPredicate>(p));
}
template<typename Cont, typename T, typename T2>
decltype(auto) replace(Cont&& cont, T&& old_value, T2&& new_value)
{
using std::begin;
using std::end;
return std::replace(begin(cont), end(cont), std::forward<T>(old_value),
std::forward<T2>(new_value));
}
template<typename Cont, typename OutputIterator, typename T, typename T2>
decltype(auto) replace_copy(Cont&& cont, OutputIterator&& first, T&& old_value, T2&& new_value)
{
using std::begin;
using std::end;
return std::replace_copy(begin(cont), end(cont), std::forward<OutputIterator>(first),
std::forward<T>(old_value), std::forward<T2>(old_value));
}
template<typename Cont, typename OutputIterator, typename UnaryPredicate, typename T>
decltype(auto) replace_copy_if(Cont&& cont,
OutputIterator&& first,
UnaryPredicate&& p,
T&& new_value)
{
using std::begin;
using std::end;
return std::replace_copy(begin(cont), end(cont), std::forward<OutputIterator>(first),
std::forward<UnaryPredicate>(p), std::forward<T>(new_value));
}
template<typename Cont, typename UnaryPredicate, typename T>
decltype(auto) replace_if(Cont&& cont, UnaryPredicate&& p, T&& new_value)
{
using std::begin;
using std::end;
return std::replace_if(begin(cont), end(cont), std::forward<UnaryPredicate>(p),
std::forward<T>(new_value));
}
template<typename Cont>
decltype(auto) reverse(Cont&& cont)
{
using std::begin;
using std::end;
return std::reverse(begin(cont), end(cont));
}
template<typename Cont, typename OutputIterator>
decltype(auto) reverse_copy(Cont&& cont, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::reverse_copy(begin(cont), end(cont), std::forward<OutputIterator>(first));
}
template<typename Cont, typename ForwardIterator>
decltype(auto) rotate(Cont&& cont, ForwardIterator&& new_first)
{
using std::begin;
using std::end;
return std::rotate(begin(cont), std::forward<ForwardIterator>(new_first), end(cont));
}
template<typename Cont, typename ForwardIterator, typename OutputIterator>
decltype(auto) rotate_copy(Cont&& cont, ForwardIterator&& new_first, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::rotate_copy(begin(cont), std::forward<ForwardIterator>(new_first), end(cont),
std::forward<OutputIterator>(first));
}
template<typename Cont, typename Cont2>
decltype(auto) search(Cont&& cont, Cont2&& cont2)
{
using std::begin;
using std::end;
return std::search(begin(cont), end(cont), begin(cont2), end(cont2));
}
template<typename Cont, typename Cont2, typename BinaryPredicate>
decltype(auto) search(Cont&& cont, Cont2&& cont2, BinaryPredicate&& p)
{
using std::begin;
using std::end;
return std::search(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<BinaryPredicate>(p));
}
template<typename Cont, typename Size, typename T>
decltype(auto) search_n(Cont&& cont, Size count, T&& value)
{
using std::begin;
using std::end;
return std::search_n(begin(cont), end(cont), count, std::forward<T>(value));
}
template<typename Cont, typename Size, typename T, typename BinaryPredicate>
decltype(auto) search_n(Cont&& cont, Size count, T&& value, BinaryPredicate&& p)
{
using std::begin;
using std::end;
return std::search_n(begin(cont), end(cont), count, std::forward<T>(value),
std::forward<BinaryPredicate>(p));
}
template<typename Cont, typename Cont2, typename OutputIterator>
decltype(auto) set_difference(Cont&& cont, Cont2&& cont2, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::set_difference(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first));
}
template<typename Cont, typename Cont2, typename OutputIterator, typename Compare>
decltype(auto) set_difference(Cont&& cont, Cont2&& cont2, OutputIterator&& first, Compare&& comp)
{
using std::begin;
using std::end;
return std::set_difference(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first), std::forward<Compare>(comp));
}
template<typename Cont, typename Cont2, typename OutputIterator>
decltype(auto) set_intersection(Cont&& cont, Cont2&& cont2, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::set_intersection(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first));
}
template<typename Cont, typename Cont2, typename OutputIterator, typename Compare>
decltype(auto) set_intersection(Cont&& cont,
Cont2&& cont2,
OutputIterator&& first,
Compare&& comp)
{
using std::begin;
using std::end;
return std::set_intersection(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first), std::forward<Compare>(comp));
}
template<typename Cont, typename Cont2, typename OutputIterator>
decltype(auto) set_symmetric_difference(Cont&& cont, Cont2&& cont2, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::set_symmetric_difference(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first));
}
template<typename Cont, typename Cont2, typename OutputIterator, typename Compare>
decltype(auto) set_symmetric_difference(Cont&& cont,
Cont2&& cont2,
OutputIterator&& first,
Compare&& comp)
{
using std::begin;
using std::end;
return std::set_symmetric_difference(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first),
std::forward<Compare>(comp));
}
template<typename Cont, typename Cont2, typename OutputIterator>
decltype(auto) set_union(Cont&& cont, Cont2&& cont2, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::set_union(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first));
}
template<typename Cont, typename Cont2, typename OutputIterator, typename Compare>
decltype(auto) set_union(Cont&& cont, Cont2&& cont2, OutputIterator&& first, Compare&& comp)
{
using std::begin;
using std::end;
return std::set_union(begin(cont), end(cont), begin(cont2), end(cont2),
std::forward<OutputIterator>(first), std::forward<Compare>(comp));
}
template<typename Cont, typename UniformRandomNumberGenerator>
decltype(auto) shuffle(Cont&& cont, UniformRandomNumberGenerator&& g)
{
using std::begin;
using std::end;
return std::shuffle(begin(cont), end(cont), std::forward<UniformRandomNumberGenerator>(g));
}
template<typename Cont>
decltype(auto) sort(Cont&& cont)
{
using std::begin;
using std::end;
return std::sort(begin(cont), end(cont));
}
template<typename Cont, typename Compare>
decltype(auto) sort(Cont&& cont, Compare&& comp)
{
using std::begin;
using std::end;
return std::sort(begin(cont), end(cont), std::forward<Compare>(comp));
}
template<typename Cont>
decltype(auto) sort_heap(Cont&& cont)
{
using std::begin;
using std::end;
return std::sort_heap(begin(cont), end(cont));
}
template<typename Cont, typename Compare>
decltype(auto) sort_heap(Cont&& cont, Compare&& comp)
{
using std::begin;
using std::end;
return std::sort_heap(begin(cont), end(cont), std::forward<Compare>(comp));
}
template<typename Cont, typename UnaryPredicate>
decltype(auto) stable_partition(Cont&& cont, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::stable_partition(begin(cont), end(cont), std::forward<UnaryPredicate>(p));
}
template<typename Cont>
decltype(auto) stable_sort(Cont&& cont)
{
using std::begin;
using std::end;
return std::stable_sort(begin(cont), end(cont));
}
template<typename Cont, typename Compare>
decltype(auto) stable_sort(Cont&& cont, Compare&& comp)
{
using std::begin;
using std::end;
return std::stable_sort(begin(cont), end(cont), std::forward<Compare>(comp));
}
template<typename Cont, typename ForwardIterator>
decltype(auto) swap_ranges(Cont&& cont, ForwardIterator&& first)
{
using std::begin;
using std::end;
return std::swap_ranges(begin(cont), end(cont), std::forward<ForwardIterator>(first));
}
template<typename Cont, typename Cont2, typename F>
auto transform(Cont&& cont, Cont2&& cont2, F&& f) -> decltype(begin(cont2))
{
using std::begin;
using std::end;
return std::transform(begin(cont), end(cont), begin(cont2), std::forward<F>(f));
}
template<typename Cont, typename Iter, typename F>
decltype(auto) transform(Cont&& cont, Iter&& iter, F&& f)
{
using std::begin;
using std::end;
return std::transform(begin(cont), end(cont), std::forward<Iter>(iter), std::forward<F>(f));
}
template<typename Cont, typename Cont2, typename Cont3, typename BinaryPredicate>
auto transform(Cont&& cont, Cont2&& cont2, Cont3&& cont3, BinaryPredicate&& f)
-> decltype(begin(cont2), begin(cont3))
{
using std::begin;
using std::end;
return std::transform(begin(cont), end(cont), begin(cont2), begin(cont3),
std::forward<BinaryPredicate>(f));
}
template<typename Cont, typename InputIterator, typename Cont3, typename BinaryPredicate>
auto transform(Cont&& cont, InputIterator&& iter, Cont3&& cont3, BinaryPredicate&& f)
-> decltype(begin(cont), begin(cont3))
{
using std::begin;
using std::end;
return std::transform(begin(cont), end(cont), std::forward<InputIterator>(iter), begin(cont3),
std::forward<BinaryPredicate>(f));
}
template<typename Cont, typename Cont2, typename InputIterator, typename BinaryPredicate>
auto transform(Cont&& cont, Cont2&& cont2, InputIterator&& iter, BinaryPredicate&& f)
-> decltype(begin(cont), begin(cont2), iter)
{
using std::begin;
using std::end;
return std::transform(begin(cont), end(cont), begin(cont2), std::forward<InputIterator>(iter),
std::forward<BinaryPredicate>(f));
}
template<typename Cont, typename InputIterator, typename OutputIterator, typename BinaryOperation>
decltype(auto) transform(Cont&& cont,
InputIterator&& firstIn,
OutputIterator&& firstOut,
BinaryOperation&& op)
{
using std::begin;
using std::end;
return std::transform(begin(cont), end(cont), std::forward<InputIterator>(firstIn),
std::forward<OutputIterator>(firstOut),
std::forward<BinaryOperation>(op));
}
template<typename Cont>
decltype(auto) unique(Cont&& cont)
{
using std::begin;
using std::end;
return std::unique(begin(cont), end(cont));
}
template<typename Cont, typename BinaryPredicate>
decltype(auto) unique(Cont&& cont, BinaryPredicate&& p)
{
using std::begin;
using std::end;
return std::unique(begin(cont), end(cont), std::forward<BinaryPredicate>(p));
}
template<typename Cont, typename OutputIterator>
decltype(auto) unique_copy(Cont&& cont, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::unique_copy(begin(cont), end(cont), std::forward<OutputIterator>(first));
}
template<typename Cont, typename OutputIterator, typename BinaryPredicate>
decltype(auto) unique_copy(Cont&& cont, OutputIterator&& first, BinaryPredicate&& p)
{
using std::begin;
using std::end;
return std::unique_copy(begin(cont), end(cont), std::forward<OutputIterator>(first),
std::forward<BinaryPredicate>(p));
}
template<typename Cont, typename T>
decltype(auto) upper_bound(Cont&& cont, T&& value)
{
using std::begin;
using std::end;
return std::upper_bound(begin(cont), end(cont), std::forward<T>(value));
}
template<typename Cont, typename T, typename Compare>
decltype(auto) upper_bound(Cont&& cont, T&& value, Compare&& comp)
{
using std::begin;
using std::end;
return std::upper_bound(begin(cont), end(cont), std::forward<T>(value),
std::forward<Compare>(comp));
}
template<typename Cont, typename OutputIterator>
decltype(auto) copy(Cont&& cont, OutputIterator&& first)
{
using std::begin;
using std::end;
return std::copy(begin(cont), end(cont), std::forward<OutputIterator>(first));
}
template<typename Cont, typename OutputIterator, typename UnaryPredicate>
decltype(auto) copy_if(Cont&& cont, OutputIterator&& first, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::copy_if(begin(cont), end(cont), std::forward<OutputIterator>(first),
std::forward<UnaryPredicate>(p));
}
template<typename Cont, typename T>
decltype(auto) fill(Cont&& cont, T&& value)
{
using std::begin;
using std::end;
return std::fill(begin(cont), end(cont), std::forward<T>(value));
}
template<typename Cont, typename T>
decltype(auto) fill_n(Cont&& cont, std::size_t n, T&& value)
{
using std::begin;
using std::end;
return std::fill_n(begin(cont), n, std::forward<T>(value));
}
template<typename Cont, typename UnaryPredicate>
decltype(auto) any_of(Cont&& cont, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::any_of(begin(cont), end(cont), std::forward<UnaryPredicate>(p));
}
template<typename Cont, typename UnaryPredicate>
decltype(auto) all_of(Cont&& cont, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::all_of(begin(cont), end(cont), std::forward<UnaryPredicate>(p));
}
template<typename Cont, typename UnaryPredicate>
decltype(auto) none_of(Cont&& cont, UnaryPredicate&& p)
{
using std::begin;
using std::end;
return std::none_of(begin(cont), end(cont), std::forward<UnaryPredicate>(p));
}
template<typename Cont>
decltype(auto) max_element(Cont&& cont)
{
using std::begin;
using std::end;
return std::max_element(begin(cont), end(cont));
}
template<typename Cont>
decltype(auto) min_element(Cont&& cont)
{
using std::begin;
using std::end;
return std::min_element(begin(cont), end(cont));
}
template<typename Cont, typename Compare>
decltype(auto) min_element(Cont&& cont, Compare&& f)
{
using std::begin;
using std::end;
return std::min_element(begin(cont), end(cont), std::forward<Compare>(f));
}
template<typename Cont, typename Compare>
decltype(auto) max_element(Cont&& cont, Compare&& f)
{
using std::begin;
using std::end;
return std::max_element(begin(cont), end(cont), std::forward<Compare>(f));
}
template<typename Cont, typename T>
decltype(auto) find(Cont&& cont, T&& t)
{
using std::begin;
using std::end;
return std::find(begin(cont), end(cont), std::forward<T>(t));
}
template<typename Cont, typename UnaryPredicate>
decltype(auto) find_if(Cont&& cont, UnaryPredicate&& f)
{
using std::begin;
using std::end;
return std::find_if(begin(cont), end(cont), std::forward<UnaryPredicate>(f));
}
} // namespace waybar::util

86
include/util/chrono.hpp Normal file
View File

@ -0,0 +1,86 @@
#pragma once
#include <chrono>
#include <ctime>
#include <functional>
#include <condition_variable>
#include <thread>
namespace waybar::chrono {
using namespace std::chrono;
using clock = std::chrono::system_clock;
using duration = clock::duration;
using time_point = std::chrono::time_point<clock, duration>;
inline struct timespec to_timespec(time_point t) noexcept
{
long secs = duration_cast<seconds>(t.time_since_epoch()).count();
long nsc = duration_cast<nanoseconds>(t.time_since_epoch() % seconds(1)).count();
return {secs, nsc};
}
inline time_point to_time_point(struct timespec t) noexcept
{
return time_point(duration_cast<duration>(seconds(t.tv_sec) + nanoseconds(t.tv_nsec)));
}
}
namespace waybar::util {
struct SleeperThread {
SleeperThread() = default;
SleeperThread(std::function<void()> func)
: thread{[this, func] {
do {
func();
} while (do_run);
}}
{}
SleeperThread& operator=(std::function<void()> func)
{
thread = std::thread([this, func] {
do {
func();
} while (do_run);
});
return *this;
}
auto sleep_for(chrono::duration dur)
{
auto lock = std::unique_lock(mutex);
return condvar.wait_for(lock, dur);
}
auto sleep_until(chrono::time_point time)
{
auto lock = std::unique_lock(mutex);
return condvar.wait_until(lock, time);
}
auto wake_up()
{
condvar.notify_all();
}
~SleeperThread()
{
do_run = false;
condvar.notify_all();
thread.join();
}
private:
std::thread thread;
std::condition_variable condvar;
std::mutex mutex;
bool do_run = true;
};
}

581
include/util/ptr_vec.hpp Normal file
View File

@ -0,0 +1,581 @@
#pragma once
#include <cassert>
#include <memory>
#include <type_traits>
#include <vector>
#include "algorithm.hpp"
namespace waybar::util {
/// An iterator wrapper that dereferences twice.
template<typename Iter>
struct double_iterator {
using wrapped = Iter;
using value_type = std::decay_t<decltype(*std::declval<typename wrapped::value_type>())>;
using difference_type = typename wrapped::difference_type;
using reference = value_type&;
using pointer = value_type*;
using iterator_category = std::random_access_iterator_tag;
using self_t = double_iterator<Iter>;
double_iterator(wrapped w) : _iter(std::move(w)) {}
double_iterator() : _iter() {}
reference operator*() const
{
return (**_iter);
}
pointer operator->() const
{
return &(**_iter);
}
self_t& operator++()
{
_iter.operator++();
return *this;
}
self_t operator++(int i)
{
return _iter.operator++(i);
}
self_t& operator--()
{
_iter.operator--();
return *this;
}
self_t operator--(int i)
{
return _iter.operator--(i);
}
auto operator==(const self_t& rhs) const noexcept
{
return _iter == rhs._iter;
}
auto operator!=(const self_t& rhs) const noexcept
{
return _iter != rhs._iter;
}
auto operator<(const self_t& rhs) const noexcept
{
return _iter < rhs._iter;
}
auto operator>(const self_t& rhs) const noexcept
{
return _iter > rhs._iter;
}
auto operator<=(const self_t& rhs) const noexcept
{
return _iter <= rhs._iter;
}
auto operator>=(const self_t& rhs) const noexcept
{
return _iter >= rhs._iter;
}
self_t operator+(difference_type d) const noexcept
{
return _iter + d;
}
self_t operator-(difference_type d) const noexcept
{
return _iter - d;
}
auto operator-(const self_t& rhs) const noexcept
{
return _iter - rhs._iter;
}
self_t& operator+=(difference_type d)
{
_iter += d;
return *this;
}
self_t& operator-=(difference_type d)
{
_iter -= d;
return *this;
}
operator wrapped&()
{
return _iter;
}
operator const wrapped&() const
{
return _iter;
}
wrapped& data()
{
return _iter;
}
const wrapped& data() const
{
return _iter;
}
private:
wrapped _iter;
};
template<typename Iter>
auto operator+(typename double_iterator<Iter>::difference_type diff, double_iterator<Iter> iter)
{
return iter + diff;
}
/// To avoid clients being moved, they are stored in unique_ptrs, which are
/// moved around in a vector. This class is purely for convenience, to still
/// have iterator semantics, and a few other utility functions
template<typename T>
struct ptr_vec {
using value_type = T;
std::vector<std::unique_ptr<value_type>> _order;
using iterator = double_iterator<typename decltype(_order)::iterator>;
using const_iterator = double_iterator<typename decltype(_order)::const_iterator>;
using reverse_iterator = double_iterator<typename decltype(_order)::reverse_iterator>;
using const_reverse_iterator =
double_iterator<typename decltype(_order)::const_reverse_iterator>;
value_type& push_back(const value_type& v)
{
auto ptr = std::make_unique<value_type>(v);
auto res = ptr.get();
_order.push_back(std::move(ptr));
return *res;
}
value_type& push_back(value_type&& v)
{
auto ptr = std::make_unique<value_type>(std::move(v));
auto res = ptr.get();
_order.push_back(std::move(ptr));
return *res;
}
value_type& push_back(std::unique_ptr<value_type> ptr)
{
auto res = ptr.get();
_order.push_back(std::move(ptr));
return *res;
}
template<typename... Args>
value_type& emplace_back(Args&&... args)
{
return push_back(std::make_unique<value_type>(std::forward<Args>(args)...));
}
std::unique_ptr<value_type> erase(const value_type& v)
{
auto iter =
std::find_if(_order.begin(), _order.end(), [&v](auto&& uptr) { return uptr.get() == &v; });
if (iter != _order.end()) {
auto uptr = std::move(*iter);
_order.erase(iter);
return uptr;
}
return nullptr;
}
iterator rotate_to_back(const value_type& v)
{
auto iter =
std::find_if(_order.begin(), _order.end(), [&v](auto&& uptr) { return uptr.get() == &v; });
return rotate_to_back(iter);
}
iterator rotate_to_back(iterator iter)
{
if (iter != _order.end()) {
{
return std::rotate(iter.data(), iter.data() + 1, _order.end());
}
}
return end();
}
iterator rotate_to_front(const value_type& v)
{
auto iter =
std::find_if(_order.begin(), _order.end(), [&v](auto&& uptr) { return uptr.get() == &v; });
return rotate_to_front(iter);
}
iterator rotate_to_front(iterator iter)
{
if (iter != _order.end()) {
{
return std::rotate(_order.begin(), iter.data(), iter.data() + 1);
}
}
return end();
}
std::size_t size() const noexcept
{
return _order.size();
}
bool empty() const noexcept
{
return _order.empty();
}
std::size_t capacity() const noexcept
{
return _order.capacity();
}
std::size_t max_size() const noexcept
{
return _order.max_size();
}
void reserve(std::size_t new_cap)
{
_order.reserve(new_cap);
}
void shrink_to_fit()
{
_order.shrink_to_fit();
}
value_type& operator[](std::size_t n)
{
return *_order[n];
}
const value_type& operator[](std::size_t n) const
{
return *_order[n];
}
value_type& at(std::size_t n)
{
return *_order.at(n);
}
const value_type& at(std::size_t n) const
{
return *_order.at(n);
}
iterator begin()
{
return _order.begin();
}
iterator end()
{
return _order.end();
}
const_iterator begin() const
{
return _order.begin();
}
const_iterator end() const
{
return _order.end();
}
reverse_iterator rbegin()
{
return _order.rbegin();
}
reverse_iterator rend()
{
return _order.rend();
}
const_reverse_iterator rbegin() const
{
return _order.rbegin();
}
const_reverse_iterator rend() const
{
return _order.rend();
}
value_type& front()
{
return *_order.front();
}
value_type& back()
{
return *_order.back();
}
const value_type& front() const
{
return *_order.front();
}
const value_type& back() const
{
return *_order.back();
}
std::vector<std::unique_ptr<value_type>>& underlying() {
return _order;
}
};
template<typename T, typename T2>
std::unique_ptr<T> erase_this(ptr_vec<T>& vec, T2* el)
{
return vec.erase(*el);
}
template<typename T, typename T2>
std::unique_ptr<T> erase_this(ptr_vec<T>& vec, T2& el)
{
return vec.erase(el);
}
template<typename T>
struct non_null_ptr {
non_null_ptr() = delete;
constexpr non_null_ptr(T* ptr) : _ptr(ptr)
{
assert(ptr != nullptr);
}
non_null_ptr(std::nullptr_t) = delete;
constexpr non_null_ptr(const non_null_ptr&) = default;
constexpr non_null_ptr(non_null_ptr&&) = default;
constexpr non_null_ptr& operator=(const non_null_ptr&) = default;
constexpr non_null_ptr& operator=(non_null_ptr&&) = default;
constexpr T& operator*() const noexcept
{
return *_ptr;
}
constexpr T* operator->() const noexcept
{
return _ptr;
}
constexpr operator T*() noexcept
{
return _ptr;
}
constexpr operator T* const() const noexcept
{
return _ptr;
}
private:
T* _ptr;
};
template<typename T>
struct ref_vec {
using value_type = T;
std::vector<value_type*> _order;
using iterator = double_iterator<typename decltype(_order)::iterator>;
using const_iterator = double_iterator<typename decltype(_order)::const_iterator>;
using reverse_iterator = double_iterator<typename decltype(_order)::reverse_iterator>;
using const_reverse_iterator =
double_iterator<typename decltype(_order)::const_reverse_iterator>;
ref_vec() = default;
ref_vec(std::initializer_list<value_type*> lst) : _order {lst} { };
template<typename InputIter, typename = std::enable_if_t<std::is_same_v<decltype(*std::declval<InputIter>()), value_type&>>>
ref_vec(InputIter iter1, InputIter iter2) {
_order.reserve(std::distance(iter1, iter2));
std::transform(iter1, iter2, std::back_inserter(_order), [] (auto& v) {return &v; });
}
template<typename Range, typename = std::enable_if_t<std::is_same_v<decltype(*std::declval<Range>().begin()), value_type&>>>
ref_vec(Range&& rng) : ref_vec (std::begin(rng), std::end(rng)) { }
value_type& push_back(value_type& v)
{
_order.push_back(&v);
return v;
}
value_type& push_back(non_null_ptr<value_type> ptr)
{
_order.push_back(ptr);
return *ptr;
}
value_type& emplace_back(value_type& v)
{
return push_back(v);
}
std::unique_ptr<value_type> erase(const value_type& v)
{
auto iter =
std::find_if(_order.begin(), _order.end(), [&v](auto&& ptr) { return ptr == &v; });
if (iter != _order.end()) {
auto uptr = std::move(*iter);
_order.erase(iter);
return uptr;
}
return nullptr;
}
iterator rotate_to_back(const value_type& v)
{
auto iter =
std::find_if(_order.begin(), _order.end(), [&v](auto&& ptr) { return ptr == &v; });
return rotate_to_back(iter);
}
iterator rotate_to_back(iterator iter)
{
if (iter != _order.end()) {
{
return std::rotate(iter.data(), iter.data() + 1, _order.end());
}
}
return end();
}
iterator rotate_to_front(const value_type& v)
{
auto iter =
std::find_if(_order.begin(), _order.end(), [&v](auto&& ptr) { return ptr == &v; });
return rotate_to_front(iter);
}
iterator rotate_to_front(iterator iter)
{
if (iter != _order.end()) {
{
return std::rotate(_order.begin(), iter.data(), iter.data() + 1);
}
}
return end();
}
std::size_t size() const noexcept
{
return _order.size();
}
bool empty() const noexcept
{
return _order.empty();
}
std::size_t capacity() const noexcept
{
return _order.capacity();
}
std::size_t max_size() const noexcept
{
return _order.max_size();
}
void reserve(std::size_t new_cap)
{
_order.reserve(new_cap);
}
void shrink_to_fit()
{
_order.shrink_to_fit();
}
value_type& operator[](std::size_t n)
{
return *_order[n];
}
const value_type& operator[](std::size_t n) const
{
return *_order[n];
}
value_type& at(std::size_t n)
{
return *_order.at(n);
}
const value_type& at(std::size_t n) const
{
return *_order.at(n);
}
iterator begin()
{
return _order.begin();
}
iterator end()
{
return _order.end();
}
const_iterator begin() const
{
return _order.begin();
}
const_iterator end() const
{
return _order.end();
}
reverse_iterator rbegin()
{
return _order.rbegin();
}
reverse_iterator rend()
{
return _order.rend();
}
const_reverse_iterator rbegin() const
{
return _order.rbegin();
}
const_reverse_iterator rend() const
{
return _order.rend();
}
value_type& front()
{
return *_order.front();
}
value_type& back()
{
return *_order.back();
}
const value_type& front() const
{
return *_order.front();
}
const value_type& back() const
{
return *_order.back();
}
std::vector<value_type*>& underlying() {
return _order;
}
};
} // namespace waybar::util