From 2d50767216d2555b2d8d62765abaf41cb6d6979a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20=C5=A0vagelj?= Date: Mon, 13 May 2024 22:08:27 +0200 Subject: [PATCH] Remove _member_access from geometry (#1910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- cmake/ConkyBuildOptions.cmake | 5 +- src/conky.cc | 2071 ++++++++++++++++----------------- src/display-wayland.cc | 63 +- src/display-x11.cc | 73 +- src/geometry.h | 492 ++++---- src/gui.cc | 2 +- src/gui.h | 2 +- src/llua.cc | 24 +- src/mouse-events.cc | 32 +- src/template.cc | 2 +- src/x11.cc | 76 +- 11 files changed, 1458 insertions(+), 1384 deletions(-) diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index fe4384dac..2d606a6e5 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -51,7 +51,10 @@ if(MAINTAINER_MODE) endif(MAINTAINER_MODE) # Always use libc++ when compiling w/ clang -add_compile_options($<$:-stdlib=libc++>) +add_compile_options( + $<$:-stdlib=libc++> + $<$:-Wno-unknown-warning-option> + $<$:-Wno-unknown-warning>) add_link_options($<$:-stdlib=libc++>) option(CHECK_CODE_QUALITY "Check code formatting/quality with clang" false) diff --git a/src/conky.cc b/src/conky.cc index 263248ea1..2a60adf27 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -849,7 +849,7 @@ static int text_size_updater(char *s, int special_index); int last_font_height; void update_text_area() { - int x = 0, y = 0; + conky::vec2i xy; if (display_output() == nullptr || !display_output()->graphical()) { return; } @@ -861,47 +861,44 @@ void update_text_area() { text_size = conky::vec2i(dpi_scale(minimum_width.get(*state)), 0); last_font_height = font_height(); for_each_line(text_buffer, text_size_updater); - text_size.x += 1; - if (text_size.y < dpi_scale(minimum_height.get(*state))) { - text_size.y = dpi_scale(minimum_height.get(*state)); - } + text_size += conky::vec2i::UnitX(); + + text_size.max(conky::vec2i(text_size.x(), minimum_height.get(*state))); int mw = maximum_width.get(*state); - if (text_size.x > mw && mw > 0) { text_size.x = mw; } + if (mw > 0) text_size.min(conky::vec2i(mw, text_size.y())); } alignment align = text_alignment.get(*state); /* get text position on workarea */ switch (vertical_alignment(align)) { case axis_align::START: - y = workarea[1] + dpi_scale(gap_y.get(*state)); + xy.set_y(workarea.y() + dpi_scale(gap_y.get(*state))); break; case axis_align::END: default: - y = workarea[3] - text_size.y - dpi_scale(gap_y.get(*state)); + xy.set_y(workarea.end_y() - text_size.y() - dpi_scale(gap_y.get(*state))); break; case axis_align::MIDDLE: - y = workarea[1] + (workarea[3] - workarea[1]) / 2 - text_size.y / 2 - - dpi_scale(gap_y.get(*state)); + xy.set_y(workarea.y() + workarea.height() / 2 - text_size.y() / 2 - + dpi_scale(gap_y.get(*state))); break; } switch (horizontal_alignment(align)) { case axis_align::START: default: - x = workarea[0] + dpi_scale(gap_x.get(*state)); + xy.set_x(workarea.x() + dpi_scale(gap_x.get(*state))); break; case axis_align::END: - x = workarea[2] - text_size.x - dpi_scale(gap_x.get(*state)); + xy.set_x(workarea.end_x() - text_size.x() - dpi_scale(gap_x.get(*state))); break; case axis_align::MIDDLE: - x = workarea[0] + (workarea[2] - workarea[0]) / 2 - text_size.x / 2 - - dpi_scale(gap_x.get(*state)); + xy.set_x(workarea.x() + workarea.width() / 2 - text_size.x() / 2 - + dpi_scale(gap_x.get(*state))); break; } #ifdef OWN_WINDOW if (align == alignment::NONE) { // Let the WM manage the window - x = window.geometry.x; - y = window.geometry.y; - + xy = window.geometry.pos(); fixed_pos = 1; fixed_size = 1; } @@ -911,11 +908,11 @@ void update_text_area() { if (own_window.get(*state) && (fixed_pos == 0)) { int border_total = get_border_total(); text_start = conky::vec2i::uniform(border_total); - window.geometry.pos = conky::vec2i(x, y) - text_start; + window.geometry.set_pos(xy - text_start); } else #endif { - text_start = conky::vec2i(x, y); + text_start = xy; } /* update lua window globals */ llua_update_window_table(conky::rect(text_start, text_size)); @@ -968,7 +965,7 @@ static int text_size_updater(char *s, int special_index) { int step = current->width; if ((step == 0) || step < 0) { step = 10; } - w += step - (cur_x - text_start.x - start) % step; + w += step - (cur_x - text_start.x() - start) % step; } else if (current->type == text_node_t::FONT) { selected_font = current->font_added; if (font_height() > last_font_height) { @@ -985,11 +982,11 @@ static int text_size_updater(char *s, int special_index) { w += get_string_width(s); - if (w > text_size.x) { text_size.x = w; } + if (w > text_size.x()) { text_size.set_x(w); } 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); } - text_size.y += last_font_height; + text_size += conky::vec2i(0, last_font_height); last_font_height = font_height(); return special_index; } @@ -1027,7 +1024,7 @@ static void draw_string(const char *s) { #ifdef BUILD_GUI if (display_output() && display_output()->graphical()) { - max = ((text_size.x - width_of_s) / std::max(1, get_string_width(" "))); + max = ((text_size.x() - width_of_s) / std::max(1, get_string_width(" "))); } #endif /* BUILD_GUI */ /* This code looks for tabs in the text and coverts them to spaces. @@ -1051,903 +1048,896 @@ static void draw_string(const char *s) { #ifdef BUILD_GUI if (display_output() && display_output()->graphical()) { int mw = maximum_width.get(*state); - if (text_size.x == mw) { + if (text_size.x() == mw) { /* this means the text is probably pushing the limit, * so we'll chop it */ } } #endif /* BUILD_GUI */ - s = tmpstring2; + s = tmpstring2; #ifdef BUILD_GUI - if (display_output() && display_output()->graphical()) { - display_output()->draw_string_at(text_offset.x + cur_x, - text_offset.y + cur_y, s, strlen(s)); + if (display_output() && display_output()->graphical()) { + display_output()->draw_string_at(text_offset.x() + cur_x, + text_offset.y() + cur_y, s, strlen(s)); - cur_x += width_of_s; - } + cur_x += width_of_s; + } #endif /* BUILD_GUI */ - memcpy(tmpstring1, s, tbs); - } + memcpy(tmpstring1, s, tbs); +} #if defined(BUILD_MATH) && defined(BUILD_GUI) - /// Format \a size as a real followed by closest SI unit, with \a prec - /// number of digits after the decimal point. - static std::string formatSizeWithUnits(double size, int prec = 1) { - int div = 0; - double rem = 0; - - while (size >= 1024.0 && - static_cast(div) < (sizeof suffixes / sizeof *suffixes)) { - rem = fmod(size, 1024.0); - div++; - size /= 1024.0; - } +/// Format \a size as a real followed by closest SI unit, with \a prec +/// number of digits after the decimal point. +static std::string formatSizeWithUnits(double size, int prec = 1) { + int div = 0; + double rem = 0; + + while (size >= 1024.0 && + static_cast(div) < (sizeof suffixes / sizeof *suffixes)) { + rem = fmod(size, 1024.0); + div++; + size /= 1024.0; + } - double size_d = size + rem / 1024.0; + double size_d = size + rem / 1024.0; - std::ostringstream result; - result.setf(std::ios::fixed, std::ios::floatfield); - result.precision(prec); - result << size_d; - result << " "; + std::ostringstream result; + result.setf(std::ios::fixed, std::ios::floatfield); + result.precision(prec); + result << size_d; + result << " "; - if (short_units.get(*state)) { - result << suffixes[div][0]; - } else { - result << suffixes[div]; - } + if (short_units.get(*state)) { + result << suffixes[div][0]; + } else { + result << suffixes[div]; + } - return result.str(); - } + return result.str(); +} #endif /* BUILD_MATH && BUILD_GUI */ - int draw_each_line_inner(char *s, int special_index, - int last_special_applied) { +int draw_each_line_inner(char *s, int special_index, int last_special_applied) { #ifndef BUILD_GUI - static int cur_x, cur_y; /* current x and y for drawing */ - (void)cur_y; + static int cur_x, cur_y; /* current x and y for drawing */ + (void)cur_y; #endif #ifdef BUILD_GUI - int font_h = 0; - int cur_y_add = 0; - int mw = maximum_width.get(*state); + int font_h = 0; + int cur_y_add = 0; + int mw = maximum_width.get(*state); #endif /* BUILD_GUI */ - char *p = s; - int orig_special_index = special_index; + char *p = s; + int orig_special_index = special_index; #ifdef BUILD_GUI - if (display_output() && display_output()->graphical()) { - font_h = font_height(); - cur_y += font_ascent(); - } - cur_x = text_start.x; + if (display_output() && display_output()->graphical()) { + font_h = font_height(); + cur_y += font_ascent(); + } + cur_x = text_start.x(); #endif /* BUILD_GUI */ - while (*p != 0) { - if (*p == SPECIAL_CHAR || last_special_applied > -1) { + while (*p != 0) { + if (*p == SPECIAL_CHAR || last_special_applied > -1) { #ifdef BUILD_GUI - int w = 0; + int w = 0; #endif /* BUILD_GUI */ - /* draw string before special, unless we're dealing multiline - * specials */ - if (last_special_applied > -1) { - special_index = last_special_applied; - } else { - *p = '\0'; - draw_string(s); - *p = SPECIAL_CHAR; - s = p + 1; - } - /* draw special */ - special_node *current = specials; - for (int i = 0; i < special_index; i++) { current = current->next; } - switch (current->type) { + /* draw string before special, unless we're dealing multiline + * specials */ + if (last_special_applied > -1) { + special_index = last_special_applied; + } else { + *p = '\0'; + draw_string(s); + *p = SPECIAL_CHAR; + s = p + 1; + } + /* draw special */ + special_node *current = specials; + for (int i = 0; i < special_index; i++) { current = current->next; } + switch (current->type) { #ifdef BUILD_GUI - case text_node_t::HORIZONTAL_LINE: - if (display_output() && display_output()->graphical()) { - int h = current->height; - int mid = font_ascent() / 2; + case text_node_t::HORIZONTAL_LINE: + if (display_output() && display_output()->graphical()) { + int h = current->height; + int mid = font_ascent() / 2; + + w = text_start.x() + text_size.x() - cur_x; + + if (display_output()) { + display_output()->set_line_style(h, true); + display_output()->draw_line(text_offset.x() + cur_x, + text_offset.y() + cur_y - mid / 2, + text_offset.x() + cur_x + w, + text_offset.y() + cur_y - mid / 2); + } + } + break; - w = text_start.x + text_size.x - cur_x; + case text_node_t::STIPPLED_HR: + if (display_output() && display_output()->graphical()) { + int h = current->height; + char tmp_s = current->arg; + int mid = font_ascent() / 2; + char ss[2] = {tmp_s, tmp_s}; + + w = text_start.x() + text_size.x() - cur_x - 1; + if (display_output()) { + display_output()->set_line_style(h, false); + display_output()->set_dashes(ss); + display_output()->draw_line(text_offset.x() + cur_x, + text_offset.y() + cur_y - mid / 2, + text_offset.x() + cur_x + w, + text_offset.x() + cur_y - mid / 2); + } + } + break; - if (display_output()) { - display_output()->set_line_style(h, true); - display_output()->draw_line(text_offset.x + cur_x, - text_offset.y + cur_y - mid / 2, - text_offset.x + cur_x + w, - text_offset.y + cur_y - mid / 2); - } - } - break; + case text_node_t::BAR: + if (display_output() && display_output()->graphical()) { + int h, by; + double bar_usage, scale; + if (cur_x - text_start.x() > mw && mw > 0) { break; } + h = current->height; + bar_usage = current->arg; + scale = current->scale; + by = cur_y - (font_ascent() / 2) - 1; + + if (h < font_h) { by -= h / 2 - 1; } + w = current->width; + if (w == 0) { w = text_start.x() + text_size.x() - cur_x - 1; } + if (w < 0) { w = 0; } + + if (display_output()) { + display_output()->set_line_style(dpi_scale(1), true); + + display_output()->draw_rect(text_offset.x() + cur_x, + text_offset.y() + by, w, h); + display_output()->fill_rect(text_offset.x() + cur_x, + text_offset.y() + by, + w * bar_usage / scale, h); + } + if (h > cur_y_add && h > font_h) { cur_y_add = h; } + } + break; - case text_node_t::STIPPLED_HR: - if (display_output() && display_output()->graphical()) { - int h = current->height; - char tmp_s = current->arg; - int mid = font_ascent() / 2; - char ss[2] = {tmp_s, tmp_s}; + case text_node_t::GAUGE: /* new GAUGE */ + if (display_output() && display_output()->graphical()) { + int h, by = 0; + Colour last_colour = current_color; +#ifdef BUILD_MATH + float angle, px, py; + double usage, scale; +#endif /* BUILD_MATH */ - w = text_start.x + text_size.x - cur_x - 1; - if (display_output()) { - display_output()->set_line_style(h, false); - display_output()->set_dashes(ss); - display_output()->draw_line(text_offset.x + cur_x, - text_offset.y + cur_y - mid / 2, - text_offset.x + cur_x + w, - text_offset.x + cur_y - mid / 2); - } - } - break; + if (cur_x - text_start.x() > mw && mw > 0) { break; } - case text_node_t::BAR: - if (display_output() && display_output()->graphical()) { - int h, by; - double bar_usage, scale; - if (cur_x - text_start.x > mw && mw > 0) { break; } - h = current->height; - bar_usage = current->arg; - scale = current->scale; - by = cur_y - (font_ascent() / 2) - 1; - - if (h < font_h) { by -= h / 2 - 1; } - w = current->width; - if (w == 0) { w = text_start.x + text_size.x - cur_x - 1; } - if (w < 0) { w = 0; } + h = current->height; + by = cur_y - (font_ascent() / 2) - 1; - if (display_output()) { - display_output()->set_line_style(dpi_scale(1), true); + if (h < font_h) { by -= h / 2 - 1; } + w = current->width; + if (w == 0) { w = text_start.x() + text_size.x() - cur_x - 1; } + if (w < 0) { w = 0; } - display_output()->draw_rect(text_offset.x + cur_x, - text_offset.y + by, w, h); - display_output()->fill_rect(text_offset.x + cur_x, - text_offset.y + by, - w * bar_usage / scale, h); - } - if (h > cur_y_add && h > font_h) { cur_y_add = h; } - } - break; + if (display_output()) { + display_output()->set_line_style(1, true); + display_output()->draw_arc(text_offset.x() + cur_x, + text_offset.y() + by, w, h * 2, 0, + 180 * 64); + } - case text_node_t::GAUGE: /* new GAUGE */ - if (display_output() && display_output()->graphical()) { - int h, by = 0; - Colour last_colour = current_color; #ifdef BUILD_MATH - float angle, px, py; - double usage, scale; -#endif /* BUILD_MATH */ + usage = current->arg; + scale = current->scale; + angle = M_PI * usage / scale; + px = static_cast(cur_x + (w / 2.)) - + static_cast(w / 2.) * cos(angle); + py = static_cast(by + (h)) - + static_cast(h) * sin(angle); + + if (display_output()) { + display_output()->draw_line( + text_offset.x() + cur_x + (w / 2.), + text_offset.y() + by + (h), + text_offset.x() + static_cast(px), + text_offset.y() + static_cast(py)); + } - if (cur_x - text_start.x > mw && mw > 0) { break; } +#endif /* BUILD_MATH */ - h = current->height; - by = cur_y - (font_ascent() / 2) - 1; + if (h > cur_y_add && h > font_h) { cur_y_add = h; } - if (h < font_h) { by -= h / 2 - 1; } - w = current->width; - if (w == 0) { w = text_start.x + text_size.x - cur_x - 1; } - if (w < 0) { w = 0; } + set_foreground_color(last_colour); + } + break; - if (display_output()) { - display_output()->set_line_style(1, true); - display_output()->draw_arc(text_offset.x + cur_x, - text_offset.y + by, w, h * 2, 0, - 180 * 64); - } + case text_node_t::GRAPH: + if (display_output() && display_output()->graphical()) { + int h, by, i = 0, j = 0; + int colour_idx = 0; + Colour last_colour = current_color; + if (cur_x - text_start.x() > mw && mw > 0) { break; } + h = current->height; + by = cur_y - (font_ascent() / 2) - 1; + + if (h < font_h) { by -= h / 2 - 1; } + w = current->width; + if (w == 0) { + w = text_start.x() + text_size.x() - cur_x - 1; + current->graph_width = std::max(w - 1, 0); + if (current->graph_width != current->graph_allocated) { + w = current->graph_allocated + 1; + } + } + if (w < 0) { w = 0; } + if (draw_graph_borders.get(*state)) { + if (display_output()) { + display_output()->set_line_style(dpi_scale(1), true); + display_output()->draw_rect(text_offset.x() + cur_x, + text_offset.y() + by, w, h); + } + } + if (display_output()) display_output()->set_line_style(1, true); -#ifdef BUILD_MATH - usage = current->arg; - scale = current->scale; - angle = M_PI * usage / scale; - px = static_cast(cur_x + (w / 2.)) - - static_cast(w / 2.) * cos(angle); - py = static_cast(by + (h)) - - static_cast(h) * sin(angle); + /* in case we don't have a graph yet */ + if (current->graph != nullptr) { + std::unique_ptr tmpcolour; + if (current->colours_set) { + auto factory = create_gradient_factory(w, current->last_colour, + current->first_colour); + tmpcolour = factory->create_gradient(); + delete factory; + } + colour_idx = 0; + for (i = w - 2; i > -1; i--) { + if (current->colours_set) { + if (current->tempgrad != 0) { + set_foreground_color(tmpcolour[static_cast( + static_cast(w - 2) - + current->graph[j] * (w - 2) / + std::max(static_cast(current->scale), + 1.0F))]); + } else { + set_foreground_color(tmpcolour[colour_idx++]); + } + } + /* this is mugfugly, but it works */ if (display_output()) { display_output()->draw_line( - text_offset.x + cur_x + (w / 2.), - text_offset.y + by + (h), - text_offset.x + static_cast(px), - text_offset.y + static_cast(py)); + text_offset.x() + cur_x + i + 1, text_offset.y() + by + h, + text_offset.x() + cur_x + i + 1, + text_offset.y() + + round_to_positive_int(static_cast(by) + h - + current->graph[j] * (h - 1) / + current->scale)); } - -#endif /* BUILD_MATH */ - - if (h > cur_y_add && h > font_h) { cur_y_add = h; } - - set_foreground_color(last_colour); + ++j; } - break; - - case text_node_t::GRAPH: - if (display_output() && display_output()->graphical()) { - int h, by, i = 0, j = 0; - int colour_idx = 0; - Colour last_colour = current_color; - if (cur_x - text_start.x > mw && mw > 0) { break; } - h = current->height; - by = cur_y - (font_ascent() / 2) - 1; - - if (h < font_h) { by -= h / 2 - 1; } - w = current->width; - if (w == 0) { - w = text_start.x + text_size.x - cur_x - 1; - current->graph_width = std::max(w - 1, 0); - if (current->graph_width != current->graph_allocated) { - w = current->graph_allocated + 1; - } + } + if (h > cur_y_add && h > font_h) { cur_y_add = h; } + if (show_graph_range.get(*state)) { + int tmp_x = cur_x; + int tmp_y = cur_y; + unsigned short int seconds = active_update_interval() * w; + char *tmp_day_str; + char *tmp_hour_str; + char *tmp_min_str; + char *tmp_sec_str; + char *tmp_str; + unsigned short int timeunits; + if (seconds != 0) { + timeunits = seconds / 86400; + seconds %= 86400; + if (timeunits <= 0 || + asprintf(&tmp_day_str, _("%dd"), timeunits) == -1) { + tmp_day_str = strdup(""); } - if (w < 0) { w = 0; } - if (draw_graph_borders.get(*state)) { - if (display_output()) { - display_output()->set_line_style(dpi_scale(1), true); - display_output()->draw_rect(text_offset.x + cur_x, - text_offset.y + by, w, h); - } + timeunits = seconds / 3600; + seconds %= 3600; + if (timeunits <= 0 || + asprintf(&tmp_hour_str, _("%dh"), timeunits) == -1) { + tmp_hour_str = strdup(""); } - if (display_output()) display_output()->set_line_style(1, true); - - /* in case we don't have a graph yet */ - if (current->graph != nullptr) { - std::unique_ptr tmpcolour; - - if (current->colours_set) { - auto factory = create_gradient_factory( - w, current->last_colour, current->first_colour); - tmpcolour = factory->create_gradient(); - delete factory; - } - colour_idx = 0; - for (i = w - 2; i > -1; i--) { - if (current->colours_set) { - if (current->tempgrad != 0) { - set_foreground_color(tmpcolour[static_cast( - static_cast(w - 2) - - current->graph[j] * (w - 2) / - std::max(static_cast(current->scale), - 1.0F))]); - } else { - set_foreground_color(tmpcolour[colour_idx++]); - } - } - /* this is mugfugly, but it works */ - if (display_output()) { - display_output()->draw_line( - text_offset.x + cur_x + i + 1, text_offset.y + by + h, - text_offset.x + cur_x + i + 1, - text_offset.y + round_to_positive_int( - static_cast(by) + h - - current->graph[j] * (h - 1) / - current->scale)); - } - ++j; - } + timeunits = seconds / 60; + seconds %= 60; + if (timeunits <= 0 || + asprintf(&tmp_min_str, _("%dm"), timeunits) == -1) { + tmp_min_str = strdup(""); } - if (h > cur_y_add && h > font_h) { cur_y_add = h; } - if (show_graph_range.get(*state)) { - int tmp_x = cur_x; - int tmp_y = cur_y; - unsigned short int seconds = active_update_interval() * w; - char *tmp_day_str; - char *tmp_hour_str; - char *tmp_min_str; - char *tmp_sec_str; - char *tmp_str; - unsigned short int timeunits; - if (seconds != 0) { - timeunits = seconds / 86400; - seconds %= 86400; - if (timeunits <= 0 || - asprintf(&tmp_day_str, _("%dd"), timeunits) == -1) { - tmp_day_str = strdup(""); - } - timeunits = seconds / 3600; - seconds %= 3600; - if (timeunits <= 0 || - asprintf(&tmp_hour_str, _("%dh"), timeunits) == -1) { - tmp_hour_str = strdup(""); - } - timeunits = seconds / 60; - seconds %= 60; - if (timeunits <= 0 || - asprintf(&tmp_min_str, _("%dm"), timeunits) == -1) { - tmp_min_str = strdup(""); - } - if (seconds <= 0 || - asprintf(&tmp_sec_str, _("%ds"), seconds) == -1) { - tmp_sec_str = strdup(""); - } - if (asprintf(&tmp_str, "%s%s%s%s", tmp_day_str, - tmp_hour_str, tmp_min_str, - tmp_sec_str) == -1) { - tmp_str = strdup(""); - } - free(tmp_day_str); - free(tmp_hour_str); - free(tmp_min_str); - free(tmp_sec_str); - } else { - tmp_str = strdup( - _("Range not possible")); // should never happen, but - // better safe then sorry - } - cur_x += (w / 2) - (font_ascent() * (strlen(tmp_str) / 2)); - cur_y += font_h / 2; - draw_string(tmp_str); - free(tmp_str); - cur_x = tmp_x; - cur_y = tmp_y; + if (seconds <= 0 || + asprintf(&tmp_sec_str, _("%ds"), seconds) == -1) { + tmp_sec_str = strdup(""); } -#ifdef BUILD_MATH - if (show_graph_scale.get(*state) && - (current->show_scale == 1)) { - int tmp_x = cur_x; - int tmp_y = cur_y; - cur_x += font_ascent() / 2; - cur_y += font_h / 2; - std::string tmp_str = formatSizeWithUnits( - current->scale_log != 0 ? std::pow(10.0, current->scale) - : current->scale); - draw_string(tmp_str.c_str()); - cur_x = tmp_x; - cur_y = tmp_y; + if (asprintf(&tmp_str, "%s%s%s%s", tmp_day_str, tmp_hour_str, + tmp_min_str, tmp_sec_str) == -1) { + tmp_str = strdup(""); } -#endif - set_foreground_color(last_colour); + free(tmp_day_str); + free(tmp_hour_str); + free(tmp_min_str); + free(tmp_sec_str); + } else { + tmp_str = strdup( + _("Range not possible")); // should never happen, but + // better safe then sorry } - break; + cur_x += (w / 2) - (font_ascent() * (strlen(tmp_str) / 2)); + cur_y += font_h / 2; + draw_string(tmp_str); + free(tmp_str); + cur_x = tmp_x; + cur_y = tmp_y; + } +#ifdef BUILD_MATH + if (show_graph_scale.get(*state) && (current->show_scale == 1)) { + int tmp_x = cur_x; + int tmp_y = cur_y; + cur_x += font_ascent() / 2; + cur_y += font_h / 2; + std::string tmp_str = formatSizeWithUnits( + current->scale_log != 0 ? std::pow(10.0, current->scale) + : current->scale); + draw_string(tmp_str.c_str()); + cur_x = tmp_x; + cur_y = tmp_y; + } +#endif + set_foreground_color(last_colour); + } + break; - case text_node_t::FONT: - if (display_output() && display_output()->graphical()) { - int old = font_ascent(); - - cur_y -= font_ascent(); - selected_font = current->font_added; - set_font(); - if (cur_y + font_ascent() < cur_y + old) { - cur_y += old; - } else { - cur_y += font_ascent(); - } - font_h = font_height(); - } - break; + case text_node_t::FONT: + if (display_output() && display_output()->graphical()) { + int old = font_ascent(); + + cur_y -= font_ascent(); + selected_font = current->font_added; + set_font(); + if (cur_y + font_ascent() < cur_y + old) { + cur_y += old; + } else { + cur_y += font_ascent(); + } + font_h = font_height(); + } + break; #endif /* BUILD_GUI */ - case text_node_t::FG: - if (draw_mode == draw_mode_t::FG) { - set_foreground_color(Colour::from_argb32(current->arg)); - } - break; + case text_node_t::FG: + if (draw_mode == draw_mode_t::FG) { + set_foreground_color(Colour::from_argb32(current->arg)); + } + break; #ifdef BUILD_GUI - case text_node_t::BG: - if (draw_mode == draw_mode_t::BG) { - set_foreground_color(Colour::from_argb32(current->arg)); - } - break; + case text_node_t::BG: + if (draw_mode == draw_mode_t::BG) { + set_foreground_color(Colour::from_argb32(current->arg)); + } + break; - case text_node_t::OUTLINE: - if (draw_mode == draw_mode_t::OUTLINE) { - set_foreground_color(Colour::from_argb32(current->arg)); - } - break; + case text_node_t::OUTLINE: + if (draw_mode == draw_mode_t::OUTLINE) { + set_foreground_color(Colour::from_argb32(current->arg)); + } + break; - case text_node_t::OFFSET: - w += current->arg; - break; + case text_node_t::OFFSET: + w += current->arg; + break; - case text_node_t::VOFFSET: - cur_y += current->arg; - break; + case text_node_t::VOFFSET: + cur_y += current->arg; + break; - case text_node_t::SAVE_COORDINATES: + case text_node_t::SAVE_COORDINATES: #ifdef BUILD_IMLIB2 - saved_coordinates[static_cast(current->arg)] = - std::array{cur_x - text_start.x, - cur_y - text_start.y - last_font_height}; + saved_coordinates[static_cast(current->arg)] = + std::array{cur_x - text_start.x(), + cur_y - text_start.y() - last_font_height}; #endif /* BUILD_IMLIB2 */ - break; + break; - case text_node_t::TAB: { - int start = current->arg; - int step = current->width; + case text_node_t::TAB: { + int start = current->arg; + int step = current->width; - if ((step == 0) || step < 0) { step = 10; } - w = step - (cur_x - text_start.x - start) % step; - break; - } + if ((step == 0) || step < 0) { step = 10; } + w = step - (cur_x - text_start.x() - start) % step; + break; + } - case text_node_t::ALIGNR: { - /* TODO: add back in "+ window.border_inner_margin" to the end of - * this line? */ - int pos_x = text_start.x + text_size.x - - get_string_width_special(s, special_index); - - /* printf("pos_x %i text_start.x %i text_size.x %i cur_x %i " - "get_string_width(p) %i gap_x %i " - "current->arg %i window.border_inner_margin %i " - "window.border_width %i\n", pos_x, text_start.x, text_size.x, - cur_x, get_string_width_special(s), gap_x, - current->arg, window.border_inner_margin, - window.border_width); */ - cur_x = pos_x - current->arg; - break; - } + case text_node_t::ALIGNR: { + /* TODO: add back in "+ window.border_inner_margin" to the end of + * this line? */ + int pos_x = text_start.x() + text_size.x() - + get_string_width_special(s, special_index); + + /* printf("pos_x %i text_start.x %i text_size.x %i cur_x %i " + "get_string_width(p) %i gap_x %i " + "current->arg %i window.border_inner_margin %i " + "window.border_width %i\n", pos_x, text_start.x, text_size.x, + cur_x, get_string_width_special(s), gap_x, + current->arg, window.border_inner_margin, + window.border_width); */ + cur_x = pos_x - current->arg; + break; + } - case text_node_t::ALIGNC: { - int pos_x = text_size.x / 2 - - get_string_width_special(s, special_index) / 2 - - (cur_x - text_start.x); - /* int pos_x = text_start_x + text_size.x / 2 - - get_string_width_special(s) / 2; */ - - /* printf("pos_x %i text_start.x %i text_size.x %i cur_x %i " - "get_string_width(p) %i gap_x %i " - "current->arg %i\n", pos_x, text_start.x, - text_size.x, cur_x, get_string_width(s), gap_x, - current->arg); */ - if (pos_x > current->arg) { w = pos_x - current->arg; } - break; - } + case text_node_t::ALIGNC: { + int pos_x = text_size.x() / 2 - + get_string_width_special(s, special_index) / 2 - + (cur_x - text_start.x()); + /* int pos_x = text_start_x + text_size.x / 2 - + get_string_width_special(s) / 2; */ + + /* printf("pos_x %i text_start.x %i text_size.x %i cur_x %i " + "get_string_width(p) %i gap_x %i " + "current->arg %i\n", pos_x, text_start.x, + text_size.x, cur_x, get_string_width(s), gap_x, + current->arg); */ + if (pos_x > current->arg) { w = pos_x - current->arg; } + break; + } #endif /* BUILD_GUI */ - case text_node_t::GOTO: - if (current->arg >= 0) { + case text_node_t::GOTO: + if (current->arg >= 0) { #ifdef BUILD_GUI - cur_x = static_cast(current->arg); - // make sure shades are 1 pixel to the right of the text - if (draw_mode == draw_mode_t::BG) { cur_x++; } + cur_x = static_cast(current->arg); + // make sure shades are 1 pixel to the right of the text + if (draw_mode == draw_mode_t::BG) { cur_x++; } #endif /* BUILD_GUI */ - cur_x = static_cast(current->arg); - for (auto output : display_outputs()) output->gotox(cur_x); - } - break; - default: - // do nothing; not a special node or support not enabled - break; + cur_x = static_cast(current->arg); + for (auto output : display_outputs()) output->gotox(cur_x); } + break; + default: + // do nothing; not a special node or support not enabled + break; + } #ifdef BUILD_GUI - cur_x += w; + cur_x += w; #endif /* BUILD_GUI */ - if (special_index != last_special_applied) { - special_index++; - } else { - special_index = orig_special_index; - last_special_applied = -1; - } - } - p++; + if (special_index != last_special_applied) { + special_index++; + } else { + special_index = orig_special_index; + last_special_applied = -1; } + } + p++; + } #ifdef BUILD_GUI - cur_y += cur_y_add; + cur_y += cur_y_add; #endif /* BUILD_GUI */ - draw_string(s); - for (auto output : display_outputs()) output->line_inner_done(); + draw_string(s); + for (auto output : display_outputs()) output->line_inner_done(); #ifdef BUILD_GUI - if (display_output() && display_output()->graphical()) { - cur_y += font_descent(); - } + if (display_output() && display_output()->graphical()) { + cur_y += font_descent(); + } #endif /* BUILD_GUI */ - return special_index; - } + return special_index; +} - static int draw_line(char *s, int special_index) { - if (display_output() && display_output()->draw_line_inner_required()) { - return draw_each_line_inner(s, special_index, -1); - } - draw_string(s); - UNUSED(special_index); - return 0; - } +static int draw_line(char *s, int special_index) { + if (display_output() && display_output()->draw_line_inner_required()) { + return draw_each_line_inner(s, special_index, -1); + } + draw_string(s); + UNUSED(special_index); + return 0; +} - static void draw_text() { - for (auto output : display_outputs()) output->begin_draw_text(); +static void draw_text() { + for (auto output : display_outputs()) output->begin_draw_text(); #ifdef BUILD_GUI - // XXX:only works if inside set_display_output() - for (auto output : display_outputs()) { - if (output && output->graphical()) { - cur_y = text_start.y; - int bw = dpi_scale(border_width.get(*state)); - - /* draw borders */ - if (draw_borders.get(*state) && bw > 0) { - if (stippled_borders.get(*state) != 0) { - char ss[2] = {(char)dpi_scale(stippled_borders.get(*state)), - (char)dpi_scale(stippled_borders.get(*state))}; - output->set_line_style(bw, false); - output->set_dashes(ss); - } else { - output->set_line_style(bw, true); - } - - int offset = dpi_scale(border_inner_margin.get(*state)) + bw; - output->draw_rect(text_offset.x + text_start.x - offset, - text_offset.y + text_start.y - offset, - text_size.x + 2 * offset, - text_size.y + 2 * offset); - } - - /* draw text */ + // XXX:only works if inside set_display_output() + for (auto output : display_outputs()) { + if (output && output->graphical()) { + cur_y = text_start.y(); + int bw = dpi_scale(border_width.get(*state)); + + /* draw borders */ + if (draw_borders.get(*state) && bw > 0) { + if (stippled_borders.get(*state) != 0) { + char ss[2] = {(char)dpi_scale(stippled_borders.get(*state)), + (char)dpi_scale(stippled_borders.get(*state))}; + output->set_line_style(bw, false); + output->set_dashes(ss); + } else { + output->set_line_style(bw, true); } + + int offset = dpi_scale(border_inner_margin.get(*state)) + bw; + output->draw_rect(text_offset.x() + text_start.x() - offset, + text_offset.y() + text_start.y() - offset, + text_size.x() + 2 * offset, + text_size.y() + 2 * offset); } - setup_fonts(); -#endif /* BUILD_GUI */ - for_each_line(text_buffer, draw_line); - for (auto output : display_outputs()) output->end_draw_text(); + + /* draw text */ } + } + setup_fonts(); +#endif /* BUILD_GUI */ + for_each_line(text_buffer, draw_line); + for (auto output : display_outputs()) output->end_draw_text(); +} - void draw_stuff() { - for (auto output : display_outputs()) output->begin_draw_stuff(); +void draw_stuff() { + for (auto output : display_outputs()) output->begin_draw_stuff(); #ifdef BUILD_GUI - llua_draw_pre_hook(); + llua_draw_pre_hook(); #ifdef BUILD_IMLIB2 - text_offset = conky::vec2i::Zero(); - cimlib_render(text_start.x, text_start.y, window.geometry.width, - window.geometry.height, - imlib_cache_flush_interval.get(*state), - imlib_draw_blended.get(*state)); + text_offset = conky::vec2i::Zero(); + cimlib_render(text_start.x(), text_start.y(), window.geometry.width(), + window.geometry.height(), + imlib_cache_flush_interval.get(*state), + imlib_draw_blended.get(*state)); #endif /* BUILD_IMLIB2 */ - for (auto output : display_outputs()) { - if (!output->graphical()) continue; - // XXX: we assume a single graphical display - set_display_output(output); + for (auto output : display_outputs()) { + if (!output->graphical()) continue; + // XXX: we assume a single graphical display + set_display_output(output); - selected_font = 0; - if (draw_shades.get(*state) && !draw_outline.get(*state)) { - text_offset = conky::vec2i::One(); - set_foreground_color(default_shade_color.get(*state)); - draw_mode = draw_mode_t::BG; - draw_text(); - text_offset = conky::vec2i::Zero(); - } + selected_font = 0; + if (draw_shades.get(*state) && !draw_outline.get(*state)) { + text_offset = conky::vec2i::One(); + set_foreground_color(default_shade_color.get(*state)); + draw_mode = draw_mode_t::BG; + draw_text(); + text_offset = conky::vec2i::Zero(); + } - if (draw_outline.get(*state)) { - selected_font = 0; + if (draw_outline.get(*state)) { + selected_font = 0; - for (int ix = -1; ix < 2; ix++) { - for (int iy = -1; iy < 2; iy++) { - if (ix == 0 && iy == 0) { continue; } - text_offset = conky::vec2i(ix, iy); - set_foreground_color(default_outline_color.get(*state)); - draw_mode = draw_mode_t::OUTLINE; - draw_text(); - } - } - text_offset = conky::vec2i::Zero(); + for (int ix = -1; ix < 2; ix++) { + for (int iy = -1; iy < 2; iy++) { + if (ix == 0 && iy == 0) { continue; } + text_offset = conky::vec2i(ix, iy); + set_foreground_color(default_outline_color.get(*state)); + draw_mode = draw_mode_t::OUTLINE; + draw_text(); } - - selected_font = 0; - set_foreground_color(default_color.get(*state)); - unset_display_output(); } + text_offset = conky::vec2i::Zero(); + } + + selected_font = 0; + set_foreground_color(default_color.get(*state)); + unset_display_output(); + } #endif /* BUILD_GUI */ - // always draw text - draw_mode = draw_mode_t::FG; - draw_text(); + // always draw text + draw_mode = draw_mode_t::FG; + draw_text(); #ifdef BUILD_GUI - llua_draw_post_hook(); + llua_draw_post_hook(); #endif /* BUILD_GUI */ - for (auto output : display_outputs()) output->end_draw_stuff(); - } + for (auto output : display_outputs()) output->end_draw_stuff(); +} - int need_to_update; +int need_to_update; - /* update_text() generates new text and clears old text area */ - void update_text() { +/* update_text() generates new text and clears old text area */ +void update_text() { #ifdef BUILD_IMLIB2 - cimlib_cleanup(); + cimlib_cleanup(); #endif /* BUILD_IMLIB2 */ - generate_text(); + generate_text(); #ifdef BUILD_GUI - for (auto output : display_outputs()) { - if (output->graphical()) output->clear_text(1); - } + for (auto output : display_outputs()) { + if (output->graphical()) output->clear_text(1); + } #endif /* BUILD_GUI */ - need_to_update = 1; - llua_update_info(&info, active_update_interval()); - } + need_to_update = 1; + llua_update_info(&info, active_update_interval()); +} #ifdef HAVE_SYS_INOTIFY_H - int inotify_fd = -1; +int inotify_fd = -1; #endif - template - void split(const std::string &s, char delim, Out result) { - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { *(result++) = item; } - } - std::vector split(const std::string &s, char delim) { - std::vector elems; - split(s, delim, std::back_inserter(elems)); - return elems; - } +template +void split(const std::string &s, char delim, Out result) { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { *(result++) = item; } +} +std::vector split(const std::string &s, char delim) { + std::vector elems; + split(s, delim, std::back_inserter(elems)); + return elems; +} - bool is_on_battery() { // checks if at least one battery specified in - // "detect_battery" is discharging - char buf[64]; - std::vector b_items = split(detect_battery.get(*state), ','); +bool is_on_battery() { // checks if at least one battery specified in + // "detect_battery" is discharging + char buf[64]; + std::vector b_items = split(detect_battery.get(*state), ','); - for (auto const &value : b_items) { - get_battery_short_status(buf, 64, value.c_str()); - if (buf[0] == 'D') { return true; } - } - return false; - } + for (auto const &value : b_items) { + get_battery_short_status(buf, 64, value.c_str()); + if (buf[0] == 'D') { return true; } + } + return false; +} - volatile sig_atomic_t g_sigterm_pending, g_sighup_pending, - g_sigusr2_pending; +volatile sig_atomic_t g_sigterm_pending, g_sighup_pending, g_sigusr2_pending; - void log_system_details() { - char *session_ty = getenv("XDG_SESSION_TYPE"); - char *session = getenv("GDMSESSION"); - char *desktop = getenv("XDG_CURRENT_DESKTOP"); - if (desktop != nullptr || session != nullptr) { - NORM_ERR("'%s' %s session running '%s' destop", session, session_ty, - desktop); - } - } +void log_system_details() { + char *session_ty = getenv("XDG_SESSION_TYPE"); + char *session = getenv("GDMSESSION"); + char *desktop = getenv("XDG_CURRENT_DESKTOP"); + if (desktop != nullptr || session != nullptr) { + NORM_ERR("'%s' %s session running '%s' destop", session, session_ty, + desktop); + } +} - void main_loop() { - int terminate = 0; +void main_loop() { + int terminate = 0; #ifdef SIGNAL_BLOCKING - sigset_t newmask, oldmask; + sigset_t newmask, oldmask; #endif #ifdef BUILD_GUI - double t; + double t; #endif /* BUILD_GUI */ #ifdef HAVE_SYS_INOTIFY_H - int inotify_config_wd = -1; + int inotify_config_wd = -1; #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) #define INOTIFY_BUF_LEN (20 * (INOTIFY_EVENT_SIZE + 16)) + 1 - char inotify_buff[INOTIFY_BUF_LEN]; + char inotify_buff[INOTIFY_BUF_LEN]; #endif /* HAVE_SYS_INOTIFY_H */ #ifdef SIGNAL_BLOCKING - sigemptyset(&newmask); - sigaddset(&newmask, SIGINT); - sigaddset(&newmask, SIGTERM); - sigaddset(&newmask, SIGUSR1); + sigemptyset(&newmask); + sigaddset(&newmask, SIGINT); + sigaddset(&newmask, SIGTERM); + sigaddset(&newmask, SIGUSR1); #endif - log_system_details(); + log_system_details(); - last_update_time = 0.0; - next_update_time = - get_time() - fmod(get_time(), active_update_interval()); - info.looped = 0; - while (terminate == 0 && (total_run_times.get(*state) == 0 || - info.looped < total_run_times.get(*state))) { - if ((update_interval_on_battery.get(*state) != NOBATTERY)) { - on_battery = is_on_battery(); - } - info.looped++; + last_update_time = 0.0; + next_update_time = get_time() - fmod(get_time(), active_update_interval()); + info.looped = 0; + while (terminate == 0 && (total_run_times.get(*state) == 0 || + info.looped < total_run_times.get(*state))) { + if ((update_interval_on_battery.get(*state) != NOBATTERY)) { + on_battery = is_on_battery(); + } + info.looped++; #ifdef SIGNAL_BLOCKING - /* block signals. we will inspect for pending signals later */ - if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { - CRIT_ERR("unable to sigprocmask()"); - } + /* block signals. we will inspect for pending signals later */ + if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { + CRIT_ERR("unable to sigprocmask()"); + } #endif #ifdef BUILD_GUI - if (display_output() && display_output()->graphical()) { - t = next_update_time - get_time(); - display_output()->main_loop_wait(t); - } else { + if (display_output() && display_output()->graphical()) { + t = next_update_time - get_time(); + display_output()->main_loop_wait(t); + } else { #endif /* BUILD_GUI */ - struct timespec req, rem; - auto time_to_sleep = next_update_time - get_time(); - auto seconds = static_cast(std::floor(time_to_sleep)); - auto nanos = (time_to_sleep - seconds) * 1000000000L; - req.tv_sec = seconds; - req.tv_nsec = nanos; - nanosleep(&req, &rem); - update_text(); - draw_stuff(); - for (auto output : display_outputs()) output->flush(); + struct timespec req, rem; + auto time_to_sleep = next_update_time - get_time(); + auto seconds = static_cast(std::floor(time_to_sleep)); + auto nanos = (time_to_sleep - seconds) * 1000000000L; + req.tv_sec = seconds; + req.tv_nsec = nanos; + nanosleep(&req, &rem); + update_text(); + draw_stuff(); + for (auto output : display_outputs()) output->flush(); #ifdef BUILD_GUI - } + } #endif /* BUILD_GUI */ #ifdef SIGNAL_BLOCKING - /* unblock signals of interest and let handler fly */ - if (sigprocmask(SIG_SETMASK, &oldmask, nullptr) < 0) { - CRIT_ERR("unable to sigprocmask()"); - } + /* unblock signals of interest and let handler fly */ + if (sigprocmask(SIG_SETMASK, &oldmask, nullptr) < 0) { + CRIT_ERR("unable to sigprocmask()"); + } #endif - if (g_sighup_pending != 0) { - g_sighup_pending = 0; - NORM_ERR("received SIGUSR1. reloading the config file."); + if (g_sighup_pending != 0) { + g_sighup_pending = 0; + NORM_ERR("received SIGUSR1. reloading the config file."); - reload_config(); - } + reload_config(); + } - if (g_sigusr2_pending != 0) { - g_sigusr2_pending = 0; - // refresh view; - NORM_ERR("received SIGUSR2. refreshing."); - update_text(); - draw_stuff(); - for (auto output : display_outputs()) output->flush(); - } + if (g_sigusr2_pending != 0) { + g_sigusr2_pending = 0; + // refresh view; + NORM_ERR("received SIGUSR2. refreshing."); + update_text(); + draw_stuff(); + for (auto output : display_outputs()) output->flush(); + } - if (g_sigterm_pending != 0) { - g_sigterm_pending = 0; - NORM_ERR("received SIGHUP, SIGINT, or SIGTERM to terminate. bye!"); - terminate = 1; - for (auto output : display_outputs()) output->sigterm_cleanup(); - } + if (g_sigterm_pending != 0) { + g_sigterm_pending = 0; + NORM_ERR("received SIGHUP, SIGINT, or SIGTERM to terminate. bye!"); + terminate = 1; + for (auto output : display_outputs()) output->sigterm_cleanup(); + } #ifdef HAVE_SYS_INOTIFY_H - if (!disable_auto_reload.get(*state) && inotify_fd != -1 && - inotify_config_wd == -1 && !current_config.empty()) { - inotify_config_wd = - inotify_add_watch(inotify_fd, current_config.c_str(), IN_MODIFY); - } - if (!disable_auto_reload.get(*state) && inotify_fd != -1 && - inotify_config_wd != -1 && !current_config.empty()) { - int len = 0, idx = 0; - fd_set descriptors; - struct timeval time_to_wait; - - FD_ZERO(&descriptors); - FD_SET(inotify_fd, &descriptors); - - time_to_wait.tv_sec = time_to_wait.tv_usec = 0; - - select(inotify_fd + 1, &descriptors, nullptr, NULL, &time_to_wait); - if (FD_ISSET(inotify_fd, &descriptors)) { - /* process inotify events */ - len = read(inotify_fd, inotify_buff, INOTIFY_BUF_LEN - 1); - inotify_buff[len] = 0; - while (len > 0 && idx < len) { - struct inotify_event *ev = - (struct inotify_event *)&inotify_buff[idx]; - if (ev->wd == inotify_config_wd && - (ev->mask & IN_MODIFY || ev->mask & IN_IGNORED)) { - /* current_config should be reloaded */ - NORM_ERR("'%s' modified, reloading...", current_config.c_str()); - reload_config(); - if (ev->mask & IN_IGNORED) { - /* for some reason we get IN_IGNORED here - * sometimes, so we need to re-add the watch */ - inotify_config_wd = inotify_add_watch( - inotify_fd, current_config.c_str(), IN_MODIFY); - } - break; - } else { - llua_inotify_query(ev->wd, ev->mask); - } - idx += INOTIFY_EVENT_SIZE + ev->len; + if (!disable_auto_reload.get(*state) && inotify_fd != -1 && + inotify_config_wd == -1 && !current_config.empty()) { + inotify_config_wd = + inotify_add_watch(inotify_fd, current_config.c_str(), IN_MODIFY); + } + if (!disable_auto_reload.get(*state) && inotify_fd != -1 && + inotify_config_wd != -1 && !current_config.empty()) { + int len = 0, idx = 0; + fd_set descriptors; + struct timeval time_to_wait; + + FD_ZERO(&descriptors); + FD_SET(inotify_fd, &descriptors); + + time_to_wait.tv_sec = time_to_wait.tv_usec = 0; + + select(inotify_fd + 1, &descriptors, nullptr, NULL, &time_to_wait); + if (FD_ISSET(inotify_fd, &descriptors)) { + /* process inotify events */ + len = read(inotify_fd, inotify_buff, INOTIFY_BUF_LEN - 1); + inotify_buff[len] = 0; + while (len > 0 && idx < len) { + struct inotify_event *ev = (struct inotify_event *)&inotify_buff[idx]; + if (ev->wd == inotify_config_wd && + (ev->mask & IN_MODIFY || ev->mask & IN_IGNORED)) { + /* current_config should be reloaded */ + NORM_ERR("'%s' modified, reloading...", current_config.c_str()); + reload_config(); + if (ev->mask & IN_IGNORED) { + /* for some reason we get IN_IGNORED here + * sometimes, so we need to re-add the watch */ + inotify_config_wd = inotify_add_watch( + inotify_fd, current_config.c_str(), IN_MODIFY); } + break; + } else { + llua_inotify_query(ev->wd, ev->mask); } - } else if (disable_auto_reload.get(*state) && inotify_fd != -1) { - inotify_rm_watch(inotify_fd, inotify_config_wd); - close(inotify_fd); - inotify_fd = inotify_config_wd = -1; + idx += INOTIFY_EVENT_SIZE + ev->len; } + } + } else if (disable_auto_reload.get(*state) && inotify_fd != -1) { + inotify_rm_watch(inotify_fd, inotify_config_wd); + close(inotify_fd); + inotify_fd = inotify_config_wd = -1; + } #endif /* HAVE_SYS_INOTIFY_H */ - llua_update_info(&info, active_update_interval()); - } - clean_up(); + llua_update_info(&info, active_update_interval()); + } + clean_up(); #ifdef HAVE_SYS_INOTIFY_H - if (inotify_fd != -1) { - inotify_rm_watch(inotify_fd, inotify_config_wd); - close(inotify_fd); - inotify_fd = inotify_config_wd = -1; - } + if (inotify_fd != -1) { + inotify_rm_watch(inotify_fd, inotify_config_wd); + close(inotify_fd); + inotify_fd = inotify_config_wd = -1; + } #endif /* HAVE_SYS_INOTIFY_H */ - } +} - /* reload the config file */ - static void reload_config() { - struct stat sb {}; - if ((stat(current_config.c_str(), &sb) != 0) || - (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) { - NORM_ERR( - _("Config file '%s' is gone, continuing with config from " - "memory.\nIf you recreate this file sent me a SIGUSR1 to tell " - "me about it. ( kill -s USR1 %d )"), - current_config.c_str(), getpid()); - return; - } - clean_up(); - state = std::make_unique(); - conky::export_symbols(*state); - sleep(1); /* slight pause */ - initialisation(argc_copy, argv_copy); - } +/* reload the config file */ +static void reload_config() { + struct stat sb {}; + if ((stat(current_config.c_str(), &sb) != 0) || + (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) { + NORM_ERR(_("Config file '%s' is gone, continuing with config from " + "memory.\nIf you recreate this file sent me a SIGUSR1 to tell " + "me about it. ( kill -s USR1 %d )"), + current_config.c_str(), getpid()); + return; + } + clean_up(); + state = std::make_unique(); + conky::export_symbols(*state); + sleep(1); /* slight pause */ + initialisation(argc_copy, argv_copy); +} - void free_specials(special_node * ¤t) { - if (current != nullptr) { - free_specials(current->next); - if (current->type == text_node_t::GRAPH) { free(current->graph); } - delete current; - current = nullptr; - } +void free_specials(special_node *¤t) { + if (current != nullptr) { + free_specials(current->next); + if (current->type == text_node_t::GRAPH) { free(current->graph); } + delete current; + current = nullptr; + } - clear_stored_graphs(); - } + clear_stored_graphs(); +} - void clean_up(void) { - /* free_update_callbacks(); XXX: some new equivalent of this? */ - free_and_zero(info.cpu_usage); - for (auto output : display_outputs()) output->cleanup(); - conky::shutdown_display_outputs(); +void clean_up(void) { + /* free_update_callbacks(); XXX: some new equivalent of this? */ + free_and_zero(info.cpu_usage); + for (auto output : display_outputs()) output->cleanup(); + conky::shutdown_display_outputs(); #ifdef BUILD_GUI - if (!display_output() || !display_output()->graphical()) { - fonts.clear(); // in set_default_configurations a font is set but not - // loaded - selected_font = 0; - } + if (!display_output() || !display_output()->graphical()) { + fonts.clear(); // in set_default_configurations a font is set but not + // loaded + selected_font = 0; + } #endif /* BUILD_GUI */ - if (info.first_process != nullptr) { - free_all_processes(); - info.first_process = nullptr; - } + if (info.first_process != nullptr) { + free_all_processes(); + info.first_process = nullptr; + } - free_text_objects(&global_root_object); - delete_block_and_zero(tmpstring1); - delete_block_and_zero(tmpstring2); - delete_block_and_zero(text_buffer); - free_and_zero(global_text); + free_text_objects(&global_root_object); + delete_block_and_zero(tmpstring1); + delete_block_and_zero(tmpstring2); + delete_block_and_zero(text_buffer); + free_and_zero(global_text); #ifdef BUILD_PORT_MONITORS - tcp_portmon_clear(); + tcp_portmon_clear(); #endif - llua_shutdown_hook(); + llua_shutdown_hook(); #if defined BUILD_RSS - xmlCleanupParser(); + xmlCleanupParser(); #endif - free_specials(specials); + free_specials(specials); - clear_net_stats(); - clear_fs_stats(); - clear_diskio_stats(); - free_and_zero(global_cpu); + clear_net_stats(); + clear_fs_stats(); + clear_diskio_stats(); + free_and_zero(global_cpu); - conky::cleanup_config_settings(*state); - state.reset(); - } + conky::cleanup_config_settings(*state); + state.reset(); +} - static void set_default_configurations() { - update_uname(); - info.memmax = 0; - top_cpu = 0; - top_mem = 0; - top_time = 0; +static void set_default_configurations() { + update_uname(); + info.memmax = 0; + top_cpu = 0; + top_mem = 0; + top_time = 0; #ifdef BUILD_IOSTATS - top_io = 0; + top_io = 0; #endif - top_running = 0; + top_running = 0; #ifdef BUILD_XMMS2 - info.xmms2.artist = nullptr; - info.xmms2.album = nullptr; - info.xmms2.title = nullptr; - info.xmms2.genre = nullptr; - info.xmms2.comment = nullptr; - info.xmms2.url = nullptr; - info.xmms2.status = nullptr; - info.xmms2.playlist = nullptr; + info.xmms2.artist = nullptr; + info.xmms2.album = nullptr; + info.xmms2.title = nullptr; + info.xmms2.genre = nullptr; + info.xmms2.comment = nullptr; + info.xmms2.url = nullptr; + info.xmms2.status = nullptr; + info.xmms2.playlist = nullptr; #endif /* BUILD_XMMS2 */ /* Enable a single output by default based on what was enabled at build-time */ #ifdef BUILD_WAYLAND - state->pushboolean(true); - out_to_wayland.lua_set(*state); + state->pushboolean(true); + out_to_wayland.lua_set(*state); #else #ifdef BUILD_X11 state->pushboolean(true); @@ -1958,70 +1948,69 @@ static void draw_string(const char *s) { #endif #endif - info.users.number = 1; - } + info.users.number = 1; +} - void load_config_file() { - DBGP(_("reading contents from config file '%s'"), current_config.c_str()); +void load_config_file() { + DBGP(_("reading contents from config file '%s'"), current_config.c_str()); - lua::state &l = *state; - lua::stack_sentry s(l); - l.checkstack(2); + lua::state &l = *state; + lua::stack_sentry s(l); + l.checkstack(2); - // Extend lua package.path so scripts can use relative paths - { - struct stat file_stat {}; + // Extend lua package.path so scripts can use relative paths + { + struct stat file_stat {}; - std::string path_ext; + std::string path_ext; - // add XDG directory to lua path - auto xdg_path = - std::filesystem::path(to_real_path(XDG_CONFIG_FILE)).parent_path(); - if (stat(xdg_path.c_str(), &file_stat) == 0) { - path_ext.push_back(';'); - path_ext.append(xdg_path); - path_ext.append("/?.lua"); - } + // add XDG directory to lua path + auto xdg_path = + std::filesystem::path(to_real_path(XDG_CONFIG_FILE)).parent_path(); + if (stat(xdg_path.c_str(), &file_stat) == 0) { + path_ext.push_back(';'); + path_ext.append(xdg_path); + path_ext.append("/?.lua"); + } - auto parent_path = current_config.parent_path(); - if (xdg_path != parent_path && - stat(path_ext.c_str(), &file_stat) == 0) { - path_ext.push_back(';'); - path_ext.append(parent_path); - path_ext.append("/?.lua"); - } + auto parent_path = current_config.parent_path(); + if (xdg_path != parent_path && stat(path_ext.c_str(), &file_stat) == 0) { + path_ext.push_back(';'); + path_ext.append(parent_path); + path_ext.append("/?.lua"); + } - l.getglobal("package"); - l.getfield(-1, "path"); + l.getglobal("package"); + l.getfield(-1, "path"); - auto path = l.tostring(-1); - path.append(path_ext); - l.pop(); - l.pushstring(path.c_str()); + auto path = l.tostring(-1); + path.append(path_ext); + l.pop(); + l.pushstring(path.c_str()); - l.setfield(-2, "path"); - l.pop(); - } + l.setfield(-2, "path"); + l.pop(); + } - try { + try { #ifdef BUILD_BUILTIN_CONFIG - if (current_config == builtin_config_magic) { - l.loadstring(defconfig); - } else { + if (current_config == builtin_config_magic) { + l.loadstring(defconfig); + } else { #endif - l.loadfile(current_config.c_str()); + l.loadfile(current_config.c_str()); #ifdef BUILD_BUILTIN_CONFIG - } + } #endif - } catch (lua::syntax_error &e) { + } catch (lua::syntax_error &e) { #define SYNTAX_ERR_READ_CONF "Syntax error (%s) while reading config file. " #ifdef BUILD_OLD_CONFIG - NORM_ERR(_(SYNTAX_ERR_READ_CONF), e.what()); - NORM_ERR(_("Assuming it's in old syntax and attempting conversion.")); - // the strchr thingy skips the first line (#! /usr/bin/lua) - l.loadstring(strchr(convertconf, '\n')); - l.pushstring(current_config.c_str()); - l.call(1, 1); + NORM_ERR(_(SYNTAX_ERR_READ_CONF), e.what()); + NORM_ERR(_("Assuming it's in old syntax and attempting conversion.")); + // the strchr thingy skips the first line (#! /usr/bin/lua) + l.loadstring(strchr(convertconf, '\n')); + l.pushstring(current_config.c_str()); + l.call(1, 1); #else char *syntaxerr; if (asprintf(&syntaxerr, _(SYNTAX_ERR_READ_CONF), e.what())) { @@ -2030,333 +2019,333 @@ static void draw_string(const char *s) { throw conky::error(syntaxerrobj); } #endif - } - l.call(0, 0); + } + l.call(0, 0); - l.getglobal("conky"); - l.getfield(-1, "text"); - l.replace(-2); - if (l.type(-1) != lua::TSTRING) { - throw conky::error(_("missing text block in configuration")); - } + l.getglobal("conky"); + l.getfield(-1, "text"); + l.replace(-2); + if (l.type(-1) != lua::TSTRING) { + throw conky::error(_("missing text block in configuration")); + } - /* Remove \\-\n. */ - l.gsub(l.tocstring(-1), "\\\n", ""); - l.replace(-2); - global_text = strdup(l.tocstring(-1)); - l.pop(); - } + /* Remove \\-\n. */ + l.gsub(l.tocstring(-1), "\\\n", ""); + l.replace(-2); + global_text = strdup(l.tocstring(-1)); + l.pop(); +} - inline void reset_optind() { +inline void reset_optind() { #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) - optind = optreset = 1; + optind = optreset = 1; #else optind = 0; #endif - } +} - void set_current_config() { - /* load current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */ - struct stat s {}; +void set_current_config() { + /* load current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */ + struct stat s {}; - if (current_config.empty()) { - /* Try to use personal config file first */ - std::string buf = to_real_path(XDG_CONFIG_FILE); - if (stat(buf.c_str(), &s) == 0) { current_config = buf; } - } + if (current_config.empty()) { + /* Try to use personal config file first */ + std::string buf = to_real_path(XDG_CONFIG_FILE); + if (stat(buf.c_str(), &s) == 0) { current_config = buf; } + } - if (current_config.empty()) { - /* Try to use personal config file first */ - std::string buf = to_real_path(CONFIG_FILE); - if (stat(buf.c_str(), &s) == 0) { current_config = buf; } - } + if (current_config.empty()) { + /* Try to use personal config file first */ + std::string buf = to_real_path(CONFIG_FILE); + if (stat(buf.c_str(), &s) == 0) { current_config = buf; } + } - /* Try to use system config file if personal config does not exist */ - if (current_config.empty() && (stat(SYSTEM_CONFIG_FILE, &s) == 0)) { - current_config = SYSTEM_CONFIG_FILE; - } + /* Try to use system config file if personal config does not exist */ + if (current_config.empty() && (stat(SYSTEM_CONFIG_FILE, &s) == 0)) { + current_config = SYSTEM_CONFIG_FILE; + } - /* No readable config found */ - if (current_config.empty()) { + /* No readable config found */ + if (current_config.empty()) { #define NOCFGFILEFOUND "no personal or system-wide config file found" #ifdef BUILD_BUILTIN_CONFIG - current_config = builtin_config_magic; - NORM_ERR(NOCFGFILEFOUND ", using builtin default"); + current_config = builtin_config_magic; + NORM_ERR(NOCFGFILEFOUND ", using builtin default"); #else throw conky::error(NOCFGFILEFOUND); #endif - } + } - // "-" stands for "read from stdin" - if (current_config == "-") { current_config = "/dev/stdin"; } - } + // "-" stands for "read from stdin" + if (current_config == "-") { current_config = "/dev/stdin"; } +} - /* : means that character before that takes an argument */ - const char *getopt_string = - "vVqdDSs:t:u:i:hc:p:" +/* : means that character before that takes an argument */ +const char *getopt_string = + "vVqdDSs:t:u:i:hc:p:" #ifdef BUILD_X11 - "x:y:w:a:X:m:f:" + "x:y:w:a:X:m:f:" #ifdef OWN_WINDOW - "o" + "o" #endif - "b" + "b" #endif /* BUILD_X11 */ #ifdef BUILD_BUILTIN_CONFIG - "C" + "C" #endif - ; + ; - const struct option longopts[] = { - {"help", 0, nullptr, 'h'}, {"version", 0, nullptr, 'v'}, - {"short-version", 0, nullptr, 'V'}, {"quiet", 0, nullptr, 'q'}, - {"debug", 0, nullptr, 'D'}, {"config", 1, nullptr, 'c'}, +const struct option longopts[] = { + {"help", 0, nullptr, 'h'}, {"version", 0, nullptr, 'v'}, + {"short-version", 0, nullptr, 'V'}, {"quiet", 0, nullptr, 'q'}, + {"debug", 0, nullptr, 'D'}, {"config", 1, nullptr, 'c'}, #ifdef BUILD_BUILTIN_CONFIG - {"print-config", 0, nullptr, 'C'}, + {"print-config", 0, nullptr, 'C'}, #endif - {"daemonize", 0, nullptr, 'd'}, + {"daemonize", 0, nullptr, 'd'}, #ifdef BUILD_X11 - {"alignment", 1, nullptr, 'a'}, {"display", 1, nullptr, 'X'}, - {"xinerama-head", 1, nullptr, 'm'}, {"font", 1, nullptr, 'f'}, + {"alignment", 1, nullptr, 'a'}, {"display", 1, nullptr, 'X'}, + {"xinerama-head", 1, nullptr, 'm'}, {"font", 1, nullptr, 'f'}, #ifdef OWN_WINDOW - {"own-window", 0, nullptr, 'o'}, + {"own-window", 0, nullptr, 'o'}, #endif - {"double-buffer", 0, nullptr, 'b'}, {"window-id", 1, nullptr, 'w'}, + {"double-buffer", 0, nullptr, 'b'}, {"window-id", 1, nullptr, 'w'}, #endif /* BUILD_X11 */ - {"text", 1, nullptr, 't'}, {"interval", 1, nullptr, 'u'}, - {"pause", 1, nullptr, 'p'}, {nullptr, 0, nullptr, 0}}; + {"text", 1, nullptr, 't'}, {"interval", 1, nullptr, 'u'}, + {"pause", 1, nullptr, 'p'}, {nullptr, 0, nullptr, 0}}; - void setup_inotify() { +void setup_inotify() { #ifdef HAVE_SYS_INOTIFY_H - // the file descriptor will be automatically closed on exit - inotify_fd = inotify_init(); - if (inotify_fd != -1) { - fcntl(inotify_fd, F_SETFL, fcntl(inotify_fd, F_GETFL) | O_NONBLOCK); + // the file descriptor will be automatically closed on exit + inotify_fd = inotify_init(); + if (inotify_fd != -1) { + fcntl(inotify_fd, F_SETFL, fcntl(inotify_fd, F_GETFL) | O_NONBLOCK); - fcntl(inotify_fd, F_SETFD, fcntl(inotify_fd, F_GETFD) | FD_CLOEXEC); - } + fcntl(inotify_fd, F_SETFD, fcntl(inotify_fd, F_GETFD) | FD_CLOEXEC); + } #endif /* HAVE_SYS_INOTIFY_H */ - } - void initialisation(int argc, char **argv) { - struct sigaction act { - }, oact{}; +} +void initialisation(int argc, char **argv) { + struct sigaction act { + }, oact{}; - clear_net_stats(); - set_default_configurations(); + clear_net_stats(); + set_default_configurations(); - set_current_config(); - load_config_file(); + set_current_config(); + load_config_file(); - /* handle other command line arguments */ + /* handle other command line arguments */ - reset_optind(); + reset_optind(); #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, - "kvm_open")) == nullptr) { - CRIT_ERR("cannot read kvm"); - } + if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, + "kvm_open")) == nullptr) { + CRIT_ERR("cannot read kvm"); + } #endif - while (1) { - int c = getopt_long(argc, argv, getopt_string, longopts, nullptr); - int startup_pause; - char *conv_end; + while (1) { + int c = getopt_long(argc, argv, getopt_string, longopts, nullptr); + int startup_pause; + char *conv_end; - if (c == -1) { break; } + if (c == -1) { break; } - switch (c) { - case 'd': - state->pushboolean(true); - fork_to_background.lua_set(*state); - break; + switch (c) { + case 'd': + state->pushboolean(true); + fork_to_background.lua_set(*state); + break; #ifdef BUILD_X11 - case 'f': - state->pushstring(optarg); - font.lua_set(*state); - break; - case 'a': - state->pushstring(optarg); - text_alignment.lua_set(*state); - break; - case 'm': - state->pushinteger(strtol(optarg, &conv_end, 10)); - if (*conv_end != 0) { - CRIT_ERR("'%s' is a wrong xinerama-head index", optarg); - } - head_index.lua_set(*state); - break; - case 'X': - state->pushstring(optarg); - display_name.lua_set(*state); - break; + case 'f': + state->pushstring(optarg); + font.lua_set(*state); + break; + case 'a': + state->pushstring(optarg); + text_alignment.lua_set(*state); + break; + case 'm': + state->pushinteger(strtol(optarg, &conv_end, 10)); + if (*conv_end != 0) { + CRIT_ERR("'%s' is a wrong xinerama-head index", optarg); + } + head_index.lua_set(*state); + break; + case 'X': + state->pushstring(optarg); + display_name.lua_set(*state); + break; #ifdef OWN_WINDOW - case 'o': - state->pushboolean(true); - own_window.lua_set(*state); - break; + case 'o': + state->pushboolean(true); + own_window.lua_set(*state); + break; #endif #ifdef BUILD_XDBE - case 'b': - state->pushboolean(true); - use_xdbe.lua_set(*state); - break; + case 'b': + state->pushboolean(true); + use_xdbe.lua_set(*state); + break; #else - case 'b': - state->pushboolean(true); - use_xpmdb.lua_set(*state); - break; + case 'b': + state->pushboolean(true); + use_xpmdb.lua_set(*state); + break; #endif #endif /* BUILD_X11 */ - case 't': - free_and_zero(global_text); - global_text = strndup(optarg, max_user_text.get(*state)); - convert_escapes(global_text); - break; - - case 'u': - state->pushnumber(strtod(optarg, &conv_end)); - if (*conv_end != 0) { - CRIT_ERR("'%s' is an invalid update interval", optarg); - } - update_interval.lua_set(*state); - break; + case 't': + free_and_zero(global_text); + global_text = strndup(optarg, max_user_text.get(*state)); + convert_escapes(global_text); + break; + + case 'u': + state->pushnumber(strtod(optarg, &conv_end)); + if (*conv_end != 0) { + CRIT_ERR("'%s' is an invalid update interval", optarg); + } + update_interval.lua_set(*state); + break; - case 'i': - state->pushinteger(strtol(optarg, &conv_end, 10)); - if (*conv_end != 0) { - CRIT_ERR("'%s' is an invalid number of update times", optarg); - } - total_run_times.lua_set(*state); - break; + case 'i': + state->pushinteger(strtol(optarg, &conv_end, 10)); + if (*conv_end != 0) { + CRIT_ERR("'%s' is an invalid number of update times", optarg); + } + total_run_times.lua_set(*state); + break; #ifdef BUILD_X11 - case 'x': - state->pushinteger(strtol(optarg, &conv_end, 10)); - if (*conv_end != 0) { - CRIT_ERR("'%s' is an invalid value for the X-position", optarg); - } - gap_x.lua_set(*state); - break; + case 'x': + state->pushinteger(strtol(optarg, &conv_end, 10)); + if (*conv_end != 0) { + CRIT_ERR("'%s' is an invalid value for the X-position", optarg); + } + gap_x.lua_set(*state); + break; - case 'y': - state->pushinteger(strtol(optarg, &conv_end, 10)); - if (*conv_end != 0) { - CRIT_ERR("'%s' is a wrong value for the Y-position", optarg); - } - gap_y.lua_set(*state); - break; + case 'y': + state->pushinteger(strtol(optarg, &conv_end, 10)); + if (*conv_end != 0) { + CRIT_ERR("'%s' is a wrong value for the Y-position", optarg); + } + gap_y.lua_set(*state); + break; #endif /* BUILD_X11 */ - case 'p': - if (first_pass != 0) { - startup_pause = strtol(optarg, nullptr, 10); - sleep(startup_pause); - } - break; - - case '?': - throw unknown_arg_throw(); + case 'p': + if (first_pass != 0) { + startup_pause = strtol(optarg, nullptr, 10); + sleep(startup_pause); } - } + break; - conky::set_config_settings(*state); + case '?': + throw unknown_arg_throw(); + } + } + + conky::set_config_settings(*state); #ifdef BUILD_GUI - if (display_output() && display_output()->graphical()) { - current_text_color = default_color.get(*state); - } + if (display_output() && display_output()->graphical()) { + current_text_color = default_color.get(*state); + } #endif - /* generate text and get initial size */ - extract_variable_text(global_text); - free_and_zero(global_text); - /* fork */ - if (fork_to_background.get(*state) && (first_pass != 0)) { - int pid = fork(); - - switch (pid) { - case -1: - NORM_ERR(PACKAGE_NAME ": couldn't fork() to background: %s", - strerror(errno)); - break; - - case 0: - /* child process */ - usleep(25000); - fprintf(stderr, "\n"); - fflush(stderr); - break; - - default: - /* parent process */ - fprintf(stderr, PACKAGE_NAME ": forked to background, pid is %d\n", - pid); - fflush(stderr); - throw fork_throw(); - } - } + /* generate text and get initial size */ + extract_variable_text(global_text); + free_and_zero(global_text); + /* fork */ + if (fork_to_background.get(*state) && (first_pass != 0)) { + int pid = fork(); + + switch (pid) { + case -1: + NORM_ERR(PACKAGE_NAME ": couldn't fork() to background: %s", + strerror(errno)); + break; + + case 0: + /* child process */ + usleep(25000); + fprintf(stderr, "\n"); + fflush(stderr); + break; + + default: + /* parent process */ + fprintf(stderr, PACKAGE_NAME ": forked to background, pid is %d\n", + pid); + fflush(stderr); + throw fork_throw(); + } + } - text_buffer = new char[max_user_text.get(*state)]; - memset(text_buffer, 0, max_user_text.get(*state)); - tmpstring1 = new char[text_buffer_size.get(*state)]; - memset(tmpstring1, 0, text_buffer_size.get(*state)); - tmpstring2 = new char[text_buffer_size.get(*state)]; - memset(tmpstring2, 0, text_buffer_size.get(*state)); + text_buffer = new char[max_user_text.get(*state)]; + memset(text_buffer, 0, max_user_text.get(*state)); + tmpstring1 = new char[text_buffer_size.get(*state)]; + memset(tmpstring1, 0, text_buffer_size.get(*state)); + tmpstring2 = new char[text_buffer_size.get(*state)]; + memset(tmpstring2, 0, text_buffer_size.get(*state)); - if (!conky::initialize_display_outputs()) { - CRIT_ERR("initialize_display_outputs() failed."); - } + if (!conky::initialize_display_outputs()) { + CRIT_ERR("initialize_display_outputs() failed."); + } #ifdef BUILD_GUI - /* setup lua window globals */ - llua_setup_window_table(conky::rect(text_start, text_size)); + /* setup lua window globals */ + llua_setup_window_table(conky::rect(text_start, text_size)); #endif /* BUILD_GUI */ - llua_setup_info(&info, active_update_interval()); + llua_setup_info(&info, active_update_interval()); - /* Set signal handlers */ - act.sa_handler = signal_handler; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; + /* Set signal handlers */ + act.sa_handler = signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; #ifdef SA_RESTART - act.sa_flags |= SA_RESTART; + act.sa_flags |= SA_RESTART; #endif - if (sigaction(SIGINT, &act, &oact) < 0 || - sigaction(SIGALRM, &act, &oact) < 0 || - sigaction(SIGUSR1, &act, &oact) < 0 || - sigaction(SIGUSR2, &act, &oact) < 0 || - sigaction(SIGHUP, &act, &oact) < 0 || - sigaction(SIGTERM, &act, &oact) < 0) { - NORM_ERR("error setting signal handler: %s", strerror(errno)); - } + if (sigaction(SIGINT, &act, &oact) < 0 || + sigaction(SIGALRM, &act, &oact) < 0 || + sigaction(SIGUSR1, &act, &oact) < 0 || + sigaction(SIGUSR2, &act, &oact) < 0 || + sigaction(SIGHUP, &act, &oact) < 0 || + sigaction(SIGTERM, &act, &oact) < 0) { + NORM_ERR("error setting signal handler: %s", strerror(errno)); + } - llua_startup_hook(); - } + llua_startup_hook(); +} - static void signal_handler(int sig) { - /* signal handler is light as a feather, as it should be. - * we will poll g_signal_pending with each loop of conky - * and do any signal processing there, NOT here */ +static void signal_handler(int sig) { + /* signal handler is light as a feather, as it should be. + * we will poll g_signal_pending with each loop of conky + * and do any signal processing there, NOT here */ - switch (sig) { - case SIGHUP: - case SIGINT: - case SIGTERM: - g_sigterm_pending = 1; - break; - case SIGUSR1: - g_sighup_pending = 1; - break; - case SIGUSR2: - g_sigusr2_pending = 1; - default: - /* Reaching here means someone set a signal - * (SIGXXXX, signal_handler), but didn't write any code - * to deal with it. - * If you don't want to handle a signal, don't set a handler on - * it in the first place. - * We cannot print debug messages from a sighandler, so simply ignore. - */ - break; - } - } + switch (sig) { + case SIGHUP: + case SIGINT: + case SIGTERM: + g_sigterm_pending = 1; + break; + case SIGUSR1: + g_sighup_pending = 1; + break; + case SIGUSR2: + g_sigusr2_pending = 1; + default: + /* Reaching here means someone set a signal + * (SIGXXXX, signal_handler), but didn't write any code + * to deal with it. + * If you don't want to handle a signal, don't set a handler on + * it in the first place. + * We cannot print debug messages from a sighandler, so simply ignore. + */ + break; + } +} diff --git a/src/display-wayland.cc b/src/display-wayland.cc index af9bb1023..e1c2f9d0b 100644 --- a/src/display-wayland.cc +++ b/src/display-wayland.cc @@ -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( + 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(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(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(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 *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 *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(map), cairo_format, scaled.x, scaled.y, + static_cast(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::Zero(); - window->rectangle.size = vec2(width, height); + window->rectangle.set_pos(vec2::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 diff --git a/src/display-x11.cc b/src/display-x11.cc index 04c35decb..ded4eb6f4 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -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 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 r(text_start, text_size); - r.pos -= border_total; - r.size += border_total * 2; - - XRectangle rect = r.to_xrectangle(); + XRectangle rect = conky::rect(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 r(text_start, text_size); - r.pos -= border_total; - r.size += border_total * 2; - - XRectangle rect = r.to_xrectangle(); + XRectangle rect = conky::rect(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( 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( 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( { 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); } } diff --git a/src/geometry.h b/src/geometry.h index c415221e1..e8d816970 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -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 -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; - } - -#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); } -}; +/// @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 +inline Output cast_to_assignable(const Input &value, Output &target) { + if constexpr (std::is_same_v) { return value; } + for (size_t i = 0; i < Length; i++) { + target[i] = static_cast(value.at(i)); + } + return target; +} -/// @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 -std::array cast_array(std::array value) { +inline std::array cast_array(const std::array &value) { static_assert(std::is_convertible_v, "T is not convertible to R"); if constexpr (std::is_same_v) { return value; } - std::array buff; - std::copy_n(value.begin(), Length, buff.begin()); - return buff; + std::array result; + cast_to_assignable, R, Length, std::array>( + value, result); + return result; } /// @brief Takes an array and pads/trims it to the desired length by inserting @@ -86,39 +70,12 @@ std::array cast_array(std::array value) { /// @param value array to pad/trim /// @return padded/trimmed array template -std::array resize_array(std::array value) { +inline std::array resize_array(std::array value) { if constexpr (Source == Target) { return value; } auto buff = std::array{0}; std::copy_n(value.begin(), std::min(Source, Target), buff.begin()); return buff; } - -class _no_z_member {}; -template -struct _has_z_member { - static_assert(std::is_arithmetic_v, - "vector z member type (T) must be a number"); - using ComponentRef = _member_access; - - /// @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 -struct _has_w_member { - static_assert(std::is_arithmetic_v, - "vector w member type (T) must be a number"); - using ComponentRef = _member_access; - - /// @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 -struct vec - // conditionally add z member accessor - : public std::conditional_t<(Length >= 3), - _priv_geom::_has_z_member, T>, - _priv_geom::_no_z_member>, - // conditionally add w member accessor - public std::conditional_t<(Length >= 4), - _priv_geom::_has_w_member, T>, - _priv_geom::_no_w_member> { +struct vec { static_assert(std::is_arithmetic_v, "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, T>; using Data = Vc::array; Data value; public: vec() : value(Data{0}) {} - vec(Data value) : value(value) {} + vec(const Data &value) : value(value) {} vec(std::array array) { - Vc::array vc_array; - for (size_t i = 0; i < Length; ++i) { vc_array[i] = array[i]; } - this->value = vc_array; + _priv_geom::cast_to_assignable, T, Length, + Vc::array>(array, this->value); } - template - vec(vec other) - : vec(_priv_geom::cast_array(other.to_array())) {} + vec(const vec &other) : vec(other.value) {} vec(T x, T y) : vec(std::array{x, y}) { static_assert(Length == 2, "constructor only valid for vec2"); @@ -177,16 +122,12 @@ struct vec static_assert(Length == 4, "constructor only valid for vec4"); } + vec(vec &&other) { this->value = other->value; } + static inline vec uniform(T x) { return vec(std::array{x}); } - std::array to_array() const { - std::array 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 &operator=(vec other) { + vec &operator=(const vec &other) { this->value = other.value; return *this; } + vec &operator=(vec &&other) { + this->value = std::move(other.value); + return *this; + } template vec &operator=(std::array 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(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 Zero() { return vec::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 operator+(vec 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 min(const vec &other) { + Data result{this->value}; + for (size_t i = 0; i < Length; i++) { + result[i] = std::min(result[i], other.value[i]); + } + return vec(result); + } + + /// @brief Computes component-wise vector maximum + /// @param other other vector + /// @returns new vector with max values + inline vec max(const vec &other) { + Data result{this->value}; + for (size_t i = 0; i < Length; i++) { + result[i] = std::max(result[i], other.value[i]); + } + return vec(result); + } + inline T distance_squared(vec other) const { vec 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 + vec cast() const { + Vc::array buffer; + _priv_geom::cast_to_assignable, O, Length, + Vc::array>(this->value, buffer); + return vec(buffer); + } + + std::array to_array() const { + std::array result; + for (size_t i = 0; i < Length; ++i) { result[i] = this->value[i]; } + return result; + } + + template + operator vec() const { + return this->cast(); + } + operator std::array() const { return this->to_array(); } }; template @@ -414,33 +376,76 @@ using vec4f = vec4; using vec4d = vec4; using vec4i = vec4; +enum class rect_kind { + SIZED, + ABSOLUTE, +}; + /// @brief 2D rectangle representation using position and size vectors. /// @tparam T component number type. -template +template struct rect { static_assert(std::is_arithmetic_v, "T must be a number"); using Component = T; - using ComponentRef = _priv_geom::_member_access, T>; - vec2 pos; - vec2 size; + private: + vec2 m_pos; + vec2 m_other; - rect() : pos(vec2::Zero()), size(vec2::Zero()) {} - rect(vec2 pos, vec2 size) : pos(pos), size(size) {} + public: + rect() : m_pos(vec2::Zero()), m_other(vec2::Zero()) {} + rect(vec2 pos, vec2 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 pos() const { return this->m_pos; } + inline vec2 size() const { + if constexpr (Kind == rect_kind::SIZED) { + return this->m_other; + } else { + return this->m_other - this->m_pos; + } + } + inline vec2 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(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 value) { this->m_pos = value; } + inline void set_pos(T x, T y) { this->set_pos(vec2(x, y)); } + inline void set_size(vec2 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(width, height)); + } + inline void set_end_pos(vec2 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(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(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, 4> corners() const { return std::array, 4>{ - this->pos, - this->pos + vec2(this->get_width(), 0), - this->pos + this->size, - this->pos + vec2(0, this->get_height()), + this->m_pos, + this->m_pos + vec2(this->get_width(), 0), + this->get_end_pos(), + this->m_pos + vec2(0, this->get_height()), }; } template bool contains(vec2 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 bool contains(rect other) const { - return contains(other.pos) && - contains(other.pos + vec2(other.get_width(), 0)) && - contains(other.pos + other.size) && - contains(other.pos + vec2(0, other.get_height())); + return contains(other.m_pos) && + contains(other.m_pos + vec2(other.width(), 0)) && + contains(other.m_pos + other.m_other) && + contains(other.m_pos + vec2(0, other.height())); } private: template bool _intersects_partial(rect other) const { - return contains(other.pos) || - contains(other.pos + vec2(other.get_width(), 0)) || - contains(other.pos + other.size) || - contains(other.pos + vec2(0, other.get_height())); + return contains(other.m_pos) || + contains(other.m_pos + vec2(other.width(), 0)) || + contains(other.m_pos + other.m_other) || + contains(other.m_pos + vec2(0, other.height())); } public: template bool intersects(rect 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(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 &operator=(const rect &other) { + this->m_pos = other.m_pos; + this->m_other = other.m_other; + return *this; + } + rect &operator=(rect &&other) { + this->m_pos = other.m_pos; + this->m_other = other.m_other; + return *this; + } + template + rect &operator=(std::array 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(this->get_x()), - .y = static_cast(this->get_y()), - .width = static_cast(this->get_width()), - .height = static_cast(this->get_height())}; + return XRectangle{.x = static_cast(this->x()), + .y = static_cast(this->y()), + .width = static_cast(this->width()), + .height = static_cast(this->height())}; } #endif /* BUILD_X11 */ + + rect to_sized() const { + if constexpr (Kind == rect_kind::SIZED) { + return *this; + } else { + return rect{this->m_pos, + this->m_other - this->m_pos}; + } + } + + rect to_absolute() const { + if constexpr (Kind == rect_kind::ABSOLUTE) { + return *this; + } else { + return rect{this->m_pos, + this->m_pos + this->m_other}; + } + } + + std::array to_array() const { + return std::array{this->m_pos.x(), this->m_pos.y(), this->m_other.x(), + this->m_other.y()}; + } + + inline operator std::array() const { return this->to_array(); } + inline explicit operator rect() const { + return this->to_sized(); + } + inline explicit operator rect() const { + return this->to_absolute(); + } }; +template +using sized_rect = rect; + +template +using absolute_rect = rect; + } // namespace conky #endif /* _CONKY_GEOMETRY_H_ */ diff --git a/src/gui.cc b/src/gui.cc index 533efd6fb..f73265d0a 100644 --- a/src/gui.cc +++ b/src/gui.cc @@ -49,7 +49,7 @@ #endif /* workarea where window / text is aligned (from _NET_WORKAREA on X11) */ -conky::rect workarea; +conky::absolute_rect workarea; /* Window stuff */ char window_created = 0; diff --git a/src/gui.h b/src/gui.h index 23ba998de..98ffaf5a8 100644 --- a/src/gui.h +++ b/src/gui.h @@ -161,7 +161,7 @@ inline bool TEST_HINT(uint16_t mask, window_hints hint) { } #endif -extern conky::rect workarea; +extern conky::absolute_rect workarea; extern char window_created; diff --git a/src/llua.cc b/src/llua.cc index 468323f0d..ab1516c09 100644 --- a/src/llua.cc +++ b/src/llua.cc @@ -593,17 +593,17 @@ void llua_setup_window_table(conky::rect 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 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"); } diff --git a/src/mouse-events.cc b/src/mouse-events.cc index 78d7d7e7d..afdab5a0b 100644 --- a/src/mouse-events.cc +++ b/src/mouse-events.cc @@ -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> xi_event_data::generate_events( e->window = target; e->subwindow = child; e->time = CurrentTime; - e->x = static_cast(target_pos.x); - e->y = static_cast(target_pos.y); - e->x_root = static_cast(this->pos_absolute.x); - e->y_root = static_cast(this->pos_absolute.y); + e->x = static_cast(target_pos.x()); + e->y = static_cast(target_pos.y()); + e->x_root = static_cast(this->pos_absolute.x()); + e->y_root = static_cast(this->pos_absolute.y()); e->state = this->mods.effective; e->is_hint = NotifyNormal; e->same_screen = True; @@ -556,10 +556,10 @@ std::vector> xi_event_data::generate_events( e->window = target; e->subwindow = child; e->time = CurrentTime; - e->x = static_cast(target_pos.x); - e->y = static_cast(target_pos.y); - e->x_root = static_cast(this->pos_absolute.x); - e->y_root = static_cast(this->pos_absolute.y); + e->x = static_cast(target_pos.x()); + e->y = static_cast(target_pos.y()); + e->x_root = static_cast(this->pos_absolute.x()); + e->y_root = static_cast(this->pos_absolute.y()); e->state = this->mods.effective; e->button = scroll_direction; e->same_screen = True; @@ -582,10 +582,10 @@ std::vector> xi_event_data::generate_events( e->window = target; e->subwindow = child; e->time = CurrentTime; - e->x = static_cast(target_pos.x); - e->y = static_cast(target_pos.y); - e->x_root = static_cast(this->pos_absolute.x); - e->y_root = static_cast(this->pos_absolute.y); + e->x = static_cast(target_pos.x()); + e->y = static_cast(target_pos.y()); + e->x_root = static_cast(this->pos_absolute.x()); + e->y_root = static_cast(this->pos_absolute.y()); e->state = this->mods.effective; e->button = this->detail; e->same_screen = True; diff --git a/src/template.cc b/src/template.cc index 39cc5949c..6045fe8dc 100644 --- a/src/template.cc +++ b/src/template.cc @@ -226,7 +226,7 @@ char *find_and_replace_templates(const char *inbuf) { outlen += len; *o = '\0'; outbuf = static_cast(realloc(outbuf, outlen * sizeof(char))); - strncat(outbuf, tmpl_out, len); + strcat(outbuf, tmpl_out); free(tmpl_out); o = outbuf + strlen(outbuf); } else { diff --git a/src/x11.cc b/src/x11.cc index 70b7a09ea..b270ffe59 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -180,8 +180,12 @@ static int x11_error_handler(Display *d, XErrorEvent *err) { error_name, reinterpret_cast(err->display), static_cast(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( + 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 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); } }