1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2025-02-06 05:58:36 +00:00

Remove _member_access from geometry (#1910)

* It was difficult/too costly ensuring temporary this was correct when vecs contained in rects were accessed directly.
* Added semantics to `rect` and some utility functions.

Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
This commit is contained in:
Tin Švagelj 2024-05-13 22:08:27 +02:00 committed by GitHub
parent 968fc7fcbc
commit 2d50767216
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 1491 additions and 1417 deletions

View File

@ -51,7 +51,10 @@ if(MAINTAINER_MODE)
endif(MAINTAINER_MODE) endif(MAINTAINER_MODE)
# Always use libc++ when compiling w/ clang # Always use libc++ when compiling w/ clang
add_compile_options($<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>) add_compile_options(
$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>
$<$<COMPILE_LANG_AND_ID:CXX,Clang>:-Wno-unknown-warning-option>
$<$<COMPILE_LANG_AND_ID:CXX,GCC>:-Wno-unknown-warning>)
add_link_options($<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>) add_link_options($<$<COMPILE_LANG_AND_ID:CXX,Clang>:-stdlib=libc++>)
option(CHECK_CODE_QUALITY "Check code formatting/quality with clang" false) option(CHECK_CODE_QUALITY "Check code formatting/quality with clang" false)

File diff suppressed because it is too large Load Diff

View File

@ -303,10 +303,10 @@ static void output_geometry(void *data, struct wl_output *wl_output, int32_t x,
// Maybe also support (if XDG protocol not reported): // Maybe also support (if XDG protocol not reported):
// - kde-output-management(-v2) // - kde-output-management(-v2)
// - wlr-output-management-unstable-v1 // - wlr-output-management-unstable-v1
workarea.x = x; // TODO: use xdg_output.logical_position workarea = absolute_rect<int>(
workarea.y = y; vec2i(x, y),
workarea.width = physical_width; vec2i(x + physical_width,
workarea.height = physical_height; y + physical_height)); // TODO: use xdg_output.logical_position
} }
static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
@ -413,8 +413,8 @@ void window_get_width_height(struct window *window, int *w, int *h);
void window_layer_surface_set_size(struct window *window) { void window_layer_surface_set_size(struct window *window) {
zwlr_layer_surface_v1_set_size(global_window->layer_surface, zwlr_layer_surface_v1_set_size(global_window->layer_surface,
global_window->rectangle.width, global_window->rectangle.width(),
global_window->rectangle.height); global_window->rectangle.height());
} }
#ifdef BUILD_MOUSE_EVENTS #ifdef BUILD_MOUSE_EVENTS
@ -428,7 +428,7 @@ static void on_pointer_enter(void *data, wl_pointer *pointer,
auto pos = auto pos =
vec2d(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)); vec2d(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
last_known_positions[pointer] = pos; last_known_positions[pointer] = pos;
auto pos_abs = w->rectangle.pos + pos; auto pos_abs = w->rectangle.pos() + pos;
mouse_crossing_event event{mouse_event_t::AREA_ENTER, pos, pos_abs}; mouse_crossing_event event{mouse_event_t::AREA_ENTER, pos, pos_abs};
llua_mouse_hook(event); llua_mouse_hook(event);
@ -439,7 +439,7 @@ static void on_pointer_leave(void *data, struct wl_pointer *pointer,
auto w = reinterpret_cast<struct window *>(data); auto w = reinterpret_cast<struct window *>(data);
auto pos = last_known_positions[pointer]; auto pos = last_known_positions[pointer];
auto pos_abs = w->rectangle.pos + pos; auto pos_abs = w->rectangle.pos() + pos;
mouse_crossing_event event{mouse_event_t::AREA_LEAVE, pos, pos_abs}; mouse_crossing_event event{mouse_event_t::AREA_LEAVE, pos, pos_abs};
llua_mouse_hook(event); llua_mouse_hook(event);
@ -453,7 +453,7 @@ static void on_pointer_motion(void *data, struct wl_pointer *pointer,
auto pos = auto pos =
vec2d(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)); vec2d(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
last_known_positions[pointer] = pos; last_known_positions[pointer] = pos;
auto pos_abs = w->rectangle.pos + pos; auto pos_abs = w->rectangle.pos() + pos;
mouse_move_event event{pos, pos_abs}; mouse_move_event event{pos, pos_abs};
llua_mouse_hook(event); llua_mouse_hook(event);
@ -465,7 +465,7 @@ static void on_pointer_button(void *data, struct wl_pointer *pointer,
auto w = reinterpret_cast<struct window *>(data); auto w = reinterpret_cast<struct window *>(data);
auto pos = last_known_positions[pointer]; auto pos = last_known_positions[pointer];
auto pos_abs = w->rectangle.pos + pos; auto pos_abs = w->rectangle.pos() + pos;
mouse_button_event event{ mouse_button_event event{
mouse_event_t::RELEASE, mouse_event_t::RELEASE,
@ -494,7 +494,7 @@ void on_pointer_axis(void *data, struct wl_pointer *pointer, std::uint32_t time,
auto w = reinterpret_cast<struct window *>(data); auto w = reinterpret_cast<struct window *>(data);
auto pos = last_known_positions[pointer]; auto pos = last_known_positions[pointer];
auto pos_abs = w->rectangle.pos + pos; auto pos_abs = w->rectangle.pos() + pos;
mouse_scroll_event event{ mouse_scroll_event event{
pos, pos,
@ -657,19 +657,19 @@ bool display_output_wayland::main_loop_wait(double t) {
/* resize window if it isn't right size */ /* resize window if it isn't right size */
if ((fixed_size == 0) && if ((fixed_size == 0) &&
(text_size.x + 2 * border_total != width || (text_size.x() + 2 * border_total != width ||
text_size.y + 2 * border_total != height || scale_changed)) { text_size.y() + 2 * border_total != height || scale_changed)) {
/* clamp text_width to configured maximum */ /* clamp text_width to configured maximum */
if (maximum_width.get(*state)) { if (maximum_width.get(*state)) {
int mw = global_window->scale * maximum_width.get(*state); int mw = global_window->scale * maximum_width.get(*state);
if (text_size.x > mw && mw > 0) { text_size.x = mw; } if (text_size.x() > mw && mw > 0) { text_size.set_x(mw); }
} }
/* pending scale will be applied by resizing the window */ /* pending scale will be applied by resizing the window */
global_window->scale = global_window->pending_scale; global_window->scale = global_window->pending_scale;
width = text_size.x + 2 * border_total; width = text_size.x() + 2 * border_total;
height = text_size.y + 2 * border_total; height = text_size.y() + 2 * border_total;
window_resize(global_window, width, height); /* resize window */ window_resize(global_window, width, height); /* resize window */
changed++; changed++;
@ -808,8 +808,8 @@ int display_output_wayland::calc_text_width(const char *s) {
} }
static void adjust_coords(int &x, int &y) { static void adjust_coords(int &x, int &y) {
x -= text_start.x; x -= text_start.x();
y -= text_start.y; y -= text_start.y();
int border = get_border_total(); int border = get_border_total();
x += border; x += border;
y += border; y += border;
@ -1106,14 +1106,14 @@ static void shm_pool_destroy(struct shm_pool *pool) {
static int stride_for_shm_surface(rect<size_t> *rect, int scale) { static int stride_for_shm_surface(rect<size_t> *rect, int scale) {
return cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, return cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,
rect->width * scale); rect->width() * scale);
} }
static int data_length_for_shm_surface(rect<size_t> *rect, int scale) { static int data_length_for_shm_surface(rect<size_t> *rect, int scale) {
int stride; int stride;
stride = stride_for_shm_surface(rect, scale); stride = stride_for_shm_surface(rect, scale);
return stride * rect->height * scale; return stride * rect->height() * scale;
} }
static cairo_surface_t *create_shm_surface_from_pool(void *none, static cairo_surface_t *create_shm_surface_from_pool(void *none,
@ -1142,9 +1142,9 @@ static cairo_surface_t *create_shm_surface_from_pool(void *none,
return NULL; return NULL;
} }
auto scaled = rectangle->size * scale; auto scaled = rectangle->size() * scale;
surface = cairo_image_surface_create_for_data( surface = cairo_image_surface_create_for_data(
static_cast<unsigned char *>(map), cairo_format, scaled.x, scaled.y, static_cast<unsigned char *>(map), cairo_format, scaled.x(), scaled.y(),
stride); stride);
cairo_surface_set_user_data(surface, &shm_surface_data_key, data, cairo_surface_set_user_data(surface, &shm_surface_data_key, data,
@ -1152,8 +1152,8 @@ static cairo_surface_t *create_shm_surface_from_pool(void *none,
format = WL_SHM_FORMAT_ARGB8888; /*or WL_SHM_FORMAT_RGB565*/ format = WL_SHM_FORMAT_ARGB8888; /*or WL_SHM_FORMAT_RGB565*/
data->buffer = wl_shm_pool_create_buffer(pool->pool, offset, scaled.x, data->buffer = wl_shm_pool_create_buffer(pool->pool, offset, scaled.x(),
scaled.y, stride, format); scaled.y(), stride, format);
return surface; return surface;
} }
@ -1195,8 +1195,8 @@ struct window *window_create(struct wl_surface *surface, struct wl_shm *shm,
struct window *window; struct window *window;
window = new struct window; window = new struct window;
window->rectangle.pos = vec2<size_t>::Zero(); window->rectangle.set_pos(vec2<size_t>::Zero());
window->rectangle.size = vec2<size_t>(width, height); window->rectangle.set_size(width, height);
window->scale = 0; window->scale = 0;
window->pending_scale = 1; window->pending_scale = 1;
@ -1235,7 +1235,7 @@ void window_destroy(struct window *window) {
void window_resize(struct window *window, int width, int height) { void window_resize(struct window *window, int width, int height) {
window_free_buffer(window); window_free_buffer(window);
window->rectangle.size = conky::vec2i(width, height); window->rectangle.set_size(width, height);
window_allocate_buffer(window); window_allocate_buffer(window);
window_layer_surface_set_size(window); window_layer_surface_set_size(window);
} }
@ -1248,14 +1248,15 @@ void window_commit_buffer(struct window *window) {
get_buffer_from_cairo_surface(window->cairo_surface), 0, 0); get_buffer_from_cairo_surface(window->cairo_surface), 0, 0);
/* repaint all the pixels in the surface, change size to only repaint changed /* repaint all the pixels in the surface, change size to only repaint changed
* area*/ * area*/
wl_surface_damage(window->surface, window->rectangle.x, window->rectangle.y, wl_surface_damage(window->surface, window->rectangle.x(),
window->rectangle.width, window->rectangle.height); window->rectangle.y(), window->rectangle.width(),
window->rectangle.height());
wl_surface_commit(window->surface); wl_surface_commit(window->surface);
} }
void window_get_width_height(struct window *window, int *w, int *h) { void window_get_width_height(struct window *window, int *w, int *h) {
*w = window->rectangle.width; *w = window->rectangle.width();
*h = window->rectangle.height; *h = window->rectangle.height();
} }
} // namespace conky } // namespace conky

View File

@ -184,7 +184,8 @@ static void X11_create_window() {
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
if (own_window.get(*state)) { if (own_window.get(*state)) {
if (fixed_pos == 0) { if (fixed_pos == 0) {
XMoveWindow(display, window.window, window.geometry.x, window.geometry.y); XMoveWindow(display, window.window, window.geometry.x(),
window.geometry.y());
} }
set_transparent_background(window.window); set_transparent_background(window.window);
@ -278,7 +279,7 @@ bool display_output_x11::main_loop_wait(double t) {
vec2i border_total = vec2i::uniform(get_border_total()); vec2i border_total = vec2i::uniform(get_border_total());
if (need_to_update != 0) { if (need_to_update != 0) {
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
auto old_pos = window.geometry.pos; auto old_pos = window.geometry.pos();
#endif #endif
need_to_update = 0; need_to_update = 0;
@ -292,11 +293,11 @@ bool display_output_x11::main_loop_wait(double t) {
/* resize window if it isn't right size */ /* resize window if it isn't right size */
vec2<long> border_size = border_total * 2; vec2<long> border_size = border_total * 2;
if ((fixed_size == 0) && if ((fixed_size == 0) &&
(text_size + border_size != window.geometry.size)) { (text_size + border_size != window.geometry.size())) {
window.geometry.size = text_size + border_size; window.geometry.set_size(text_size + border_size);
draw_stuff(); /* redraw everything in our newly sized window */ draw_stuff(); /* redraw everything in our newly sized window */
XResizeWindow(display, window.window, window.geometry.width, XResizeWindow(display, window.window, window.geometry.width(),
window.geometry.height); /* resize window */ window.geometry.height()); /* resize window */
set_transparent_background(window.window); set_transparent_background(window.window);
#ifdef BUILD_XDBE #ifdef BUILD_XDBE
/* swap buffers */ /* swap buffers */
@ -305,8 +306,8 @@ bool display_output_x11::main_loop_wait(double t) {
if (use_xpmdb.get(*state)) { if (use_xpmdb.get(*state)) {
XFreePixmap(display, window.back_buffer); XFreePixmap(display, window.back_buffer);
window.back_buffer = XCreatePixmap( window.back_buffer = XCreatePixmap(
display, window.window, window.geometry.width, display, window.window, window.geometry.width(),
window.geometry.height, DefaultDepth(display, screen)); window.geometry.height(), DefaultDepth(display, screen));
if (window.back_buffer != None) { if (window.back_buffer != None) {
window.drawable = window.back_buffer; window.drawable = window.back_buffer;
@ -316,7 +317,7 @@ bool display_output_x11::main_loop_wait(double t) {
} }
XSetForeground(display, window.gc, 0); XSetForeground(display, window.gc, 0);
XFillRectangle(display, window.drawable, window.gc, 0, 0, XFillRectangle(display, window.drawable, window.gc, 0, 0,
window.geometry.width, window.geometry.height); window.geometry.width(), window.geometry.height());
} }
#endif #endif
@ -326,9 +327,9 @@ bool display_output_x11::main_loop_wait(double t) {
} }
/* move window if it isn't in right position */ /* move window if it isn't in right position */
if ((fixed_pos == 0) && old_pos != window.geometry.pos) { if ((fixed_pos == 0) && old_pos != window.geometry.pos()) {
XMoveWindow(display, window.window, window.geometry.x, XMoveWindow(display, window.window, window.geometry.x(),
window.geometry.y); window.geometry.y());
changed++; changed++;
} }
@ -347,11 +348,9 @@ bool display_output_x11::main_loop_wait(double t) {
#else #else
if (use_xpmdb.get(*state)) { if (use_xpmdb.get(*state)) {
#endif #endif
conky::rect<int> r(text_start, text_size); XRectangle rect = conky::rect<int>(text_start - border_total,
r.pos -= border_total; text_size + border_total * 2)
r.size += border_total * 2; .to_xrectangle();
XRectangle rect = r.to_xrectangle();
XUnionRectWithRegion(&rect, x11_stuff.region, x11_stuff.region); XUnionRectWithRegion(&rect, x11_stuff.region, x11_stuff.region);
} }
} }
@ -378,11 +377,9 @@ bool display_output_x11::main_loop_wait(double t) {
#else #else
if (use_xpmdb.get(*state)) { if (use_xpmdb.get(*state)) {
#endif #endif
conky::rect<int> r(text_start, text_size); XRectangle rect = conky::rect<int>(text_start - border_total,
r.pos -= border_total; text_size + border_total * 2)
r.size += border_total * 2; .to_xrectangle();
XRectangle rect = r.to_xrectangle();
XUnionRectWithRegion(&rect, x11_stuff.region, x11_stuff.region); XUnionRectWithRegion(&rect, x11_stuff.region, x11_stuff.region);
} }
XSetRegion(display, window.gc, x11_stuff.region); XSetRegion(display, window.gc, x11_stuff.region);
@ -507,13 +504,13 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
if (!cursor_inside) { if (!cursor_inside) {
*consumed = llua_mouse_hook(mouse_crossing_event( *consumed = llua_mouse_hook(mouse_crossing_event(
mouse_event_t::AREA_ENTER, mouse_event_t::AREA_ENTER,
data->pos_absolute - window.geometry.pos, data->pos_absolute)); data->pos_absolute - window.geometry.pos(), data->pos_absolute));
} }
cursor_inside = true; cursor_inside = true;
} else if (cursor_inside) { } else if (cursor_inside) {
*consumed = llua_mouse_hook(mouse_crossing_event( *consumed = llua_mouse_hook(mouse_crossing_event(
mouse_event_t::AREA_LEAVE, data->pos_absolute - window.geometry.pos, mouse_event_t::AREA_LEAVE,
data->pos_absolute)); data->pos_absolute - window.geometry.pos(), data->pos_absolute));
cursor_inside = false; cursor_inside = false;
} }
@ -650,8 +647,8 @@ bool handle_event<x_event_handler::CONFIGURE>(
if (own_window.get(*state)) { if (own_window.get(*state)) {
auto configure_size = vec2i(ev.xconfigure.width, ev.xconfigure.height); auto configure_size = vec2i(ev.xconfigure.width, ev.xconfigure.height);
/* if window size isn't what's expected, set fixed size */ /* if window size isn't what's expected, set fixed size */
if (configure_size != window.geometry.size) { if (configure_size != window.geometry.size()) {
if (window.geometry.size.surface() != 0) { fixed_size = 1; } if (window.geometry.size().surface() != 0) { fixed_size = 1; }
/* clear old stuff before screwing up /* clear old stuff before screwing up
* size and pos */ * size and pos */
@ -660,18 +657,16 @@ bool handle_event<x_event_handler::CONFIGURE>(
{ {
XWindowAttributes attrs; XWindowAttributes attrs;
if (XGetWindowAttributes(display, window.window, &attrs) != 0) { if (XGetWindowAttributes(display, window.window, &attrs) != 0) {
window.geometry.size = vec2i(attrs.width, attrs.height); window.geometry.set_size(attrs.width, attrs.height);
} }
} }
auto border_total = vec2i::uniform(get_border_total() * 2); auto border_total = vec2i::uniform(get_border_total() * 2);
auto new_text_size = window.geometry.size - border_total; text_size = window.geometry.size() - border_total;
text_size = new_text_size;
// don't apply dpi scaling to max pixel size // don't apply dpi scaling to max pixel size
int mw = maximum_width.get(*state); int mw = maximum_width.get(*state);
if (text_size.x > mw && mw > 0) { text_size.x = mw; } if (text_size.x() > mw && mw > 0) { text_size.set_x(mw); }
} }
/* if position isn't what expected, set fixed pos /* if position isn't what expected, set fixed pos
@ -859,9 +854,9 @@ void display_output_x11::cleanup() {
if (window_created == 1) { if (window_created == 1) {
int border_total = get_border_total(); int border_total = get_border_total();
XClearArea(display, window.window, text_start.x - border_total, XClearArea(display, window.window, text_start.x() - border_total,
text_start.y - border_total, text_size.x + 2 * border_total, text_start.y() - border_total, text_size.x() + 2 * border_total,
text_size.y + 2 * border_total, 0); text_size.y() + 2 * border_total, 0);
} }
destroy_window(); destroy_window();
free_fonts(utf8_mode.get(*state)); free_fonts(utf8_mode.get(*state));
@ -963,7 +958,7 @@ void display_output_x11::draw_arc(int x, int y, int w, int h, int a1, int a2) {
void display_output_x11::move_win(int x, int y) { void display_output_x11::move_win(int x, int y) {
#ifdef OWN_WINDOW #ifdef OWN_WINDOW
window.geometry.pos = vec2i(x, y); window.geometry.set_pos(x, y);
XMoveWindow(display, window.window, x, y); XMoveWindow(display, window.window, x, y);
#endif /* OWN_WINDOW */ #endif /* OWN_WINDOW */
} }
@ -1000,9 +995,9 @@ void display_output_x11::clear_text(int exposures) {
/* there is some extra space for borders and outlines */ /* there is some extra space for borders and outlines */
int border_total = get_border_total(); int border_total = get_border_total();
XClearArea(display, window.window, text_start.x - border_total, XClearArea(display, window.window, text_start.x() - border_total,
text_start.y - border_total, text_size.x + 2 * border_total, text_start.y() - border_total, text_size.x() + 2 * border_total,
text_size.y + 2 * border_total, exposures != 0 ? True : 0); text_size.y() + 2 * border_total, exposures != 0 ? True : 0);
} }
} }

View File

@ -10,6 +10,7 @@
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdlib>
#include <limits> #include <limits>
#include <numeric> #include <numeric>
#include <type_traits> #include <type_traits>
@ -22,60 +23,43 @@
namespace conky { namespace conky {
namespace _priv_geom { namespace _priv_geom {
/// @brief Member access wrapper for containers of values. /// @brief Constructs an index assignable type from an array with different
/// value types using `static_cast`.
/// ///
/// Emulates member access to abstract away the fact that components might not /// Panics at runtime if `O` can be indexed by every value in range `0` to
/// be discrete `T` types. /// (excluding) `Length`.
/// ///
/// This is implementation detail for `geometry.h` and not intended to be used /// @tparam Input source array element
/// elsewhere. /// @tparam R target element type
template <typename Container, typename T> /// @tparam Output target container
struct _member_access { /// @tparam Length array length
Container *value; /// @param value array to pad/trim
size_t index; /// @return casted array
template <typename Input, typename R, size_t Length, typename Output>
constexpr _member_access(Container *value, size_t index) inline Output cast_to_assignable(const Input &value, Output &target) {
: value(value), index(index) {} if constexpr (std::is_same_v<Input, Output>) { return value; }
for (size_t i = 0; i < Length; i++) {
/// @brief Converts `_member_access` to `T`. target[i] = static_cast<R>(value.at(i));
inline T operator*() const { return this->value->at(this->index); }
/// @brief Assignment handler for `new_value` to `T` at `index`.
inline const _member_access &operator=(T new_value) const {
this->value->set(this->index, new_value);
return *this;
} }
return target;
}
#define ASSIGN_OP_IMPL(assign_op_name, application) \ /// @brief Constructs a casted array from an array with different value types
inline T assign_op_name(T other) const { \ /// using `static_cast`.
this->value->set(this->index, \ ///
this->value->at(this->index) application other); \
return *this; \
}
ASSIGN_OP_IMPL(operator+=, +)
ASSIGN_OP_IMPL(operator-=, -)
ASSIGN_OP_IMPL(operator*=, *)
ASSIGN_OP_IMPL(operator/=, /)
#undef ASSIGN_OP_IMPL
/// @brief Converts `_member_access` to `T`.
inline operator T() const { return this->value->at(this->index); }
};
/// @brief Takes an array and pads/trims it to the desired length by inserting
/// zeros or discarding unwanted elements
/// @tparam T source array element /// @tparam T source array element
/// @tparam R target array element /// @tparam R target array element
/// @tparam Length array length /// @tparam Length array length
/// @param value array to pad/trim /// @param value array to pad/trim
/// @return padded/trimmed array /// @return casted array
template <typename T, typename R, size_t Length> template <typename T, typename R, size_t Length>
std::array<R, Length> cast_array(std::array<T, Length> value) { inline std::array<R, Length> cast_array(const std::array<T, Length> &value) {
static_assert(std::is_convertible_v<T, R>, "T is not convertible to R"); static_assert(std::is_convertible_v<T, R>, "T is not convertible to R");
if constexpr (std::is_same_v<T, R>) { return value; } if constexpr (std::is_same_v<T, R>) { return value; }
std::array<R, Length> buff; std::array<R, Length> result;
std::copy_n(value.begin(), Length, buff.begin()); cast_to_assignable<std::array<T, Length>, R, Length, std::array<R, Length>>(
return buff; value, result);
return result;
} }
/// @brief Takes an array and pads/trims it to the desired length by inserting /// @brief Takes an array and pads/trims it to the desired length by inserting
@ -86,39 +70,12 @@ std::array<R, Length> cast_array(std::array<T, Length> value) {
/// @param value array to pad/trim /// @param value array to pad/trim
/// @return padded/trimmed array /// @return padded/trimmed array
template <typename T, size_t Source, size_t Target> template <typename T, size_t Source, size_t Target>
std::array<T, Target> resize_array(std::array<T, Source> value) { inline std::array<T, Target> resize_array(std::array<T, Source> value) {
if constexpr (Source == Target) { return value; } if constexpr (Source == Target) { return value; }
auto buff = std::array<T, Target>{0}; auto buff = std::array<T, Target>{0};
std::copy_n(value.begin(), std::min(Source, Target), buff.begin()); std::copy_n(value.begin(), std::min(Source, Target), buff.begin());
return buff; return buff;
} }
class _no_z_member {};
template <typename Of, typename T>
struct _has_z_member {
static_assert(std::is_arithmetic_v<T>,
"vector z member type (T) must be a number");
using ComponentRef = _member_access<Of, T>;
/// @brief vec z value.
///
/// Treat it as `T`. Use `*z` in case type coertion is needed.
const ComponentRef z = ComponentRef(this, 2);
};
class _no_w_member {};
template <typename Of, typename T>
struct _has_w_member {
static_assert(std::is_arithmetic_v<T>,
"vector w member type (T) must be a number");
using ComponentRef = _member_access<Of, T>;
/// @brief vec w value.
///
/// Treat it as `T`. Use `*w` in case type coertion is needed.
const ComponentRef w = ComponentRef(this, 3);
};
} // namespace _priv_geom } // namespace _priv_geom
/// @brief A 2D vector representation. /// @brief A 2D vector representation.
@ -129,15 +86,7 @@ struct _has_w_member {
/// ///
/// @tparam T numeric component type. /// @tparam T numeric component type.
template <typename T, size_t Length> template <typename T, size_t Length>
struct vec struct vec {
// conditionally add z member accessor
: public std::conditional_t<(Length >= 3),
_priv_geom::_has_z_member<vec<T, Length>, T>,
_priv_geom::_no_z_member>,
// conditionally add w member accessor
public std::conditional_t<(Length >= 4),
_priv_geom::_has_w_member<vec<T, Length>, T>,
_priv_geom::_no_w_member> {
static_assert(std::is_arithmetic_v<T>, "T must be a number"); static_assert(std::is_arithmetic_v<T>, "T must be a number");
static_assert(Length >= 2, "Length must be greater than 2"); static_assert(Length >= 2, "Length must be greater than 2");
@ -149,23 +98,19 @@ struct vec
class _disabled {}; class _disabled {};
protected: protected:
using ComponentRef = _priv_geom::_member_access<vec<T, Length>, T>;
using Data = Vc::array<T, Length>; using Data = Vc::array<T, Length>;
Data value; Data value;
public: public:
vec() : value(Data{0}) {} vec() : value(Data{0}) {}
vec(Data value) : value(value) {} vec(const Data &value) : value(value) {}
vec(std::array<T, Length> array) { vec(std::array<T, Length> array) {
Vc::array<T, Length> vc_array; _priv_geom::cast_to_assignable<std::array<T, Length>, T, Length,
for (size_t i = 0; i < Length; ++i) { vc_array[i] = array[i]; } Vc::array<T, Length>>(array, this->value);
this->value = vc_array;
} }
template <typename O = T> vec(const vec<T, Length> &other) : vec(other.value) {}
vec(vec<O, Length> other)
: vec(_priv_geom::cast_array<O, T, Length>(other.to_array())) {}
vec(T x, T y) : vec<T, 2>(std::array<T, 2>{x, y}) { vec(T x, T y) : vec<T, 2>(std::array<T, 2>{x, y}) {
static_assert(Length == 2, "constructor only valid for vec2<T>"); static_assert(Length == 2, "constructor only valid for vec2<T>");
@ -177,16 +122,12 @@ struct vec
static_assert(Length == 4, "constructor only valid for vec4<T>"); static_assert(Length == 4, "constructor only valid for vec4<T>");
} }
vec(vec<T, Length> &&other) { this->value = other->value; }
static inline vec<T, Length> uniform(T x) { static inline vec<T, Length> uniform(T x) {
return vec<T, Length>(std::array<T, Length>{x}); return vec<T, Length>(std::array<T, Length>{x});
} }
std::array<T, Length> to_array() const {
std::array<T, Length> result;
for (size_t i = 0; i < Length; ++i) { result[i] = this->value[i]; }
return result;
}
/// @brief Returns vec component at `index`. /// @brief Returns vec component at `index`.
/// @param index component index. /// @param index component index.
/// @return component at `index` of this vec. /// @return component at `index` of this vec.
@ -194,19 +135,19 @@ struct vec
/// @brief vec x component. /// @brief vec x component.
/// @return x value of this vec. /// @return x value of this vec.
inline T get_x() const { return this->at(0); } inline T x() const { return this->at(0); }
/// @brief vec y component. /// @brief vec y component.
/// @return y value of this vec. /// @return y value of this vec.
inline T get_y() const { return this->at(1); } inline T y() const { return this->at(1); }
/// @brief vec z component. /// @brief vec z component.
/// @return z value of this vec. /// @return z value of this vec.
inline T get_z() const { inline T z() const {
static_assert(Length >= 3, "vector doesn't have a z component"); static_assert(Length >= 3, "vector doesn't have a z component");
return this->at(2); return this->at(2);
} }
/// @brief vec w component. /// @brief vec w component.
/// @return w value of this vec. /// @return w value of this vec.
inline T get_w() const { inline T w() const {
static_assert(Length >= 4, "vector doesn't have a w component"); static_assert(Length >= 4, "vector doesn't have a w component");
return this->at(3); return this->at(3);
} }
@ -224,45 +165,21 @@ struct vec
this->set(3, new_value); this->set(3, new_value);
} }
/// @brief vec x value. vec<T, Length> &operator=(const vec<T, Length> &other) {
///
/// Treat it as `T`. Use `*x` in case type coertion is needed.
const ComponentRef x = ComponentRef(this, 0);
/// @brief vec y value.
///
/// Treat it as `T`. Use `*y` in case type coertion is needed.
const ComponentRef y = ComponentRef(this, 1);
// z & w are conditionally defined by _has_z_member and _has_w_member in
// _priv_geom because member templates aren't allowed.
vec<T, Length> &operator=(vec<T, Length> other) {
this->value = other.value; this->value = other.value;
return *this; return *this;
} }
vec<T, Length> &operator=(vec<T, Length> &&other) {
this->value = std::move(other.value);
return *this;
}
template <typename O = T> template <typename O = T>
vec<T, Length> &operator=(std::array<O, Length> other) { vec<T, Length> &operator=(std::array<O, Length> other) {
Data buffer = _priv_geom::cast_array(other); _priv_geom::cast_to_assignable(other, this->value);
this->value = buffer;
return *this; return *this;
} }
inline const ComponentRef &operator[](size_t index) { inline T operator[](size_t index) { return this->at(index); }
assert_print(index < std::min(Length, static_cast<size_t>(4)),
"index out of bounds");
switch (index) {
case 0:
return this->x;
case 1:
return this->y;
case 2:
return this->z;
case 3:
return this->w;
default:
UNREACHABLE();
}
}
/// @brief Zero vector value. /// @brief Zero vector value.
static vec<T, Length> Zero() { return vec<T, Length>::uniform(0); } static vec<T, Length> Zero() { return vec<T, Length>::uniform(0); }
@ -295,6 +212,9 @@ struct vec
return vec(buffer); return vec(buffer);
} }
// NOTE: All of the following loops will get unrolled by the compiler because
// Length is a constant expression (unless Length is very large).
inline vec<T, Length> operator+(vec<T, Length> other) const { inline vec<T, Length> operator+(vec<T, Length> other) const {
Data result{this->value}; Data result{this->value};
for (size_t i = 0; i < Length; i++) { result[i] += other.value[i]; } for (size_t i = 0; i < Length; i++) { result[i] += other.value[i]; }
@ -378,6 +298,28 @@ struct vec
} }
} }
/// @brief Computes component-wise vector minimum
/// @param other other vector
/// @returns new vector with min values
inline vec<T, Length> min(const vec<T, Length> &other) {
Data result{this->value};
for (size_t i = 0; i < Length; i++) {
result[i] = std::min(result[i], other.value[i]);
}
return vec<T, Length>(result);
}
/// @brief Computes component-wise vector maximum
/// @param other other vector
/// @returns new vector with max values
inline vec<T, Length> max(const vec<T, Length> &other) {
Data result{this->value};
for (size_t i = 0; i < Length; i++) {
result[i] = std::max(result[i], other.value[i]);
}
return vec<T, Length>(result);
}
inline T distance_squared(vec<T, Length> other) const { inline T distance_squared(vec<T, Length> other) const {
vec<T, Length> buffer = other - *this; vec<T, Length> buffer = other - *this;
buffer *= buffer; buffer *= buffer;
@ -394,8 +336,28 @@ struct vec
T surface() const { T surface() const {
static_assert(Length == 2, "surface computable only for 2D vectors"); static_assert(Length == 2, "surface computable only for 2D vectors");
return this->get_x() * this->get_y(); return this->x() * this->y();
} }
template <typename O>
vec<O, Length> cast() const {
Vc::array<O, Length> buffer;
_priv_geom::cast_to_assignable<Vc::array<T, Length>, O, Length,
Vc::array<O, Length>>(this->value, buffer);
return vec<O, Length>(buffer);
}
std::array<T, Length> to_array() const {
std::array<T, Length> result;
for (size_t i = 0; i < Length; ++i) { result[i] = this->value[i]; }
return result;
}
template <typename O>
operator vec<O, Length>() const {
return this->cast<O>();
}
operator std::array<T, Length>() const { return this->to_array(); }
}; };
template <typename T> template <typename T>
@ -414,33 +376,76 @@ using vec4f = vec4<float>;
using vec4d = vec4<double>; using vec4d = vec4<double>;
using vec4i = vec4<std::int32_t>; using vec4i = vec4<std::int32_t>;
enum class rect_kind {
SIZED,
ABSOLUTE,
};
/// @brief 2D rectangle representation using position and size vectors. /// @brief 2D rectangle representation using position and size vectors.
/// @tparam T component number type. /// @tparam T component number type.
template <typename T = std::int32_t> template <typename T = std::int32_t, rect_kind Kind = rect_kind::SIZED>
struct rect { struct rect {
static_assert(std::is_arithmetic_v<T>, "T must be a number"); static_assert(std::is_arithmetic_v<T>, "T must be a number");
using Component = T; using Component = T;
using ComponentRef = _priv_geom::_member_access<rect<T>, T>;
vec2<T> pos; private:
vec2<T> size; vec2<T> m_pos;
vec2<T> m_other;
rect() : pos(vec2<T>::Zero()), size(vec2<T>::Zero()) {} public:
rect(vec2<T> pos, vec2<T> size) : pos(pos), size(size) {} rect() : m_pos(vec2<T>::Zero()), m_other(vec2<T>::Zero()) {}
rect(vec2<T> pos, vec2<T> other) : m_pos(pos), m_other(other) {}
/// @brief Rectangle x position. /// @brief Rectangle x position.
/// @return x position of this rectangle. /// @return x position of this rectangle.
T get_x() const { return this->pos.get_x(); } inline T x() const { return this->m_pos.x(); }
/// @brief Rectangle y position. /// @brief Rectangle y position.
/// @return y position of this rectangle. /// @return y position of this rectangle.
T get_y() const { return this->pos.get_y(); } inline T y() const { return this->m_pos.y(); }
inline vec2<T> pos() const { return this->m_pos; }
inline vec2<T> size() const {
if constexpr (Kind == rect_kind::SIZED) {
return this->m_other;
} else {
return this->m_other - this->m_pos;
}
}
inline vec2<T> end_pos() const {
if constexpr (Kind == rect_kind::SIZED) {
return this->m_pos + this->m_other;
} else {
return this->m_other;
}
}
/// @brief Rectangle end x position.
/// @return ending x position of this rectangle.
inline T end_x() const { return this->end_pos().x(); }
/// @brief Rectangle end y position.
/// @return ending y position of this rectangle.
inline T end_y() const { return this->end_pos().y(); }
/// @brief Rectangle width. /// @brief Rectangle width.
/// @return width of this rectangle. /// @return width of this rectangle.
T get_width() const { return this->size.get_x(); } inline T width() const {
if constexpr (Kind == rect_kind::SIZED) {
return this->m_other.x();
} else {
return this->m_other.x() + this->m_pos.x();
}
}
/// @brief Rectangle height. /// @brief Rectangle height.
/// @return height of this rectangle. /// @return height of this rectangle.
T get_height() const { return this->size.get_y(); } inline T height() const {
if constexpr (Kind == rect_kind::SIZED) {
return this->m_other.y();
} else {
return this->m_other.y() + this->m_pos.y();
}
}
/// @brief Returns rectangle component at `index`. /// @brief Returns rectangle component at `index`.
/// @param index component index. /// @param index component index.
@ -449,123 +454,200 @@ struct rect {
assert_print(index < static_cast<size_t>(4), "index out of bounds"); assert_print(index < static_cast<size_t>(4), "index out of bounds");
switch (index) { switch (index) {
case 0: case 0:
return this->get_x(); return this->m_pos.x();
case 1: case 1:
return this->get_y(); return this->m_pos.y();
case 2: case 2:
return this->get_width(); return this->m_other.x();
case 3: case 3:
return this->get_height(); return this->m_other.y();
default: default:
UNREACHABLE(); UNREACHABLE();
} }
} }
void set_x(T value) { this->pos.set_x(value); } inline void set_pos(vec2<T> value) { this->m_pos = value; }
void set_y(T value) { this->pos.set_y(value); } inline void set_pos(T x, T y) { this->set_pos(vec2<T>(x, y)); }
void set_width(T value) { this->size.set_x(value); } inline void set_size(vec2<T> value) {
void set_height(T value) { this->size.set_y(value); } if constexpr (Kind == rect_kind::SIZED) {
this->m_other = value;
} else {
this->m_other = this->m_pos + value;
}
}
inline void set_size(T width, T height) {
this->set_size(vec2<T>(width, height));
}
inline void set_end_pos(vec2<T> value) {
if constexpr (Kind == rect_kind::SIZED) {
this->m_other = value - this->m_pos;
} else {
this->m_other = value;
}
}
inline void set_end_pos(T x, T y) { this->set_end_pos(vec2<T>(x, y)); }
inline void set_x(T value) { this->m_pos.set_x(value); }
inline void set_y(T value) { this->m_pos.set_y(value); }
inline void set_width(T value) {
if constexpr (Kind == rect_kind::SIZED) {
this->other.set_x(value);
} else {
this->other.set_x(this->m_pos.get_x() + value);
}
}
inline void set_height(T value) {
if constexpr (Kind == rect_kind::SIZED) {
this->m_other.set_y(value);
} else {
this->m_other.set_y(this->m_pos.get_y() + value);
}
}
inline void set_end_x(T value) {
if constexpr (Kind == rect_kind::SIZED) {
this->m_other.set_x(value - this->m_pos.get_x());
} else {
this->m_other.set_x(value);
}
}
inline void set_end_y(T value) {
if constexpr (Kind == rect_kind::SIZED) {
this->m_other.set_y(value - this->m_pos.get_y());
} else {
this->m_other.set_y(value);
}
}
void set(size_t index, T value) { void set(size_t index, T value) {
assert_print(index < static_cast<size_t>(4), "index out of bounds"); assert_print(index < static_cast<size_t>(4), "index out of bounds");
switch (index) { switch (index) {
case 0: case 0:
return this->set_x(value); return this->m_pos.set_x(value);
case 1: case 1:
return this->set_y(value); return this->m_pos.set_y(value);
case 2: case 2:
return this->set_width(value); return this->m_other.set_x(value);
case 3: case 3:
return this->set_height(value); return this->m_other.set_y(value);
default: default:
UNREACHABLE(); UNREACHABLE();
} }
} }
/// @brief rectangle position x value.
///
/// Treat it as `T`. Use `*x` in case type coertion is needed.
const ComponentRef x = ComponentRef(this, 0);
/// @brief rectangle position y value.
///
/// Treat it as `T`. Use `*y` in case type coertion is needed.
const ComponentRef y = ComponentRef(this, 1);
/// @brief rectangle width value.
///
/// Treat it as `T`. Use `*width` in case type coertion is needed.
const ComponentRef width = ComponentRef(this, 2);
/// @brief rectangle height value.
///
/// Treat it as `T`. Use `*height` in case type coertion is needed.
const ComponentRef height = ComponentRef(this, 3);
std::array<vec2<T>, 4> corners() const { std::array<vec2<T>, 4> corners() const {
return std::array<vec2<T>, 4>{ return std::array<vec2<T>, 4>{
this->pos, this->m_pos,
this->pos + vec2<T>(this->get_width(), 0), this->m_pos + vec2<T>(this->get_width(), 0),
this->pos + this->size, this->get_end_pos(),
this->pos + vec2<T>(0, this->get_height()), this->m_pos + vec2<T>(0, this->get_height()),
}; };
} }
template <typename O = T> template <typename O = T>
bool contains(vec2<O> p) const { bool contains(vec2<O> p) const {
return p.get_x() >= this->get_x() && return p.x() >= this->x() && p.x() < this->x() + this->width() &&
p.get_x() < this->get_x() + this->get_width() && p.y() >= this->y() && p.y() < this->y() + this->height();
p.get_y() >= this->get_y() &&
p.get_y() < this->get_y() + this->get_height();
} }
template <typename O = T> template <typename O = T>
bool contains(rect<O> other) const { bool contains(rect<O> other) const {
return contains(other.pos) && return contains(other.m_pos) &&
contains(other.pos + vec2<O>(other.get_width(), 0)) && contains(other.m_pos + vec2<O>(other.width(), 0)) &&
contains(other.pos + other.size) && contains(other.m_pos + other.m_other) &&
contains(other.pos + vec2<O>(0, other.get_height())); contains(other.m_pos + vec2<O>(0, other.height()));
} }
private: private:
template <typename O = T> template <typename O = T>
bool _intersects_partial(rect<O> other) const { bool _intersects_partial(rect<O> other) const {
return contains(other.pos) || return contains(other.m_pos) ||
contains(other.pos + vec2<O>(other.get_width(), 0)) || contains(other.m_pos + vec2<O>(other.width(), 0)) ||
contains(other.pos + other.size) || contains(other.m_pos + other.m_other) ||
contains(other.pos + vec2<O>(0, other.get_height())); contains(other.m_pos + vec2<O>(0, other.height()));
} }
public: public:
template <typename O = T> template <typename O = T>
bool intersects(rect<O> other) const { bool intersects(rect<O> other) const {
return this->_intersects_partial(other) || other._intersects_partial(*this); return this->_intersects_partial(m_other) ||
other._intersects_partial(*this);
} }
constexpr const ComponentRef &operator[](size_t index) { rect<T, Kind> &operator=(const rect<T, Kind> &other) {
assert_print(index < static_cast<size_t>(4), "index out of bounds"); this->m_pos = other.m_pos;
switch (index) { this->m_other = other.m_other;
case 0: return *this;
return this->x; }
case 1: rect<T, Kind> &operator=(rect<T, Kind> &&other) {
return this->y; this->m_pos = other.m_pos;
case 2: this->m_other = other.m_other;
return this->width; return *this;
case 3: }
return this->height; template <typename O = T>
default: rect<T, Kind> &operator=(std::array<O, 4> other) {
UNREACHABLE(); _priv_geom::cast_to_assignable(other.m_pos, this->m_pos);
_priv_geom::cast_to_assignable(other.m_other, this->m_other);
return *this;
}
inline T operator[](size_t index) {
if (index < 2) {
return this->m_pos[index];
} else if (index < 4) {
return this->m_other[index - 2];
} else {
CRIT_ERR("index out of bounds");
} }
} }
#ifdef BUILD_X11 #ifdef BUILD_X11
XRectangle to_xrectangle() const { XRectangle to_xrectangle() const {
return XRectangle{ return XRectangle{.x = static_cast<short>(this->x()),
.x = static_cast<short>(this->get_x()), .y = static_cast<short>(this->y()),
.y = static_cast<short>(this->get_y()), .width = static_cast<unsigned short>(this->width()),
.width = static_cast<unsigned short>(this->get_width()), .height = static_cast<unsigned short>(this->height())};
.height = static_cast<unsigned short>(this->get_height())};
} }
#endif /* BUILD_X11 */ #endif /* BUILD_X11 */
rect<T, rect_kind::SIZED> to_sized() const {
if constexpr (Kind == rect_kind::SIZED) {
return *this;
} else {
return rect<T, rect_kind::SIZED>{this->m_pos,
this->m_other - this->m_pos};
}
}
rect<T, rect_kind::ABSOLUTE> to_absolute() const {
if constexpr (Kind == rect_kind::ABSOLUTE) {
return *this;
} else {
return rect<T, rect_kind::ABSOLUTE>{this->m_pos,
this->m_pos + this->m_other};
}
}
std::array<T, 4> to_array() const {
return std::array<T, 4>{this->m_pos.x(), this->m_pos.y(), this->m_other.x(),
this->m_other.y()};
}
inline operator std::array<T, 4>() const { return this->to_array(); }
inline explicit operator rect<T, rect_kind::SIZED>() const {
return this->to_sized();
}
inline explicit operator rect<T, rect_kind::ABSOLUTE>() const {
return this->to_absolute();
}
}; };
template <typename T>
using sized_rect = rect<T>;
template <typename T>
using absolute_rect = rect<T, rect_kind::ABSOLUTE>;
} // namespace conky } // namespace conky
#endif /* _CONKY_GEOMETRY_H_ */ #endif /* _CONKY_GEOMETRY_H_ */

View File

@ -49,7 +49,7 @@
#endif #endif
/* workarea where window / text is aligned (from _NET_WORKAREA on X11) */ /* workarea where window / text is aligned (from _NET_WORKAREA on X11) */
conky::rect<int> workarea; conky::absolute_rect<int> workarea;
/* Window stuff */ /* Window stuff */
char window_created = 0; char window_created = 0;

View File

@ -161,7 +161,7 @@ inline bool TEST_HINT(uint16_t mask, window_hints hint) {
} }
#endif #endif
extern conky::rect<int> workarea; extern conky::absolute_rect<int> workarea;
extern char window_created; extern char window_created;

View File

@ -593,17 +593,17 @@ void llua_setup_window_table(conky::rect<int> text_rect) {
#ifdef BUILD_GUI #ifdef BUILD_GUI
if (out_to_gui(*state)) { if (out_to_gui(*state)) {
#ifdef BUILD_X11 #ifdef BUILD_X11
llua_set_number("width", window.geometry.width); llua_set_number("width", window.geometry.width());
llua_set_number("height", window.geometry.height); llua_set_number("height", window.geometry.height());
#endif /*BUILD_X11*/ #endif /*BUILD_X11*/
llua_set_number("border_inner_margin", border_inner_margin.get(*state)); llua_set_number("border_inner_margin", border_inner_margin.get(*state));
llua_set_number("border_outer_margin", border_outer_margin.get(*state)); llua_set_number("border_outer_margin", border_outer_margin.get(*state));
llua_set_number("border_width", border_width.get(*state)); llua_set_number("border_width", border_width.get(*state));
llua_set_number("text_start_x", text_rect.x); llua_set_number("text_start_x", text_rect.x());
llua_set_number("text_start_y", text_rect.y); llua_set_number("text_start_y", text_rect.y());
llua_set_number("text_width", text_rect.width); llua_set_number("text_width", text_rect.width());
llua_set_number("text_height", text_rect.height); llua_set_number("text_height", text_rect.height());
lua_setglobal(lua_L, "conky_window"); lua_setglobal(lua_L, "conky_window");
} }
@ -621,14 +621,14 @@ void llua_update_window_table(conky::rect<int> text_rect) {
} }
#ifdef BUILD_X11 #ifdef BUILD_X11
llua_set_number("width", window.geometry.width); llua_set_number("width", window.geometry.width());
llua_set_number("height", window.geometry.height); llua_set_number("height", window.geometry.height());
#endif /*BUILD_X11*/ #endif /*BUILD_X11*/
llua_set_number("text_start_x", text_rect.x); llua_set_number("text_start_x", text_rect.x());
llua_set_number("text_start_y", text_rect.y); llua_set_number("text_start_y", text_rect.y());
llua_set_number("text_width", text_rect.width); llua_set_number("text_width", text_rect.width());
llua_set_number("text_height", text_rect.height); llua_set_number("text_height", text_rect.height());
lua_setglobal(lua_L, "conky_window"); lua_setglobal(lua_L, "conky_window");
} }

View File

@ -191,10 +191,10 @@ void mouse_event::push_lua_table(lua_State *L) const {
} }
void mouse_positioned_event::push_lua_data(lua_State *L) const { void mouse_positioned_event::push_lua_data(lua_State *L) const {
push_table_value(L, "x", this->pos.x); push_table_value(L, "x", this->pos.x());
push_table_value(L, "y", this->pos.y); push_table_value(L, "y", this->pos.y());
push_table_value(L, "x_abs", this->pos_absolute.x); push_table_value(L, "x_abs", this->pos_absolute.x());
push_table_value(L, "y_abs", this->pos_absolute.y); push_table_value(L, "y_abs", this->pos_absolute.y());
} }
void mouse_move_event::push_lua_data(lua_State *L) const { void mouse_move_event::push_lua_data(lua_State *L) const {
@ -523,10 +523,10 @@ std::vector<std::tuple<int, XEvent *>> xi_event_data::generate_events(
e->window = target; e->window = target;
e->subwindow = child; e->subwindow = child;
e->time = CurrentTime; e->time = CurrentTime;
e->x = static_cast<int>(target_pos.x); e->x = static_cast<int>(target_pos.x());
e->y = static_cast<int>(target_pos.y); e->y = static_cast<int>(target_pos.y());
e->x_root = static_cast<int>(this->pos_absolute.x); e->x_root = static_cast<int>(this->pos_absolute.x());
e->y_root = static_cast<int>(this->pos_absolute.y); e->y_root = static_cast<int>(this->pos_absolute.y());
e->state = this->mods.effective; e->state = this->mods.effective;
e->is_hint = NotifyNormal; e->is_hint = NotifyNormal;
e->same_screen = True; e->same_screen = True;
@ -556,10 +556,10 @@ std::vector<std::tuple<int, XEvent *>> xi_event_data::generate_events(
e->window = target; e->window = target;
e->subwindow = child; e->subwindow = child;
e->time = CurrentTime; e->time = CurrentTime;
e->x = static_cast<int>(target_pos.x); e->x = static_cast<int>(target_pos.x());
e->y = static_cast<int>(target_pos.y); e->y = static_cast<int>(target_pos.y());
e->x_root = static_cast<int>(this->pos_absolute.x); e->x_root = static_cast<int>(this->pos_absolute.x());
e->y_root = static_cast<int>(this->pos_absolute.y); e->y_root = static_cast<int>(this->pos_absolute.y());
e->state = this->mods.effective; e->state = this->mods.effective;
e->button = scroll_direction; e->button = scroll_direction;
e->same_screen = True; e->same_screen = True;
@ -582,10 +582,10 @@ std::vector<std::tuple<int, XEvent *>> xi_event_data::generate_events(
e->window = target; e->window = target;
e->subwindow = child; e->subwindow = child;
e->time = CurrentTime; e->time = CurrentTime;
e->x = static_cast<int>(target_pos.x); e->x = static_cast<int>(target_pos.x());
e->y = static_cast<int>(target_pos.y); e->y = static_cast<int>(target_pos.y());
e->x_root = static_cast<int>(this->pos_absolute.x); e->x_root = static_cast<int>(this->pos_absolute.x());
e->y_root = static_cast<int>(this->pos_absolute.y); e->y_root = static_cast<int>(this->pos_absolute.y());
e->state = this->mods.effective; e->state = this->mods.effective;
e->button = this->detail; e->button = this->detail;
e->same_screen = True; e->same_screen = True;

View File

@ -226,7 +226,7 @@ char *find_and_replace_templates(const char *inbuf) {
outlen += len; outlen += len;
*o = '\0'; *o = '\0';
outbuf = static_cast<char *>(realloc(outbuf, outlen * sizeof(char))); outbuf = static_cast<char *>(realloc(outbuf, outlen * sizeof(char)));
strncat(outbuf, tmpl_out, len); strcat(outbuf, tmpl_out);
free(tmpl_out); free(tmpl_out);
o = outbuf + strlen(outbuf); o = outbuf + strlen(outbuf);
} else { } else {

View File

@ -180,8 +180,12 @@ static int x11_error_handler(Display *d, XErrorEvent *err) {
error_name, reinterpret_cast<uint64_t>(err->display), error_name, reinterpret_cast<uint64_t>(err->display),
static_cast<int64_t>(err->resourceid), err->serial, code_description); static_cast<int64_t>(err->resourceid), err->serial, code_description);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
// *_allocated takes care of avoiding freeing unallocated objects
if (name_allocated) delete[] error_name; if (name_allocated) delete[] error_name;
if (code_allocated) delete[] code_description; if (code_allocated) delete[] code_description;
#pragma GCC diagnostic pop
return 0; return 0;
} }
@ -321,9 +325,9 @@ void update_x11_resource_db(bool first_run) {
void update_x11_workarea() { void update_x11_workarea() {
/* default work area is display */ /* default work area is display */
workarea.pos = conky::vec2i(); workarea = conky::absolute_rect<int>(
workarea.width = DisplayWidth(display, screen); conky::vec2i::Zero(), conky::vec2i(DisplayWidth(display, screen),
workarea.height = DisplayHeight(display, screen); DisplayHeight(display, screen)));
#ifdef BUILD_XINERAMA #ifdef BUILD_XINERAMA
/* if xinerama is being used, adjust workarea to the head's area */ /* if xinerama is being used, adjust workarea to the head's area */
@ -352,10 +356,8 @@ void update_x11_workarea() {
} }
XineramaScreenInfo *ps = &si[i]; XineramaScreenInfo *ps = &si[i];
workarea[0] = ps->x_org; workarea.set_pos(ps->x_org, ps->y_org);
workarea[1] = ps->y_org; workarea.set_size(ps->width, ps->height);
workarea[2] = workarea[0] + ps->width;
workarea[3] = workarea[1] + ps->height;
XFree(si); XFree(si);
DBGP("Fixed xinerama area to: %d %d %d %d", workarea[0], workarea[1], DBGP("Fixed xinerama area to: %d %d %d %d", workarea[0], workarea[1],
@ -375,8 +377,8 @@ static Window find_desktop_window(Window root) {
int display_height = DisplayHeight(display, screen); int display_height = DisplayHeight(display, screen);
desktop = find_desktop_window_impl(root, display_width, display_height); desktop = find_desktop_window_impl(root, display_width, display_height);
update_x11_workarea(); update_x11_workarea();
desktop = find_desktop_window_impl(desktop, workarea[2] - workarea[0], desktop =
workarea[3] - workarea[1]); find_desktop_window_impl(desktop, workarea.width(), workarea.height());
if (desktop != root) { if (desktop != root) {
NORM_ERR("desktop window (0x%lx) is subwindow of root window (0x%lx)", NORM_ERR("desktop window (0x%lx) is subwindow of root window (0x%lx)",
@ -551,9 +553,9 @@ void x11_init_window(lua::state &l, bool own) {
} }
/* Parent is desktop window (which might be a child of root) */ /* Parent is desktop window (which might be a child of root) */
window.window = XCreateWindow(display, window.desktop, window.geometry.x, window.window = XCreateWindow(
window.geometry.y, b, b, 0, depth, display, window.desktop, window.geometry.x(), window.geometry.y(), b,
InputOutput, visual, flags, &attrs); b, 0, depth, InputOutput, visual, flags, &attrs);
XLowerWindow(display, window.window); XLowerWindow(display, window.window);
XSetClassHint(display, window.window, &classHint); XSetClassHint(display, window.window, &classHint);
@ -592,11 +594,11 @@ void x11_init_window(lua::state &l, bool own) {
} }
if (own_window_type.get(l) == window_type::DOCK) { if (own_window_type.get(l) == window_type::DOCK) {
window.geometry.pos = conky::vec2i::Zero(); window.geometry.set_pos(conky::vec2i::Zero());
} }
/* Parent is root window so WM can take control */ /* Parent is root window so WM can take control */
window.window = XCreateWindow(display, window.root, window.geometry.x, window.window = XCreateWindow(display, window.root, window.geometry.x(),
window.geometry.y, b, b, 0, depth, window.geometry.y(), b, b, 0, depth,
InputOutput, visual, flags, &attrs); InputOutput, visual, flags, &attrs);
uint16_t hints = own_window_hints.get(l); uint16_t hints = own_window_hints.get(l);
@ -793,7 +795,7 @@ void x11_init_window(lua::state &l, bool own) {
if (window.window == None) { window.window = window.desktop; } if (window.window == None) { window.window = window.desktop; }
if (XGetWindowAttributes(display, window.window, &attrs) != 0) { if (XGetWindowAttributes(display, window.window, &attrs) != 0) {
window.geometry.size = conky::vec2i(attrs.width, attrs.height); window.geometry.set_size(attrs.width, attrs.height);
} }
NORM_ERR("drawing to desktop window"); NORM_ERR("drawing to desktop window");
@ -1139,44 +1141,46 @@ void set_struts(alignment align) {
if (strut != None) { if (strut != None) {
long sizes[STRUT_COUNT] = {0}; long sizes[STRUT_COUNT] = {0};
int display_width = workarea[2] - workarea[0]; int display_width = workarea.width();
int display_height = workarea[3] - workarea[1]; int display_height = workarea.height();
switch (horizontal_alignment(align)) { switch (horizontal_alignment(align)) {
case axis_align::START: case axis_align::START:
sizes[*x11_strut::LEFT] = std::clamp( sizes[*x11_strut::LEFT] = std::clamp(
window.geometry.x + window.geometry.width, 0, *workarea.width); window.geometry.x() + window.geometry.end_x(), 0, display_width);
sizes[*x11_strut::LEFT_START_Y] = sizes[*x11_strut::LEFT_START_Y] =
std::clamp(*window.geometry.y, 0, *workarea.height); std::clamp(window.geometry.y(), 0, display_height);
sizes[*x11_strut::LEFT_END_Y] = std::clamp( sizes[*x11_strut::LEFT_END_Y] = std::clamp(
window.geometry.y + window.geometry.height, 0, *workarea.height); window.geometry.y() + window.geometry.height(), 0, display_height);
break; break;
case axis_align::END: case axis_align::END:
sizes[*x11_strut::RIGHT] = sizes[*x11_strut::RIGHT] =
std::clamp(workarea.width - window.geometry.x, 0, *workarea.width); std::clamp(display_width - window.geometry.x(), 0, display_width);
sizes[*x11_strut::RIGHT_START_Y] = sizes[*x11_strut::RIGHT_START_Y] =
std::clamp(*window.geometry.y, 0, *workarea.height); std::clamp(window.geometry.y(), 0, display_height);
sizes[*x11_strut::RIGHT_END_Y] = std::clamp( sizes[*x11_strut::RIGHT_END_Y] = std::clamp(
window.geometry.y + window.geometry.height, 0, *workarea.height); window.geometry.y() + window.geometry.height(), 0, display_height);
break; break;
case axis_align::MIDDLE: case axis_align::MIDDLE:
switch (vertical_alignment(align)) { switch (vertical_alignment(align)) {
case axis_align::START: case axis_align::START:
sizes[*x11_strut::TOP] = sizes[*x11_strut::TOP] =
std::clamp(window.geometry.y + window.geometry.height, 0, std::clamp(window.geometry.y() + window.geometry.height(), 0,
*workarea.height); display_height);
sizes[*x11_strut::TOP_START_X] = sizes[*x11_strut::TOP_START_X] =
std::clamp(*window.geometry.x, 0, *workarea.width); std::clamp(window.geometry.x(), 0, display_width);
sizes[*x11_strut::TOP_END_X] = std::clamp( sizes[*x11_strut::TOP_END_X] =
window.geometry.x + window.geometry.width, 0, *workarea.width); std::clamp(window.geometry.x() + window.geometry.width(), 0,
display_width);
break; break;
case axis_align::END: case axis_align::END:
sizes[*x11_strut::BOTTOM] = std::clamp( sizes[*x11_strut::BOTTOM] = std::clamp(
workarea.height - window.geometry.y, 0, *workarea.height); display_height - window.geometry.y(), 0, display_height);
sizes[*x11_strut::BOTTOM_START_X] = sizes[*x11_strut::BOTTOM_START_X] =
std::clamp(*window.geometry.x, 0, *workarea.width); std::clamp(window.geometry.x(), 0, display_width);
sizes[*x11_strut::BOTTOM_END_X] = std::clamp( sizes[*x11_strut::BOTTOM_END_X] =
window.geometry.x + window.geometry.width, 0, *workarea.width); std::clamp(window.geometry.x() + window.geometry.width(), 0,
display_width);
break; break;
case axis_align::MIDDLE: case axis_align::MIDDLE:
// can't reserve space in middle of the screen // can't reserve space in middle of the screen
@ -1335,7 +1339,7 @@ void propagate_xinput_event(const conky::xi_event_data *ev) {
int read_x, read_y; int read_x, read_y;
// Update event x and y coordinates to be target window relative // Update event x and y coordinates to be target window relative
XTranslateCoordinates(display, window.desktop, ev->event, XTranslateCoordinates(display, window.desktop, ev->event,
ev->pos_absolute.x, ev->pos_absolute.y, &read_x, ev->pos_absolute.x(), ev->pos_absolute.y(), &read_x,
&read_y, &child); &read_y, &child);
target_pos = conky::vec2i(read_x, read_y); target_pos = conky::vec2i(read_x, read_y);
} }
@ -1536,8 +1540,8 @@ std::vector<Window> query_x11_windows_at_pos(
&_ignore); &_ignore);
XGetWindowAttributes(display, current, &attr); XGetWindowAttributes(display, current, &attr);
if (pos_x <= pos.x && pos_y <= pos.y && pos_x + attr.width >= pos.x && if (pos_x <= pos.x() && pos_y <= pos.y() && pos_x + attr.width >= pos.x() &&
pos_y + attr.height >= pos.y && predicate(attr)) { pos_y + attr.height >= pos.y() && predicate(attr)) {
result.push_back(current); result.push_back(current);
} }
} }