mirror of
https://github.com/Llewellynvdm/conky.git
synced 2025-01-29 01:58:26 +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:
parent
968fc7fcbc
commit
2d50767216
@ -51,7 +51,10 @@ if(MAINTAINER_MODE)
|
||||
endif(MAINTAINER_MODE)
|
||||
|
||||
# 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++>)
|
||||
|
||||
option(CHECK_CODE_QUALITY "Check code formatting/quality with clang" false)
|
||||
|
2139
src/conky.cc
2139
src/conky.cc
File diff suppressed because it is too large
Load Diff
@ -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):
|
||||
// - kde-output-management(-v2)
|
||||
// - wlr-output-management-unstable-v1
|
||||
workarea.x = x; // TODO: use xdg_output.logical_position
|
||||
workarea.y = y;
|
||||
workarea.width = physical_width;
|
||||
workarea.height = physical_height;
|
||||
workarea = absolute_rect<int>(
|
||||
vec2i(x, y),
|
||||
vec2i(x + physical_width,
|
||||
y + physical_height)); // TODO: use xdg_output.logical_position
|
||||
}
|
||||
|
||||
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) {
|
||||
zwlr_layer_surface_v1_set_size(global_window->layer_surface,
|
||||
global_window->rectangle.width,
|
||||
global_window->rectangle.height);
|
||||
global_window->rectangle.width(),
|
||||
global_window->rectangle.height());
|
||||
}
|
||||
|
||||
#ifdef BUILD_MOUSE_EVENTS
|
||||
@ -428,7 +428,7 @@ static void on_pointer_enter(void *data, wl_pointer *pointer,
|
||||
auto pos =
|
||||
vec2d(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
|
||||
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};
|
||||
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 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};
|
||||
llua_mouse_hook(event);
|
||||
@ -453,7 +453,7 @@ static void on_pointer_motion(void *data, struct wl_pointer *pointer,
|
||||
auto pos =
|
||||
vec2d(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
|
||||
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};
|
||||
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 pos = last_known_positions[pointer];
|
||||
auto pos_abs = w->rectangle.pos + pos;
|
||||
auto pos_abs = w->rectangle.pos() + pos;
|
||||
|
||||
mouse_button_event event{
|
||||
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 pos = last_known_positions[pointer];
|
||||
auto pos_abs = w->rectangle.pos + pos;
|
||||
auto pos_abs = w->rectangle.pos() + pos;
|
||||
|
||||
mouse_scroll_event event{
|
||||
pos,
|
||||
@ -657,19 +657,19 @@ bool display_output_wayland::main_loop_wait(double t) {
|
||||
|
||||
/* resize window if it isn't right size */
|
||||
if ((fixed_size == 0) &&
|
||||
(text_size.x + 2 * border_total != width ||
|
||||
text_size.y + 2 * border_total != height || scale_changed)) {
|
||||
(text_size.x() + 2 * border_total != width ||
|
||||
text_size.y() + 2 * border_total != height || scale_changed)) {
|
||||
/* clamp text_width to configured maximum */
|
||||
if (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 */
|
||||
global_window->scale = global_window->pending_scale;
|
||||
|
||||
width = text_size.x + 2 * border_total;
|
||||
height = text_size.y + 2 * border_total;
|
||||
width = text_size.x() + 2 * border_total;
|
||||
height = text_size.y() + 2 * border_total;
|
||||
window_resize(global_window, width, height); /* resize window */
|
||||
|
||||
changed++;
|
||||
@ -808,8 +808,8 @@ int display_output_wayland::calc_text_width(const char *s) {
|
||||
}
|
||||
|
||||
static void adjust_coords(int &x, int &y) {
|
||||
x -= text_start.x;
|
||||
y -= text_start.y;
|
||||
x -= text_start.x();
|
||||
y -= text_start.y();
|
||||
int border = get_border_total();
|
||||
x += 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) {
|
||||
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) {
|
||||
int stride;
|
||||
|
||||
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,
|
||||
@ -1142,9 +1142,9 @@ static cairo_surface_t *create_shm_surface_from_pool(void *none,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auto scaled = rectangle->size * scale;
|
||||
auto scaled = rectangle->size() * scale;
|
||||
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);
|
||||
|
||||
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*/
|
||||
|
||||
data->buffer = wl_shm_pool_create_buffer(pool->pool, offset, scaled.x,
|
||||
scaled.y, stride, format);
|
||||
data->buffer = wl_shm_pool_create_buffer(pool->pool, offset, scaled.x(),
|
||||
scaled.y(), stride, format);
|
||||
|
||||
return surface;
|
||||
}
|
||||
@ -1195,8 +1195,8 @@ struct window *window_create(struct wl_surface *surface, struct wl_shm *shm,
|
||||
struct window *window;
|
||||
window = new struct window;
|
||||
|
||||
window->rectangle.pos = vec2<size_t>::Zero();
|
||||
window->rectangle.size = vec2<size_t>(width, height);
|
||||
window->rectangle.set_pos(vec2<size_t>::Zero());
|
||||
window->rectangle.set_size(width, height);
|
||||
window->scale = 0;
|
||||
window->pending_scale = 1;
|
||||
|
||||
@ -1235,7 +1235,7 @@ void window_destroy(struct window *window) {
|
||||
|
||||
void window_resize(struct window *window, int width, int height) {
|
||||
window_free_buffer(window);
|
||||
window->rectangle.size = conky::vec2i(width, height);
|
||||
window->rectangle.set_size(width, height);
|
||||
window_allocate_buffer(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);
|
||||
/* repaint all the pixels in the surface, change size to only repaint changed
|
||||
* area*/
|
||||
wl_surface_damage(window->surface, window->rectangle.x, window->rectangle.y,
|
||||
window->rectangle.width, window->rectangle.height);
|
||||
wl_surface_damage(window->surface, window->rectangle.x(),
|
||||
window->rectangle.y(), window->rectangle.width(),
|
||||
window->rectangle.height());
|
||||
wl_surface_commit(window->surface);
|
||||
}
|
||||
|
||||
void window_get_width_height(struct window *window, int *w, int *h) {
|
||||
*w = window->rectangle.width;
|
||||
*h = window->rectangle.height;
|
||||
*w = window->rectangle.width();
|
||||
*h = window->rectangle.height();
|
||||
}
|
||||
|
||||
} // namespace conky
|
||||
|
@ -184,7 +184,8 @@ static void X11_create_window() {
|
||||
#ifdef OWN_WINDOW
|
||||
if (own_window.get(*state)) {
|
||||
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);
|
||||
@ -278,7 +279,7 @@ bool display_output_x11::main_loop_wait(double t) {
|
||||
vec2i border_total = vec2i::uniform(get_border_total());
|
||||
if (need_to_update != 0) {
|
||||
#ifdef OWN_WINDOW
|
||||
auto old_pos = window.geometry.pos;
|
||||
auto old_pos = window.geometry.pos();
|
||||
#endif
|
||||
|
||||
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 */
|
||||
vec2<long> border_size = border_total * 2;
|
||||
if ((fixed_size == 0) &&
|
||||
(text_size + border_size != window.geometry.size)) {
|
||||
window.geometry.size = text_size + border_size;
|
||||
(text_size + border_size != window.geometry.size())) {
|
||||
window.geometry.set_size(text_size + border_size);
|
||||
draw_stuff(); /* redraw everything in our newly sized window */
|
||||
XResizeWindow(display, window.window, window.geometry.width,
|
||||
window.geometry.height); /* resize window */
|
||||
XResizeWindow(display, window.window, window.geometry.width(),
|
||||
window.geometry.height()); /* resize window */
|
||||
set_transparent_background(window.window);
|
||||
#ifdef BUILD_XDBE
|
||||
/* swap buffers */
|
||||
@ -305,8 +306,8 @@ bool display_output_x11::main_loop_wait(double t) {
|
||||
if (use_xpmdb.get(*state)) {
|
||||
XFreePixmap(display, window.back_buffer);
|
||||
window.back_buffer = XCreatePixmap(
|
||||
display, window.window, window.geometry.width,
|
||||
window.geometry.height, DefaultDepth(display, screen));
|
||||
display, window.window, window.geometry.width(),
|
||||
window.geometry.height(), DefaultDepth(display, screen));
|
||||
|
||||
if (window.back_buffer != None) {
|
||||
window.drawable = window.back_buffer;
|
||||
@ -316,7 +317,7 @@ bool display_output_x11::main_loop_wait(double t) {
|
||||
}
|
||||
XSetForeground(display, window.gc, 0);
|
||||
XFillRectangle(display, window.drawable, window.gc, 0, 0,
|
||||
window.geometry.width, window.geometry.height);
|
||||
window.geometry.width(), window.geometry.height());
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -326,9 +327,9 @@ bool display_output_x11::main_loop_wait(double t) {
|
||||
}
|
||||
|
||||
/* move window if it isn't in right position */
|
||||
if ((fixed_pos == 0) && old_pos != window.geometry.pos) {
|
||||
XMoveWindow(display, window.window, window.geometry.x,
|
||||
window.geometry.y);
|
||||
if ((fixed_pos == 0) && old_pos != window.geometry.pos()) {
|
||||
XMoveWindow(display, window.window, window.geometry.x(),
|
||||
window.geometry.y());
|
||||
changed++;
|
||||
}
|
||||
|
||||
@ -347,11 +348,9 @@ bool display_output_x11::main_loop_wait(double t) {
|
||||
#else
|
||||
if (use_xpmdb.get(*state)) {
|
||||
#endif
|
||||
conky::rect<int> r(text_start, text_size);
|
||||
r.pos -= border_total;
|
||||
r.size += border_total * 2;
|
||||
|
||||
XRectangle rect = r.to_xrectangle();
|
||||
XRectangle rect = conky::rect<int>(text_start - border_total,
|
||||
text_size + border_total * 2)
|
||||
.to_xrectangle();
|
||||
XUnionRectWithRegion(&rect, x11_stuff.region, x11_stuff.region);
|
||||
}
|
||||
}
|
||||
@ -378,11 +377,9 @@ bool display_output_x11::main_loop_wait(double t) {
|
||||
#else
|
||||
if (use_xpmdb.get(*state)) {
|
||||
#endif
|
||||
conky::rect<int> r(text_start, text_size);
|
||||
r.pos -= border_total;
|
||||
r.size += border_total * 2;
|
||||
|
||||
XRectangle rect = r.to_xrectangle();
|
||||
XRectangle rect = conky::rect<int>(text_start - border_total,
|
||||
text_size + border_total * 2)
|
||||
.to_xrectangle();
|
||||
XUnionRectWithRegion(&rect, x11_stuff.region, 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) {
|
||||
*consumed = llua_mouse_hook(mouse_crossing_event(
|
||||
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;
|
||||
} else if (cursor_inside) {
|
||||
*consumed = llua_mouse_hook(mouse_crossing_event(
|
||||
mouse_event_t::AREA_LEAVE, data->pos_absolute - window.geometry.pos,
|
||||
data->pos_absolute));
|
||||
mouse_event_t::AREA_LEAVE,
|
||||
data->pos_absolute - window.geometry.pos(), data->pos_absolute));
|
||||
cursor_inside = false;
|
||||
}
|
||||
|
||||
@ -650,8 +647,8 @@ bool handle_event<x_event_handler::CONFIGURE>(
|
||||
if (own_window.get(*state)) {
|
||||
auto configure_size = vec2i(ev.xconfigure.width, ev.xconfigure.height);
|
||||
/* if window size isn't what's expected, set fixed size */
|
||||
if (configure_size != window.geometry.size) {
|
||||
if (window.geometry.size.surface() != 0) { fixed_size = 1; }
|
||||
if (configure_size != window.geometry.size()) {
|
||||
if (window.geometry.size().surface() != 0) { fixed_size = 1; }
|
||||
|
||||
/* clear old stuff before screwing up
|
||||
* size and pos */
|
||||
@ -660,18 +657,16 @@ bool handle_event<x_event_handler::CONFIGURE>(
|
||||
{
|
||||
XWindowAttributes attrs;
|
||||
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 new_text_size = window.geometry.size - border_total;
|
||||
|
||||
text_size = new_text_size;
|
||||
text_size = window.geometry.size() - border_total;
|
||||
|
||||
// don't apply dpi scaling to max pixel size
|
||||
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
|
||||
@ -859,9 +854,9 @@ void display_output_x11::cleanup() {
|
||||
if (window_created == 1) {
|
||||
int border_total = get_border_total();
|
||||
|
||||
XClearArea(display, window.window, text_start.x - border_total,
|
||||
text_start.y - border_total, text_size.x + 2 * border_total,
|
||||
text_size.y + 2 * border_total, 0);
|
||||
XClearArea(display, window.window, text_start.x() - border_total,
|
||||
text_start.y() - border_total, text_size.x() + 2 * border_total,
|
||||
text_size.y() + 2 * border_total, 0);
|
||||
}
|
||||
destroy_window();
|
||||
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) {
|
||||
#ifdef OWN_WINDOW
|
||||
window.geometry.pos = vec2i(x, y);
|
||||
window.geometry.set_pos(x, y);
|
||||
XMoveWindow(display, window.window, x, y);
|
||||
#endif /* OWN_WINDOW */
|
||||
}
|
||||
@ -1000,9 +995,9 @@ void display_output_x11::clear_text(int exposures) {
|
||||
/* there is some extra space for borders and outlines */
|
||||
int border_total = get_border_total();
|
||||
|
||||
XClearArea(display, window.window, text_start.x - border_total,
|
||||
text_start.y - border_total, text_size.x + 2 * border_total,
|
||||
text_size.y + 2 * border_total, exposures != 0 ? True : 0);
|
||||
XClearArea(display, window.window, text_start.x() - border_total,
|
||||
text_start.y() - border_total, text_size.x() + 2 * border_total,
|
||||
text_size.y() + 2 * border_total, exposures != 0 ? True : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
490
src/geometry.h
490
src/geometry.h
@ -10,6 +10,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
@ -22,60 +23,43 @@
|
||||
|
||||
namespace conky {
|
||||
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
|
||||
/// be discrete `T` types.
|
||||
/// Panics at runtime if `O` can be indexed by every value in range `0` to
|
||||
/// (excluding) `Length`.
|
||||
///
|
||||
/// This is implementation detail for `geometry.h` and not intended to be used
|
||||
/// elsewhere.
|
||||
template <typename Container, typename T>
|
||||
struct _member_access {
|
||||
Container *value;
|
||||
size_t index;
|
||||
|
||||
constexpr _member_access(Container *value, size_t index)
|
||||
: value(value), index(index) {}
|
||||
|
||||
/// @brief Converts `_member_access` to `T`.
|
||||
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;
|
||||
/// @tparam Input source array element
|
||||
/// @tparam R target element type
|
||||
/// @tparam Output target container
|
||||
/// @tparam Length array length
|
||||
/// @param value array to pad/trim
|
||||
/// @return casted array
|
||||
template <typename Input, typename R, size_t Length, typename Output>
|
||||
inline Output cast_to_assignable(const Input &value, Output &target) {
|
||||
if constexpr (std::is_same_v<Input, Output>) { return value; }
|
||||
for (size_t i = 0; i < Length; i++) {
|
||||
target[i] = static_cast<R>(value.at(i));
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
#define ASSIGN_OP_IMPL(assign_op_name, application) \
|
||||
inline T assign_op_name(T other) const { \
|
||||
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
|
||||
/// @brief Constructs a casted array from an array with different value types
|
||||
/// using `static_cast`.
|
||||
///
|
||||
/// @tparam T source array element
|
||||
/// @tparam R target array element
|
||||
/// @tparam Length array length
|
||||
/// @param value array to pad/trim
|
||||
/// @return padded/trimmed array
|
||||
/// @return casted array
|
||||
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");
|
||||
if constexpr (std::is_same_v<T, R>) { return value; }
|
||||
std::array<R, Length> buff;
|
||||
std::copy_n(value.begin(), Length, buff.begin());
|
||||
return buff;
|
||||
std::array<R, Length> result;
|
||||
cast_to_assignable<std::array<T, Length>, R, Length, std::array<R, Length>>(
|
||||
value, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @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
|
||||
/// @return padded/trimmed array
|
||||
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; }
|
||||
auto buff = std::array<T, Target>{0};
|
||||
std::copy_n(value.begin(), std::min(Source, Target), buff.begin());
|
||||
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
|
||||
|
||||
/// @brief A 2D vector representation.
|
||||
@ -129,15 +86,7 @@ struct _has_w_member {
|
||||
///
|
||||
/// @tparam T numeric component type.
|
||||
template <typename T, size_t Length>
|
||||
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> {
|
||||
struct vec {
|
||||
static_assert(std::is_arithmetic_v<T>, "T must be a number");
|
||||
static_assert(Length >= 2, "Length must be greater than 2");
|
||||
|
||||
@ -149,23 +98,19 @@ struct vec
|
||||
class _disabled {};
|
||||
|
||||
protected:
|
||||
using ComponentRef = _priv_geom::_member_access<vec<T, Length>, T>;
|
||||
using Data = Vc::array<T, Length>;
|
||||
|
||||
Data value;
|
||||
|
||||
public:
|
||||
vec() : value(Data{0}) {}
|
||||
vec(Data value) : value(value) {}
|
||||
vec(const Data &value) : value(value) {}
|
||||
vec(std::array<T, Length> array) {
|
||||
Vc::array<T, Length> vc_array;
|
||||
for (size_t i = 0; i < Length; ++i) { vc_array[i] = array[i]; }
|
||||
this->value = vc_array;
|
||||
_priv_geom::cast_to_assignable<std::array<T, Length>, T, Length,
|
||||
Vc::array<T, Length>>(array, this->value);
|
||||
}
|
||||
|
||||
template <typename O = T>
|
||||
vec(vec<O, Length> other)
|
||||
: vec(_priv_geom::cast_array<O, T, Length>(other.to_array())) {}
|
||||
vec(const vec<T, Length> &other) : vec(other.value) {}
|
||||
|
||||
vec(T x, T y) : vec<T, 2>(std::array<T, 2>{x, y}) {
|
||||
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>");
|
||||
}
|
||||
|
||||
vec(vec<T, Length> &&other) { this->value = other->value; }
|
||||
|
||||
static inline vec<T, Length> uniform(T 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`.
|
||||
/// @param index component index.
|
||||
/// @return component at `index` of this vec.
|
||||
@ -194,19 +135,19 @@ struct vec
|
||||
|
||||
/// @brief vec x component.
|
||||
/// @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.
|
||||
/// @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.
|
||||
/// @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");
|
||||
return this->at(2);
|
||||
}
|
||||
/// @brief vec w component.
|
||||
/// @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");
|
||||
return this->at(3);
|
||||
}
|
||||
@ -224,45 +165,21 @@ struct vec
|
||||
this->set(3, new_value);
|
||||
}
|
||||
|
||||
/// @brief vec x value.
|
||||
///
|
||||
/// 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) {
|
||||
vec<T, Length> &operator=(const vec<T, Length> &other) {
|
||||
this->value = other.value;
|
||||
return *this;
|
||||
}
|
||||
vec<T, Length> &operator=(vec<T, Length> &&other) {
|
||||
this->value = std::move(other.value);
|
||||
return *this;
|
||||
}
|
||||
template <typename O = T>
|
||||
vec<T, Length> &operator=(std::array<O, Length> other) {
|
||||
Data buffer = _priv_geom::cast_array(other);
|
||||
this->value = buffer;
|
||||
_priv_geom::cast_to_assignable(other, this->value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const ComponentRef &operator[](size_t 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();
|
||||
}
|
||||
}
|
||||
inline T operator[](size_t index) { return this->at(index); }
|
||||
|
||||
/// @brief Zero vector value.
|
||||
static vec<T, Length> Zero() { return vec<T, Length>::uniform(0); }
|
||||
@ -295,6 +212,9 @@ struct vec
|
||||
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 {
|
||||
Data result{this->value};
|
||||
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 {
|
||||
vec<T, Length> buffer = other - *this;
|
||||
buffer *= buffer;
|
||||
@ -394,8 +336,28 @@ struct vec
|
||||
|
||||
T surface() const {
|
||||
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>
|
||||
@ -414,33 +376,76 @@ using vec4f = vec4<float>;
|
||||
using vec4d = vec4<double>;
|
||||
using vec4i = vec4<std::int32_t>;
|
||||
|
||||
enum class rect_kind {
|
||||
SIZED,
|
||||
ABSOLUTE,
|
||||
};
|
||||
|
||||
/// @brief 2D rectangle representation using position and size vectors.
|
||||
/// @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 {
|
||||
static_assert(std::is_arithmetic_v<T>, "T must be a number");
|
||||
|
||||
using Component = T;
|
||||
using ComponentRef = _priv_geom::_member_access<rect<T>, T>;
|
||||
|
||||
vec2<T> pos;
|
||||
vec2<T> size;
|
||||
private:
|
||||
vec2<T> m_pos;
|
||||
vec2<T> m_other;
|
||||
|
||||
rect() : pos(vec2<T>::Zero()), size(vec2<T>::Zero()) {}
|
||||
rect(vec2<T> pos, vec2<T> size) : pos(pos), size(size) {}
|
||||
public:
|
||||
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.
|
||||
/// @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.
|
||||
/// @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.
|
||||
/// @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.
|
||||
/// @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`.
|
||||
/// @param index component index.
|
||||
@ -449,123 +454,200 @@ struct rect {
|
||||
assert_print(index < static_cast<size_t>(4), "index out of bounds");
|
||||
switch (index) {
|
||||
case 0:
|
||||
return this->get_x();
|
||||
return this->m_pos.x();
|
||||
case 1:
|
||||
return this->get_y();
|
||||
return this->m_pos.y();
|
||||
case 2:
|
||||
return this->get_width();
|
||||
return this->m_other.x();
|
||||
case 3:
|
||||
return this->get_height();
|
||||
return this->m_other.y();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void set_x(T value) { this->pos.set_x(value); }
|
||||
void set_y(T value) { this->pos.set_y(value); }
|
||||
void set_width(T value) { this->size.set_x(value); }
|
||||
void set_height(T value) { this->size.set_y(value); }
|
||||
inline void set_pos(vec2<T> value) { this->m_pos = value; }
|
||||
inline void set_pos(T x, T y) { this->set_pos(vec2<T>(x, y)); }
|
||||
inline void set_size(vec2<T> 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) {
|
||||
assert_print(index < static_cast<size_t>(4), "index out of bounds");
|
||||
switch (index) {
|
||||
case 0:
|
||||
return this->set_x(value);
|
||||
return this->m_pos.set_x(value);
|
||||
case 1:
|
||||
return this->set_y(value);
|
||||
return this->m_pos.set_y(value);
|
||||
case 2:
|
||||
return this->set_width(value);
|
||||
return this->m_other.set_x(value);
|
||||
case 3:
|
||||
return this->set_height(value);
|
||||
return this->m_other.set_y(value);
|
||||
default:
|
||||
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 {
|
||||
return std::array<vec2<T>, 4>{
|
||||
this->pos,
|
||||
this->pos + vec2<T>(this->get_width(), 0),
|
||||
this->pos + this->size,
|
||||
this->pos + vec2<T>(0, this->get_height()),
|
||||
this->m_pos,
|
||||
this->m_pos + vec2<T>(this->get_width(), 0),
|
||||
this->get_end_pos(),
|
||||
this->m_pos + vec2<T>(0, this->get_height()),
|
||||
};
|
||||
}
|
||||
|
||||
template <typename O = T>
|
||||
bool contains(vec2<O> p) const {
|
||||
return p.get_x() >= this->get_x() &&
|
||||
p.get_x() < this->get_x() + this->get_width() &&
|
||||
p.get_y() >= this->get_y() &&
|
||||
p.get_y() < this->get_y() + this->get_height();
|
||||
return p.x() >= this->x() && p.x() < this->x() + this->width() &&
|
||||
p.y() >= this->y() && p.y() < this->y() + this->height();
|
||||
}
|
||||
|
||||
template <typename O = T>
|
||||
bool contains(rect<O> other) const {
|
||||
return contains(other.pos) &&
|
||||
contains(other.pos + vec2<O>(other.get_width(), 0)) &&
|
||||
contains(other.pos + other.size) &&
|
||||
contains(other.pos + vec2<O>(0, other.get_height()));
|
||||
return contains(other.m_pos) &&
|
||||
contains(other.m_pos + vec2<O>(other.width(), 0)) &&
|
||||
contains(other.m_pos + other.m_other) &&
|
||||
contains(other.m_pos + vec2<O>(0, other.height()));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename O = T>
|
||||
bool _intersects_partial(rect<O> other) const {
|
||||
return contains(other.pos) ||
|
||||
contains(other.pos + vec2<O>(other.get_width(), 0)) ||
|
||||
contains(other.pos + other.size) ||
|
||||
contains(other.pos + vec2<O>(0, other.get_height()));
|
||||
return contains(other.m_pos) ||
|
||||
contains(other.m_pos + vec2<O>(other.width(), 0)) ||
|
||||
contains(other.m_pos + other.m_other) ||
|
||||
contains(other.m_pos + vec2<O>(0, other.height()));
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename O = T>
|
||||
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) {
|
||||
assert_print(index < 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->width;
|
||||
case 3:
|
||||
return this->height;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
rect<T, Kind> &operator=(const rect<T, Kind> &other) {
|
||||
this->m_pos = other.m_pos;
|
||||
this->m_other = other.m_other;
|
||||
return *this;
|
||||
}
|
||||
rect<T, Kind> &operator=(rect<T, Kind> &&other) {
|
||||
this->m_pos = other.m_pos;
|
||||
this->m_other = other.m_other;
|
||||
return *this;
|
||||
}
|
||||
template <typename O = T>
|
||||
rect<T, Kind> &operator=(std::array<O, 4> other) {
|
||||
_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
|
||||
XRectangle to_xrectangle() const {
|
||||
return XRectangle{
|
||||
.x = static_cast<short>(this->get_x()),
|
||||
.y = static_cast<short>(this->get_y()),
|
||||
.width = static_cast<unsigned short>(this->get_width()),
|
||||
.height = static_cast<unsigned short>(this->get_height())};
|
||||
return XRectangle{.x = static_cast<short>(this->x()),
|
||||
.y = static_cast<short>(this->y()),
|
||||
.width = static_cast<unsigned short>(this->width()),
|
||||
.height = static_cast<unsigned short>(this->height())};
|
||||
}
|
||||
#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
|
||||
|
||||
#endif /* _CONKY_GEOMETRY_H_ */
|
||||
|
@ -49,7 +49,7 @@
|
||||
#endif
|
||||
|
||||
/* workarea where window / text is aligned (from _NET_WORKAREA on X11) */
|
||||
conky::rect<int> workarea;
|
||||
conky::absolute_rect<int> workarea;
|
||||
|
||||
/* Window stuff */
|
||||
char window_created = 0;
|
||||
|
@ -161,7 +161,7 @@ inline bool TEST_HINT(uint16_t mask, window_hints hint) {
|
||||
}
|
||||
#endif
|
||||
|
||||
extern conky::rect<int> workarea;
|
||||
extern conky::absolute_rect<int> workarea;
|
||||
|
||||
extern char window_created;
|
||||
|
||||
|
24
src/llua.cc
24
src/llua.cc
@ -593,17 +593,17 @@ void llua_setup_window_table(conky::rect<int> text_rect) {
|
||||
#ifdef BUILD_GUI
|
||||
if (out_to_gui(*state)) {
|
||||
#ifdef BUILD_X11
|
||||
llua_set_number("width", window.geometry.width);
|
||||
llua_set_number("height", window.geometry.height);
|
||||
llua_set_number("width", window.geometry.width());
|
||||
llua_set_number("height", window.geometry.height());
|
||||
#endif /*BUILD_X11*/
|
||||
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_width", border_width.get(*state));
|
||||
|
||||
llua_set_number("text_start_x", text_rect.x);
|
||||
llua_set_number("text_start_y", text_rect.y);
|
||||
llua_set_number("text_width", text_rect.width);
|
||||
llua_set_number("text_height", text_rect.height);
|
||||
llua_set_number("text_start_x", text_rect.x());
|
||||
llua_set_number("text_start_y", text_rect.y());
|
||||
llua_set_number("text_width", text_rect.width());
|
||||
llua_set_number("text_height", text_rect.height());
|
||||
|
||||
lua_setglobal(lua_L, "conky_window");
|
||||
}
|
||||
@ -621,14 +621,14 @@ void llua_update_window_table(conky::rect<int> text_rect) {
|
||||
}
|
||||
|
||||
#ifdef BUILD_X11
|
||||
llua_set_number("width", window.geometry.width);
|
||||
llua_set_number("height", window.geometry.height);
|
||||
llua_set_number("width", window.geometry.width());
|
||||
llua_set_number("height", window.geometry.height());
|
||||
#endif /*BUILD_X11*/
|
||||
|
||||
llua_set_number("text_start_x", text_rect.x);
|
||||
llua_set_number("text_start_y", text_rect.y);
|
||||
llua_set_number("text_width", text_rect.width);
|
||||
llua_set_number("text_height", text_rect.height);
|
||||
llua_set_number("text_start_x", text_rect.x());
|
||||
llua_set_number("text_start_y", text_rect.y());
|
||||
llua_set_number("text_width", text_rect.width());
|
||||
llua_set_number("text_height", text_rect.height());
|
||||
|
||||
lua_setglobal(lua_L, "conky_window");
|
||||
}
|
||||
|
@ -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 {
|
||||
push_table_value(L, "x", this->pos.x);
|
||||
push_table_value(L, "y", this->pos.y);
|
||||
push_table_value(L, "x_abs", this->pos_absolute.x);
|
||||
push_table_value(L, "y_abs", this->pos_absolute.y);
|
||||
push_table_value(L, "x", this->pos.x());
|
||||
push_table_value(L, "y", this->pos.y());
|
||||
push_table_value(L, "x_abs", this->pos_absolute.x());
|
||||
push_table_value(L, "y_abs", this->pos_absolute.y());
|
||||
}
|
||||
|
||||
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->subwindow = child;
|
||||
e->time = CurrentTime;
|
||||
e->x = static_cast<int>(target_pos.x);
|
||||
e->y = static_cast<int>(target_pos.y);
|
||||
e->x_root = static_cast<int>(this->pos_absolute.x);
|
||||
e->y_root = static_cast<int>(this->pos_absolute.y);
|
||||
e->x = static_cast<int>(target_pos.x());
|
||||
e->y = static_cast<int>(target_pos.y());
|
||||
e->x_root = static_cast<int>(this->pos_absolute.x());
|
||||
e->y_root = static_cast<int>(this->pos_absolute.y());
|
||||
e->state = this->mods.effective;
|
||||
e->is_hint = NotifyNormal;
|
||||
e->same_screen = True;
|
||||
@ -556,10 +556,10 @@ std::vector<std::tuple<int, XEvent *>> xi_event_data::generate_events(
|
||||
e->window = target;
|
||||
e->subwindow = child;
|
||||
e->time = CurrentTime;
|
||||
e->x = static_cast<int>(target_pos.x);
|
||||
e->y = static_cast<int>(target_pos.y);
|
||||
e->x_root = static_cast<int>(this->pos_absolute.x);
|
||||
e->y_root = static_cast<int>(this->pos_absolute.y);
|
||||
e->x = static_cast<int>(target_pos.x());
|
||||
e->y = static_cast<int>(target_pos.y());
|
||||
e->x_root = static_cast<int>(this->pos_absolute.x());
|
||||
e->y_root = static_cast<int>(this->pos_absolute.y());
|
||||
e->state = this->mods.effective;
|
||||
e->button = scroll_direction;
|
||||
e->same_screen = True;
|
||||
@ -582,10 +582,10 @@ std::vector<std::tuple<int, XEvent *>> xi_event_data::generate_events(
|
||||
e->window = target;
|
||||
e->subwindow = child;
|
||||
e->time = CurrentTime;
|
||||
e->x = static_cast<int>(target_pos.x);
|
||||
e->y = static_cast<int>(target_pos.y);
|
||||
e->x_root = static_cast<int>(this->pos_absolute.x);
|
||||
e->y_root = static_cast<int>(this->pos_absolute.y);
|
||||
e->x = static_cast<int>(target_pos.x());
|
||||
e->y = static_cast<int>(target_pos.y());
|
||||
e->x_root = static_cast<int>(this->pos_absolute.x());
|
||||
e->y_root = static_cast<int>(this->pos_absolute.y());
|
||||
e->state = this->mods.effective;
|
||||
e->button = this->detail;
|
||||
e->same_screen = True;
|
||||
|
@ -226,7 +226,7 @@ char *find_and_replace_templates(const char *inbuf) {
|
||||
outlen += len;
|
||||
*o = '\0';
|
||||
outbuf = static_cast<char *>(realloc(outbuf, outlen * sizeof(char)));
|
||||
strncat(outbuf, tmpl_out, len);
|
||||
strcat(outbuf, tmpl_out);
|
||||
free(tmpl_out);
|
||||
o = outbuf + strlen(outbuf);
|
||||
} else {
|
||||
|
76
src/x11.cc
76
src/x11.cc
@ -180,8 +180,12 @@ static int x11_error_handler(Display *d, XErrorEvent *err) {
|
||||
error_name, reinterpret_cast<uint64_t>(err->display),
|
||||
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 (code_allocated) delete[] code_description;
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -321,9 +325,9 @@ void update_x11_resource_db(bool first_run) {
|
||||
|
||||
void update_x11_workarea() {
|
||||
/* default work area is display */
|
||||
workarea.pos = conky::vec2i();
|
||||
workarea.width = DisplayWidth(display, screen);
|
||||
workarea.height = DisplayHeight(display, screen);
|
||||
workarea = conky::absolute_rect<int>(
|
||||
conky::vec2i::Zero(), conky::vec2i(DisplayWidth(display, screen),
|
||||
DisplayHeight(display, screen)));
|
||||
|
||||
#ifdef BUILD_XINERAMA
|
||||
/* if xinerama is being used, adjust workarea to the head's area */
|
||||
@ -352,10 +356,8 @@ void update_x11_workarea() {
|
||||
}
|
||||
|
||||
XineramaScreenInfo *ps = &si[i];
|
||||
workarea[0] = ps->x_org;
|
||||
workarea[1] = ps->y_org;
|
||||
workarea[2] = workarea[0] + ps->width;
|
||||
workarea[3] = workarea[1] + ps->height;
|
||||
workarea.set_pos(ps->x_org, ps->y_org);
|
||||
workarea.set_size(ps->width, ps->height);
|
||||
XFree(si);
|
||||
|
||||
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);
|
||||
desktop = find_desktop_window_impl(root, display_width, display_height);
|
||||
update_x11_workarea();
|
||||
desktop = find_desktop_window_impl(desktop, workarea[2] - workarea[0],
|
||||
workarea[3] - workarea[1]);
|
||||
desktop =
|
||||
find_desktop_window_impl(desktop, workarea.width(), workarea.height());
|
||||
|
||||
if (desktop != root) {
|
||||
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) */
|
||||
window.window = XCreateWindow(display, window.desktop, window.geometry.x,
|
||||
window.geometry.y, b, b, 0, depth,
|
||||
InputOutput, visual, flags, &attrs);
|
||||
window.window = XCreateWindow(
|
||||
display, window.desktop, window.geometry.x(), window.geometry.y(), b,
|
||||
b, 0, depth, InputOutput, visual, flags, &attrs);
|
||||
|
||||
XLowerWindow(display, window.window);
|
||||
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) {
|
||||
window.geometry.pos = conky::vec2i::Zero();
|
||||
window.geometry.set_pos(conky::vec2i::Zero());
|
||||
}
|
||||
/* Parent is root window so WM can take control */
|
||||
window.window = XCreateWindow(display, window.root, window.geometry.x,
|
||||
window.geometry.y, b, b, 0, depth,
|
||||
window.window = XCreateWindow(display, window.root, window.geometry.x(),
|
||||
window.geometry.y(), b, b, 0, depth,
|
||||
InputOutput, visual, flags, &attrs);
|
||||
|
||||
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 (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");
|
||||
@ -1139,44 +1141,46 @@ void set_struts(alignment align) {
|
||||
if (strut != None) {
|
||||
long sizes[STRUT_COUNT] = {0};
|
||||
|
||||
int display_width = workarea[2] - workarea[0];
|
||||
int display_height = workarea[3] - workarea[1];
|
||||
int display_width = workarea.width();
|
||||
int display_height = workarea.height();
|
||||
|
||||
switch (horizontal_alignment(align)) {
|
||||
case axis_align::START:
|
||||
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] =
|
||||
std::clamp(*window.geometry.y, 0, *workarea.height);
|
||||
std::clamp(window.geometry.y(), 0, display_height);
|
||||
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;
|
||||
case axis_align::END:
|
||||
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] =
|
||||
std::clamp(*window.geometry.y, 0, *workarea.height);
|
||||
std::clamp(window.geometry.y(), 0, display_height);
|
||||
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;
|
||||
case axis_align::MIDDLE:
|
||||
switch (vertical_alignment(align)) {
|
||||
case axis_align::START:
|
||||
sizes[*x11_strut::TOP] =
|
||||
std::clamp(window.geometry.y + window.geometry.height, 0,
|
||||
*workarea.height);
|
||||
std::clamp(window.geometry.y() + window.geometry.height(), 0,
|
||||
display_height);
|
||||
sizes[*x11_strut::TOP_START_X] =
|
||||
std::clamp(*window.geometry.x, 0, *workarea.width);
|
||||
sizes[*x11_strut::TOP_END_X] = std::clamp(
|
||||
window.geometry.x + window.geometry.width, 0, *workarea.width);
|
||||
std::clamp(window.geometry.x(), 0, display_width);
|
||||
sizes[*x11_strut::TOP_END_X] =
|
||||
std::clamp(window.geometry.x() + window.geometry.width(), 0,
|
||||
display_width);
|
||||
break;
|
||||
case axis_align::END:
|
||||
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] =
|
||||
std::clamp(*window.geometry.x, 0, *workarea.width);
|
||||
sizes[*x11_strut::BOTTOM_END_X] = std::clamp(
|
||||
window.geometry.x + window.geometry.width, 0, *workarea.width);
|
||||
std::clamp(window.geometry.x(), 0, display_width);
|
||||
sizes[*x11_strut::BOTTOM_END_X] =
|
||||
std::clamp(window.geometry.x() + window.geometry.width(), 0,
|
||||
display_width);
|
||||
break;
|
||||
case axis_align::MIDDLE:
|
||||
// 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;
|
||||
// Update event x and y coordinates to be target window relative
|
||||
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);
|
||||
target_pos = conky::vec2i(read_x, read_y);
|
||||
}
|
||||
@ -1536,8 +1540,8 @@ std::vector<Window> query_x11_windows_at_pos(
|
||||
&_ignore);
|
||||
XGetWindowAttributes(display, current, &attr);
|
||||
|
||||
if (pos_x <= pos.x && pos_y <= pos.y && pos_x + attr.width >= pos.x &&
|
||||
pos_y + attr.height >= pos.y && predicate(attr)) {
|
||||
if (pos_x <= pos.x() && pos_y <= pos.y() && pos_x + attr.width >= pos.x() &&
|
||||
pos_y + attr.height >= pos.y() && predicate(attr)) {
|
||||
result.push_back(current);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user