Cleanup build flags, global namespace and includes (#1841)

- Separated displays so they don't have to all be included in build even when the features are disabled.
- Removed weird linker magic for display init and replaced it with straightforward (and faster) template functions that behave the same.
  - Replaced `disabled_display_output` classes with log messages.
- Add explicit compiler errors when feature dependent headers get included where they shouldn't (wl, x11).
- Switch BUILD_MOUSE_EVENTS dependency from OWN_WINDOW to BUILD_X11.
- Other minor improvements to some existing code which shouldn't affect behavior.
- Improve documentation.
- Remove X11 from unrelated headers.
  - This reaches 0% unneeded X11 polution in the sources.
  - Reenabled parts of window_type which would work in Wayland.
  - Remove unneeded guards.
- Display files are now no longer compiled if their features are disabled.

Signed-off-by: Tin Švagelj <tin.svagelj@live.com>
This commit is contained in:
Tin Švagelj
2024-04-23 21:15:37 +00:00
committed by GitHub
parent c51fbe66f6
commit 6adf6b9dd4
46 changed files with 1249 additions and 974 deletions

6
.gitignore vendored
View File

@@ -11,11 +11,17 @@ doc/*.html
Makefile
CMakeCache.txt
CMakeFiles
cmake_install.cmake
cmake_uninstall.cmake
CPackConfig.cmake
CPackSourceConfig.cmake
data/convertconf.h
data/defconfig.h
*.so
*.a
/config.h
/build.h
# Compiler cache
.cache

View File

@@ -1 +1,4 @@
build/
# ignore generated Makefile; keep stub
Makefile

View File

@@ -193,8 +193,8 @@ dependent_option(BUILD_XSHAPE "Enable Xshape support" true
"BUILD_X11" false
"Xshape support requires X11")
dependent_option(BUILD_XINPUT "Build Xinput 2 support" true
"BUILD_X11;BUILD_MOUSE_EVENTS" false
"Xinput 2 support requires X11 and BUILD_MOUSE_EVENTS enabled")
"BUILD_X11" false
"Xinput 2 support requires X11")
# if we build with any GUI support
if(BUILD_X11)
@@ -206,8 +206,8 @@ if(BUILD_WAYLAND)
endif(BUILD_WAYLAND)
dependent_option(BUILD_MOUSE_EVENTS "Enable mouse event support" true
"BUILD_WAYLAND OR OWN_WINDOW" false
"Mouse event support requires Wayland or OWN_WINDOW enabled")
"BUILD_WAYLAND OR BUILD_X11" false
"Mouse event support requires Wayland or X11 enabled")
# Lua library options
dependent_option(BUILD_LUA_CAIRO "Build cairo bindings for Lua" false
@@ -247,9 +247,11 @@ option(BUILD_IRC "Enable if you want IRC support" false)
option(BUILD_HTTP "Enable if you want HTTP support" false)
if(BUILD_HTTP)
if(NOT BUILD_HTTP)
set(HTTPPORT "10080" CACHE STRING "Port to use for out_to_http")
endif(BUILD_HTTP)
else(NOT BUILD_HTTP)
set(HTTPPORT "10080")
endif(NOT BUILD_HTTP)
option(BUILD_ICONV "Enable iconv support" false)

View File

@@ -10,7 +10,10 @@
--
-- For more on Lua, see:
-- https://www.lua.org/pil/contents.html
--
-- Conky Lua API: https://conky.cc/lua
-- Configuration settings: https://conky.cc/config_settings
conky.config = {
alignment = 'bottom_left',
background = false,
@@ -36,7 +39,8 @@ conky.config = {
extra_newline = false,
own_window = false,
own_window_class = 'Conky',
own_window_type = 'desktop',
own_window_type = 'normal',
own_window_hints = 'undecorated,sticky,below,skip_taskbar,skip_pager',
stippled_borders = 0,
update_interval = 3.0,
uppercase = false,
@@ -45,6 +49,7 @@ conky.config = {
show_graph_range = false
}
-- Variables: https://conky.cc/variables
conky.text = [[
$sysname $version on $machine
$hr

View File

@@ -10,7 +10,10 @@
--
-- For more on Lua, see:
-- https://www.lua.org/pil/contents.html
--
-- Conky Lua API: https://conky.cc/lua
-- Configuration settings: https://conky.cc/config_settings
conky.config = {
alignment = 'top_left',
background = false,
@@ -39,7 +42,8 @@ conky.config = {
out_to_x = true,
own_window = true,
own_window_class = 'Conky',
own_window_type = 'desktop',
own_window_type = 'normal',
own_window_hints = 'undecorated,sticky,below,skip_taskbar,skip_pager',
show_graph_range = false,
show_graph_scale = false,
stippled_borders = 0,
@@ -49,6 +53,7 @@ conky.config = {
use_xft = true,
}
-- Variables: https://conky.cc/variables
conky.text = [[
${color grey}Info:$color ${scroll 32 Conky $conky_version - $sysname $nodename $kernel $machine}
$hr

View File

@@ -10,7 +10,10 @@
--
-- For more on Lua, see:
-- https://www.lua.org/pil/contents.html
--
-- Conky Lua API: https://conky.cc/lua
-- Configuration settings: https://conky.cc/config_settings
conky.config = {
background = false,
cpu_avg_samples = 2,
@@ -22,6 +25,7 @@ conky.config = {
use_spacer = 'none',
};
-- Variables: https://conky.cc/variables
conky.text =
[[${scroll 16 $nodename - $sysname $kernel on $machine | }
Uptime: $uptime

View File

@@ -27,10 +27,38 @@ desc: |-
values:
- name: alignment
desc: |-
Aligned position on screen, may be top_left, top_right,
top_middle, bottom_left, bottom_right, bottom_middle, middle_left,
middle_middle, middle_right, or none (also can be abbreviated as tl,
tr, tm, bl, br, bm, ml, mm, mr). See also gap_x and gap_y.
Aligned position on screen, may be `none` or one of:
<table>
<tr>
<td><code>top_left</code> (<em>or</em> <code>tl</code>)</td>
<td><code>top_middle</code> (<em>or</em> <code>tm</code>)</td>
<td><code>top_right</code> (<em>or</em> <code>tr</code>)</td>
</tr>
<tr>
<td><code>middle_left</code> (<em>or</em> <code>ml</code>)</td>
<td><code>middle_middle</code> (<em>or</em> <code>mm</code>)</td>
<td><code>middle_right</code> (<em>or</em> <code>mr</code>)</td>
</tr>
<tr>
<td><code>bottom_left</code> (<em>or</em> <code>bl</code>)</td>
<td><code>bottom_middle</code> (<em>or</em> <code>bm</code>)</td>
<td><code>bottom_right</code> (<em>or</em> <code>br</code>)</td>
</tr>
</table>
In case of `panel` and `dock` windows, it might make more sense to use one
of the following aliases:
| Alias | Value |
|:------:|:-------------:|
| `top` | `top_middle` |
| `left` | `middle_left` |
|`right` |`middle_right` |
|`bottom`|`bottom_middle`|
|`center`|`middle_middle`|
See also `gap_x` and `gap_y` settings.
- name: append_file
desc: Append the file given as argument.
- name: background
@@ -437,7 +465,7 @@ values:
default: false
- name: own_window_type
desc: |-
If own_window is set, under X11 you can specify type of window conky
If `own_window` is set, under X11 you can specify type of window conky
displayed as:
- `normal` mode makes conky show as normal window. This mode can be
@@ -464,6 +492,7 @@ values:
panels/windows as those will cover conky.
`own_window_hints` are ignored for `override` windows.
To make conky mount on root window, set `own_window` to `false`.
default: normal
args:
- (normal|desktop|dock|panel|utility|override)

View File

@@ -119,14 +119,6 @@ set(conky_sources
display-console.hh
display-file.cc
display-file.hh
display-ncurses.cc
display-ncurses.hh
display-http.cc
display-http.hh
display-x11.cc
display-x11.hh
display-wayland.cc
display-wayland.hh
lua-config.cc
lua-config.hh
setting.cc
@@ -236,8 +228,23 @@ if(BUILD_PORT_MONITORS)
set(optional_sources ${optional_sources} ${port_monitors})
endif(BUILD_PORT_MONITORS)
if(BUILD_HTTP)
set(http
display-http.cc
display-http.hh
)
set(optional_sources ${optional_sources} ${http})
endif(BUILD_HTTP)
if(BUILD_X11)
set(x11 x11.cc x11.h)
set(x11
display-x11.cc
display-x11.hh
x11-settings.cc
x11-settings.h
x11.cc
x11.h
)
set(optional_sources ${optional_sources} ${x11})
endif(BUILD_X11)
@@ -245,14 +252,22 @@ if(BUILD_GUI)
set(gui fonts.cc fonts.h gui.cc gui.h)
set(optional_sources ${optional_sources} ${gui})
if(BUILD_MOUSE_EVENTS)
if(BUILD_MOUSE_EVENTS OR BUILD_XINPUT)
set(mouse_events mouse-events.cc mouse-events.h)
set(optional_sources ${optional_sources} ${mouse_events})
endif(BUILD_MOUSE_EVENTS)
endif(BUILD_MOUSE_EVENTS OR BUILD_XINPUT)
endif(BUILD_GUI)
if(BUILD_WAYLAND)
set(wl_srcs wl.cc wl.h xdg-shell-protocol.c wlr-layer-shell-protocol.c)
set(wl_srcs
wl.cc
wl.h
display-wayland.cc
display-wayland.hh
xdg-shell-protocol.c
wlr-layer-shell-protocol.c
)
set(optional_sources ${optional_sources} ${wl_srcs})
# generate protocol implementations
@@ -324,7 +339,12 @@ if(BUILD_ICONV)
endif(BUILD_ICONV)
if(BUILD_NCURSES)
set(ncurses_srcs nc.cc nc.h)
set(ncurses_srcs
nc.cc
nc.h
display-ncurses.cc
display-ncurses.hh
)
set(optional_sources ${optional_sources} ${ncurses_srcs})
endif(BUILD_NCURSES)

View File

@@ -26,25 +26,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "conky.h"
#include "gui.h"
#include "colours.h"
#include "logging.h"
#include "x11-color.h"
#include <optional>
#ifdef BUILD_X11
std::unordered_map<Colour, unsigned long, Colour::Hash> Colour::x11_pixels;
#include <X11/Xlib.h>
#include <string.h>
#include <strings.h>
#endif /* BUILD_X11 */
static int hex_nibble_value(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
return -1;
}
// sourced from X11, doesn't actually need X11
#include "x11-color.h"
Colour Colour::from_argb32(uint32_t argb) {
Colour out;
@@ -55,29 +51,91 @@ Colour Colour::from_argb32(uint32_t argb) {
return out;
}
Colour error_colour{0xff, 0x00, 0x00, 0xff};
#ifdef BUILD_X11
unsigned long Colour::to_x11_color(Display *display, int screen,
bool transparency, bool premultiply) {
static std::unordered_map<Colour, unsigned long, Colour::Hash> x11_pixels;
Colour parse_color(const char *name) {
unsigned short r, g, b;
size_t len = strlen(name);
// Parse X11 color names.
if (OsLookupColor(-1, name, len, &r, &g, &b)) {
Colour out = {(uint8_t)r, (uint8_t)g, (uint8_t)b, 0xff};
return out;
if (display == nullptr) {
/* cannot work if display is not open */
return 0;
}
// Remove a leading '#' if present.
unsigned long pixel;
/* Either get a cached X11 pixel or allocate one */
if (auto pixel_iter = x11_pixels.find(*this);
pixel_iter != x11_pixels.end()) {
pixel = pixel_iter->second;
} else {
XColor xcolor{};
xcolor.red = this->red * 257;
xcolor.green = this->green * 257;
xcolor.blue = this->blue * 257;
if (XAllocColor(display, DefaultColormap(display, screen), &xcolor) == 0) {
// NORM_ERR("can't allocate X color");
return 0;
}
/* Save pixel value in the cache to avoid reallocating it */
x11_pixels[*this] = xcolor.pixel;
pixel = static_cast<unsigned long>(xcolor.pixel);
}
pixel &= 0xffffff;
#ifdef BUILD_ARGB
if (transparency) {
if (premultiply)
pixel = (red * alpha / 255) << 16 | (green * alpha / 255) << 8 |
(blue * alpha / 255);
pixel |= ((unsigned long)alpha << 24);
}
#endif /* BUILD_ARGB */
return pixel;
}
#endif /* BUILD_X11 */
std::optional<Colour> parse_color_name(const std::string &name) {
unsigned short r, g, b;
size_t len = name.length();
// Parse X11 color names.
if (OsLookupColor(name.c_str(), len, &r, &g, &b)) {
return Colour{(uint8_t)r, (uint8_t)g, (uint8_t)b, 0xff};
} else {
return std::nullopt;
}
}
std::optional<Colour> parse_hex_color(const std::string &color) {
const char *name = color.c_str();
size_t len = color.length();
// Skip a leading '#' if present.
if (name[0] == '#') {
name++;
len--;
}
unsigned char argb[4] = {0xff, 0, 0, 0};
static auto hex_nibble_value = [](char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
return -1;
};
const auto none = [&]() {
NORM_ERR("can't parse hex color '%s' (%d)", name, len);
return std::nullopt;
};
uint8_t argb[4] = {0xff, 0, 0, 0};
if (len == 3 || len == 4) {
bool skip_alpha = (len == 3);
for (size_t i = 0; i < len; i++) {
int nib = hex_nibble_value(name[i]);
if (nib < 0) { goto err; }
if (nib < 0) { return none(); }
// Duplicate the nibble, so "#abc" -> 0xaa, 0xbb, 0xcc
int val = (nib << 4) + nib;
@@ -88,27 +146,35 @@ Colour parse_color(const char *name) {
for (size_t i = 0; i + 1 < len; i += 2) {
int nib1 = hex_nibble_value(name[i]);
int nib2 = hex_nibble_value(name[i + 1]);
if (nib1 < 0 || nib2 < 0) { goto err; }
if (nib1 < 0 || nib2 < 0) { return none(); }
int val = (nib1 << 4) + nib2;
argb[skip_alpha + i / 2] = val;
}
} else {
goto err;
return none();
}
Colour out;
out.alpha = argb[0];
out.red = argb[1];
out.green = argb[2];
out.blue = argb[3];
return out;
err:
NORM_ERR("can't parse X color '%s' (%d)", name, len);
return error_colour;
return Colour(argb[1], argb[2], argb[3], argb[0]);
}
Colour parse_color(const std::string &colour) {
return parse_color(colour.c_str());
Colour parse_color(const std::string &color) {
std::optional<Colour> result;
#define TRY_PARSER(name) \
std::optional<Colour> value_##name = name(color); \
if (value_##name.has_value()) { return value_##name.value(); }
std::optional<Colour> value_parse_color_name = parse_color_name(color);
if (value_parse_color_name.has_value()) {
return value_parse_color_name.value();
}
std::optional<Colour> value_parse_hex_color = parse_hex_color(color);
if (value_parse_hex_color.has_value()) {
return value_parse_hex_color.value();
}
#undef TRY_PARSER
return ERROR_COLOUR;
}

View File

@@ -26,31 +26,50 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <config.h>
#ifndef _COLOURS_H_
#define _COLOURS_H_
#include "config.h"
#include <cassert>
#include <climits>
#include <memory>
#include <string>
#include <unordered_map>
#ifdef BUILD_X11
#include "x11.h"
#include <X11/Xlib.h>
#endif /* BUILD_X11 */
struct Colour {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
uint8_t alpha = 0xff;
public:
Colour() = default;
Colour(uint8_t r, uint8_t g, uint8_t b, uint8_t a = UINT8_MAX)
: red(r), green(g), blue(b), alpha(a) {}
Colour(const Colour &) = default;
Colour(Colour &&) = default;
void operator=(const Colour &c) {
red = c.red;
green = c.green;
blue = c.blue;
alpha = c.alpha;
}
// Compare two instances.
bool operator==(const Colour &c) const {
return c.red == red && c.green == green && c.blue == blue &&
c.alpha == alpha;
}
uint8_t *data() { return reinterpret_cast<uint8_t *>(this); }
// Express the color as a 32-bit ARGB integer (alpha in MSB).
uint32_t to_argb32(void) const {
uint32_t out;
@@ -61,58 +80,20 @@ struct Colour {
// Construct from a 32-bit ARGB integer (alpha in MSB).
static Colour from_argb32(uint32_t argb);
#ifdef BUILD_X11
class Hash {
public:
size_t operator()(const Colour &c) const { return c.to_argb32(); }
};
static std::unordered_map<Colour, unsigned long, Hash> x11_pixels;
#ifdef BUILD_X11
unsigned long to_x11_color(Display *display, int screen,
bool premultiply = false) {
if (display == nullptr) {
/* cannot work if display is not open */
return 0;
}
unsigned long pixel;
/* Either get a cached X11 pixel or allocate one */
if (auto pixel_iter = x11_pixels.find(*this);
pixel_iter != x11_pixels.end()) {
pixel = pixel_iter->second;
} else {
XColor xcolor{};
xcolor.red = red * 257;
xcolor.green = green * 257;
xcolor.blue = blue * 257;
if (XAllocColor(display, DefaultColormap(display, screen), &xcolor) ==
0) {
// NORM_ERR("can't allocate X color");
return 0;
}
/* Save pixel value in the cache to avoid reallocating it */
x11_pixels[*this] = xcolor.pixel;
pixel = static_cast<unsigned long>(xcolor.pixel);
}
pixel &= 0xffffff;
#ifdef BUILD_ARGB
if (have_argb_visual) {
if (premultiply)
pixel = (red * alpha / 255) << 16 | (green * alpha / 255) << 8 |
(blue * alpha / 255);
pixel |= ((unsigned long)alpha << 24);
}
#endif /* BUILD_ARGB */
return pixel;
}
bool transparency = false,
bool premultiply = false);
#endif /* BUILD_X11 */
};
extern Colour error_colour;
const Colour ERROR_COLOUR = Colour{UINT8_MAX, 0, 0, UINT8_MAX};
Colour parse_color(const std::string &colour);
// XXX: when everyone uses C++ strings, remove this C version
Colour parse_color(const char *);
Colour parse_color(const std::string &color);
#endif /* _COLOURS_H_ */

View File

@@ -22,8 +22,9 @@
*/
#include "conky-imlib2.h"
#include "config.h"
#include "conky.h"
#include "common.h"
#include "display-output.hh"
#include "logging.h"
#include "text_object.h"
@@ -47,22 +48,24 @@ struct image_list_s {
};
struct image_list_s *image_list_start, *image_list_end;
std::array<std::array<int, 2>, 100> saved_coordinates;
/* areas to update */
Imlib_Updates updates, current_update;
/* our virtual framebuffer image we draw into */
Imlib_Image buffer, image;
namespace {
Imlib_Context context;
conky::range_config_setting<unsigned int> imlib_cache_flush_interval(
"imlib_cache_flush_interval", 0, std::numeric_limits<unsigned int>::max(),
0, true);
unsigned int cimlib_cache_flush_last = 0;
conky::simple_config_setting<bool> imlib_draw_blended("draw_blended", true,
true);
conky::simple_config_setting<bool> draw_blended("draw_blended", true, true);
namespace {
Imlib_Context context;
unsigned int cimlib_cache_flush_last = 0;
} // namespace
void imlib_cache_size_setting::lua_setter(lua::state &l, bool init) {
@@ -162,8 +165,9 @@ void cimlib_add_image(const char *args) {
tmp += 3;
int i;
if (sscanf(tmp, "%d", &i) == 1) {
cur->x = get_saved_coordinates_x(i);
cur->y = get_saved_coordinates_y(i);
const auto &coordinates = saved_coordinates.at(static_cast<size_t>(i));
cur->x = coordinates[0];
cur->y = coordinates[1];
}
}
if (cur->flush_interval < 0) {
@@ -237,7 +241,8 @@ static void cimlib_draw_all(int *clip_x, int *clip_y, int *clip_x2,
}
}
void cimlib_render(int x, int y, int width, int height) {
void cimlib_render(int x, int y, int width, int height, uint32_t flush_interval,
bool draw_blended) {
int clip_x = INT_MAX, clip_y = INT_MAX;
int clip_x2 = 0, clip_y2 = 0;
time_t now;
@@ -248,8 +253,8 @@ void cimlib_render(int x, int y, int width, int height) {
/* cheque if it's time to flush our cache */
now = time(nullptr);
if ((imlib_cache_flush_interval.get(*state) != 0u) &&
now - imlib_cache_flush_interval.get(*state) > cimlib_cache_flush_last) {
if ((flush_interval != 0u) &&
now - flush_interval > cimlib_cache_flush_last) {
int size = imlib_get_cache_size();
imlib_set_cache_size(0);
imlib_set_cache_size(size);
@@ -265,7 +270,7 @@ void cimlib_render(int x, int y, int width, int height) {
imlib_image_clear();
/* check if we should blend when rendering */
if (draw_blended.get(*state)) {
if (draw_blended) {
/* we can blend stuff now */
imlib_context_set_blend(1);
} else {
@@ -295,3 +300,5 @@ void cimlib_render(int x, int y, int width, int height) {
void print_image_callback(struct text_object *obj, char *, unsigned int) {
cimlib_add_image(obj->data.s);
}
imlib_cache_size_setting imlib_cache_size;

View File

@@ -24,17 +24,24 @@
#ifndef _CONKY_IMBLI2_H_
#define _CONKY_IMBLI2_H_
#include "conky.h"
#include "setting.hh"
#include "text_object.h"
#include <array>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
#include <X11/Xlib.h>
#pragma GCC diagnostic pop
using saved_coordinates_t = std::array<std::array<int, 2>, 100>;
extern saved_coordinates_t saved_coordinates;
void cimlib_add_image(const char *args);
void cimlib_set_cache_size(long size);
void cimlib_set_cache_flush_interval(long interval);
void cimlib_render(int x, int y, int width, int height);
void cimlib_render(int x, int y, int width, int height, uint32_t flush_interval,
bool draw_blended);
void cimlib_cleanup(void);
void print_image_callback(struct text_object *, char *, unsigned int);
@@ -53,4 +60,7 @@ class imlib_cache_size_setting
4096 * 1024, true) {}
};
extern conky::range_config_setting<unsigned int> imlib_cache_flush_interval;
extern conky::simple_config_setting<bool> imlib_draw_blended;
#endif /* _CONKY_IMBLI2_H_ */

View File

@@ -28,6 +28,9 @@
*/
#include "conky.h"
#include "config.h"
#include <algorithm>
#include <cerrno>
#include <climits>
@@ -40,24 +43,37 @@
#include <sstream>
#include <string>
#include <vector>
#include "common.h"
#include "config.h"
#include "text_object.h"
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif /* HAVE_DIRENT_H */
#include <fcntl.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#ifdef HAVE_SYS_INOTIFY_H
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc99-extensions"
#include <sys/inotify.h>
#pragma clang diagnostic pop
#endif /* HAVE_SYS_INOTIFY_H */
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif /* HAVE_DIRENT_H */
#include "common.h"
#include "text_object.h"
#ifdef BUILD_WAYLAND
#include "wl.h"
#endif /* BUILD_WAYLAND */
#ifdef BUILD_X11
#include "x11.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
#include <X11/Xutil.h>
@@ -69,21 +85,18 @@
#include "conky-imlib2.h"
#endif /* BUILD_IMLIB2 */
#endif /* BUILD_X11 */
#ifdef BUILD_NCURSES
#include <ncurses.h>
#endif
#include <fcntl.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined BUILD_RSS
#include <libxml/parser.h>
#endif
#endif /* BUILD_NCURSES */
#ifdef BUILD_CURL
#include <curl/curl.h>
#endif
#endif /* BUILD_CURL */
#ifdef BUILD_RSS
#include <libxml/parser.h>
#endif /* BUILD_RSS */
/* local headers */
#include "colours.h"
@@ -97,7 +110,7 @@
#include "fs.h"
#ifdef BUILD_ICONV
#include "iconv_tools.h"
#endif
#endif /* BUILD_ICONV */
#include "llua.h"
#include "logging.h"
#include "mail.h"
@@ -108,12 +121,13 @@
#include "template.h"
#include "timeinfo.h"
#include "top.h"
#ifdef BUILD_MYSQL
#include "mysql.h"
#endif /* BUILD_MYSQL */
#ifdef BUILD_NVIDIA
#include "nvidia.h"
#endif
#endif /* BUILD_NVIDIA */
#ifdef BUILD_CURL
#include "ccurl_thread.h"
#endif /* BUILD_CURL */
@@ -394,18 +408,6 @@ int calc_text_width(const char *s) {
return slen;
}
int dpi_scale(int value) {
#ifdef BUILD_GUI
if (display_output()) {
return display_output()->dpi_scale(value);
} else {
return value;
}
#else /* BUILD_GUI */
return value;
#endif /* BUILD_GUI */
}
#ifdef BUILD_GUI
conky::gradient_factory *create_gradient_factory(int width, Colour first_colour,
Colour last_colour) {
@@ -766,7 +768,7 @@ void remove_first_char(char *s) { memmove(s, s + 1, strlen(s)); }
static int get_string_width_special(char *s, int special_index) {
char *p, *final;
special_t *current = specials;
special_node *current = specials;
int width = 0;
long i;
@@ -789,22 +791,23 @@ static int get_string_width_special(char *s, int special_index) {
/*for (i = 0; i < static_cast<long>(strlen(p)); i++) {
*(p + i) = *(p + i + 1);
}*/
if (current->type == GRAPH || current->type == GAUGE ||
current->type == BAR) {
if (current->type == text_node_t::GRAPH ||
current->type == text_node_t::GAUGE ||
current->type == text_node_t::BAR) {
width += current->width;
}
if (current->type == FONT) {
if (current->type == text_node_t::FONT) {
// put all following text until the next fontchange/stringend in
// influenced_by_font but do not include specials
char *influenced_by_font = strdup(p);
special_t *current_after_font = current;
special_node *current_after_font = current;
// influenced_by_font gets special chars removed, so after this loop i
// counts the number of letters (not special chars) influenced by font
for (i = 0; influenced_by_font[i] != 0; i++) {
if (influenced_by_font[i] == SPECIAL_CHAR) {
// remove specials and stop at fontchange
current_after_font = current_after_font->next;
if (current_after_font->type == FONT) {
if (current_after_font->type == text_node_t::FONT) {
influenced_by_font[i] = 0;
break;
}
@@ -867,50 +870,34 @@ void update_text_area() {
alignment align = text_alignment.get(*state);
/* get text position on workarea */
switch (align) {
case TOP_LEFT:
case TOP_RIGHT:
case TOP_MIDDLE:
switch (vertical_alignment(align)) {
case axis_align::START:
y = workarea[1] + dpi_scale(gap_y.get(*state));
break;
case BOTTOM_LEFT:
case BOTTOM_RIGHT:
case BOTTOM_MIDDLE:
case axis_align::END:
default:
y = workarea[3] - text_height - dpi_scale(gap_y.get(*state));
break;
case MIDDLE_LEFT:
case MIDDLE_RIGHT:
case MIDDLE_MIDDLE:
case axis_align::MIDDLE:
y = workarea[1] + (workarea[3] - workarea[1]) / 2 - text_height / 2 -
dpi_scale(gap_y.get(*state));
break;
}
switch (align) {
case TOP_LEFT:
case BOTTOM_LEFT:
case MIDDLE_LEFT:
switch (horizontal_alignment(align)) {
case axis_align::START:
default:
x = workarea[0] + dpi_scale(gap_x.get(*state));
break;
case TOP_RIGHT:
case BOTTOM_RIGHT:
case MIDDLE_RIGHT:
case axis_align::END:
x = workarea[2] - text_width - dpi_scale(gap_x.get(*state));
break;
case TOP_MIDDLE:
case BOTTOM_MIDDLE:
case MIDDLE_MIDDLE:
case axis_align::MIDDLE:
x = workarea[0] + (workarea[2] - workarea[0]) / 2 - text_width / 2 -
dpi_scale(gap_x.get(*state));
break;
}
#ifdef OWN_WINDOW
if (align == NONE) { // Let the WM manage the window
if (align == alignment::NONE) { // Let the WM manage the window
x = window.x;
y = window.y;
@@ -941,20 +928,14 @@ static int cur_x, cur_y; /* current x and y for drawing */
#endif
// draw_mode also without BUILD_GUI because we only need to print to stdout with
// FG
static int draw_mode; /* FG, BG or OUTLINE */
static draw_mode_t draw_mode; /* FG, BG or OUTLINE */
#ifdef BUILD_GUI
/*static*/ Colour current_color;
static int saved_coordinates_x[100];
static int saved_coordinates_y[100];
int get_saved_coordinates_x(int i) { return saved_coordinates_x[i]; }
int get_saved_coordinates_y(int i) { return saved_coordinates_y[i]; }
static int text_size_updater(char *s, int special_index) {
int w = 0;
char *p;
special_t *current = specials;
special_node *current = specials;
for (int i = 0; i < special_index; i++) { current = current->next; }
@@ -969,26 +950,27 @@ static int text_size_updater(char *s, int special_index) {
w += get_string_width(s);
*p = SPECIAL_CHAR;
if (current->type == BAR || current->type == GAUGE ||
current->type == GRAPH) {
if (current->type == text_node_t::BAR ||
current->type == text_node_t::GAUGE ||
current->type == text_node_t::GRAPH) {
w += current->width;
if (current->height > last_font_height) {
last_font_height = current->height;
last_font_height += font_height();
}
} else if (current->type == OFFSET) {
} else if (current->type == text_node_t::OFFSET) {
if (current->arg > 0) { w += current->arg; }
} else if (current->type == VOFFSET) {
} else if (current->type == text_node_t::VOFFSET) {
last_font_height += current->arg;
} else if (current->type == GOTO) {
} else if (current->type == text_node_t::GOTO) {
if (current->arg > cur_x) { w = static_cast<int>(current->arg); }
} else if (current->type == TAB) {
} else if (current->type == 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;
} else if (current->type == FONT) {
} else if (current->type == text_node_t::FONT) {
selected_font = current->font_added;
if (font_height() > last_font_height) {
last_font_height = font_height();
@@ -1033,7 +1015,7 @@ static void draw_string(const char *s) {
#ifdef BUILD_GUI
width_of_s = get_string_width(s);
#endif /* BUILD_GUI */
if (draw_mode == FG) {
if (draw_mode == draw_mode_t::FG) {
for (auto output : display_outputs())
if (!output->graphical()) output->draw_string(s, 0);
}
@@ -1163,11 +1145,11 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
s = p + 1;
}
/* draw special */
special_t *current = specials;
special_node *current = specials;
for (int i = 0; i < special_index; i++) { current = current->next; }
switch (current->type) {
#ifdef BUILD_GUI
case HORIZONTAL_LINE:
case text_node_t::HORIZONTAL_LINE:
if (display_output() && display_output()->graphical()) {
int h = current->height;
int mid = font_ascent() / 2;
@@ -1183,7 +1165,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
}
break;
case STIPPLED_HR:
case text_node_t::STIPPLED_HR:
if (display_output() && display_output()->graphical()) {
int h = current->height;
char tmp_s = current->arg;
@@ -1201,7 +1183,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
}
break;
case BAR:
case text_node_t::BAR:
if (display_output() && display_output()->graphical()) {
int h, by;
double bar_usage, scale;
@@ -1229,7 +1211,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
}
break;
case GAUGE: /* new GAUGE */
case text_node_t::GAUGE: /* new GAUGE */
if (display_output() && display_output()->graphical()) {
int h, by = 0;
Colour last_colour = current_color;
@@ -1279,7 +1261,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
}
break;
case GRAPH:
case text_node_t::GRAPH:
if (display_output() && display_output()->graphical()) {
int h, by, i = 0, j = 0;
int colour_idx = 0;
@@ -1415,7 +1397,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
}
break;
case FONT:
case text_node_t::FONT:
if (display_output() && display_output()->graphical()) {
int old = font_ascent();
@@ -1431,41 +1413,42 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
}
break;
#endif /* BUILD_GUI */
case FG:
if (draw_mode == FG) {
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 BG:
if (draw_mode == BG) {
case text_node_t::BG:
if (draw_mode == draw_mode_t::BG) {
set_foreground_color(Colour::from_argb32(current->arg));
}
break;
case OUTLINE:
if (draw_mode == OUTLINE) {
case text_node_t::OUTLINE:
if (draw_mode == draw_mode_t::OUTLINE) {
set_foreground_color(Colour::from_argb32(current->arg));
}
break;
case OFFSET:
case text_node_t::OFFSET:
w += current->arg;
break;
case VOFFSET:
case text_node_t::VOFFSET:
cur_y += current->arg;
break;
case SAVE_COORDINATES:
saved_coordinates_x[static_cast<int>(current->arg)] =
cur_x - text_start_x;
saved_coordinates_y[static_cast<int>(current->arg)] =
cur_y - text_start_y - last_font_height;
case text_node_t::SAVE_COORDINATES:
#ifdef BUILD_IMLIB2
saved_coordinates[static_cast<int>(current->arg)] =
std::array<int, 2>{cur_x - text_start_x,
cur_y - text_start_y - last_font_height};
#endif /* BUILD_IMLIB2 */
break;
case TAB: {
case text_node_t::TAB: {
int start = current->arg;
int step = current->width;
@@ -1474,7 +1457,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
break;
}
case ALIGNR: {
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_width -
@@ -1491,7 +1474,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
break;
}
case ALIGNC: {
case text_node_t::ALIGNC: {
int pos_x = (text_width) / 2 -
get_string_width_special(s, special_index) / 2 -
(cur_x - text_start_x);
@@ -1507,17 +1490,20 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) {
break;
}
#endif /* BUILD_GUI */
case GOTO:
case text_node_t::GOTO:
if (current->arg >= 0) {
#ifdef BUILD_GUI
cur_x = static_cast<int>(current->arg);
// make sure shades are 1 pixel to the right of the text
if (draw_mode == BG) { cur_x++; }
if (draw_mode == draw_mode_t::BG) { cur_x++; }
#endif /* BUILD_GUI */
cur_x = static_cast<int>(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
@@ -1599,7 +1585,9 @@ void draw_stuff() {
#ifdef BUILD_IMLIB2
text_offset_x = text_offset_y = 0;
cimlib_render(text_start_x, text_start_y, window.width, window.height);
cimlib_render(text_start_x, text_start_y, window.width, window.height,
imlib_cache_flush_interval.get(*state),
imlib_draw_blended.get(*state));
#endif /* BUILD_IMLIB2 */
for (auto output : display_outputs()) {
@@ -1611,7 +1599,7 @@ void draw_stuff() {
if (draw_shades.get(*state) && !draw_outline.get(*state)) {
text_offset_x = text_offset_y = 1;
set_foreground_color(default_shade_color.get(*state));
draw_mode = BG;
draw_mode = draw_mode_t::BG;
draw_text();
text_offset_x = text_offset_y = 0;
}
@@ -1623,7 +1611,7 @@ void draw_stuff() {
for (text_offset_y = -1; text_offset_y < 2; text_offset_y++) {
if (text_offset_x == 0 && text_offset_y == 0) { continue; }
set_foreground_color(default_outline_color.get(*state));
draw_mode = OUTLINE;
draw_mode = draw_mode_t::OUTLINE;
draw_text();
}
}
@@ -1637,7 +1625,7 @@ void draw_stuff() {
#endif /* BUILD_GUI */
// always draw text
draw_mode = FG;
draw_mode = draw_mode_t::FG;
draw_text();
#ifdef BUILD_GUI
@@ -1874,10 +1862,10 @@ static void reload_config() {
initialisation(argc_copy, argv_copy);
}
void free_specials(special_t *&current) {
void free_specials(special_node *&current) {
if (current != nullptr) {
free_specials(current->next);
if (current->type == GRAPH) { free(current->graph); }
if (current->type == text_node_t::GRAPH) { free(current->graph); }
delete current;
current = nullptr;
}

View File

@@ -32,11 +32,14 @@
#define __STDC_FORMAT_MACROS
#include "config.h"
#include <arpa/inet.h>
#include <config.h> /* defines */
#include <sys/utsname.h> /* struct uname_s */
#include <csignal>
#include <memory>
#include "colours.h"
#include "common.h" /* at least for struct dns_data */
#include "luamm.hh"
@@ -311,11 +314,6 @@ void set_updatereset(int);
int get_updatereset(void);
int get_total_updates(void);
int dpi_scale(int value);
int get_saved_coordinates_x(int);
int get_saved_coordinates_y(int);
/* defined in conky.c */
int spaced_print(char *, int, const char *, int, ...)
__attribute__((format(printf, 3, 5)));

View File

@@ -27,9 +27,12 @@
*
*/
#include "config.h"
/* local headers */
#include "core.h"
#include "algebra.h"
#include "core.h"
#include "bsdapm.h"
#include "build.h"
#include "colour-settings.h"
@@ -40,11 +43,11 @@
#include "exec.h"
#include "i8k.h"
#include "misc.h"
#include "proc.h"
#include "text_object.h"
#ifdef BUILD_IMLIB2
#include "conky-imlib2.h"
#endif /* BUILD_IMLIB2 */
#include "proc.h"
#ifdef BUILD_MYSQL
#include "mysql.h"
#endif /* BUILD_MYSQL */
@@ -1893,9 +1896,10 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
obj->callbacks.print = &print_combine;
obj->callbacks.free = &free_combine;
#ifdef BUILD_NVIDIA
END OBJ_ARG(
nvidia, 0,
"nvidia needs an argument") if (set_nvidia_query(obj, arg, NONSPECIAL)) {
END OBJ_ARG(nvidia, 0, "nvidia needs an argument") if (set_nvidia_query(
obj, arg,
text_node_t::
NONSPECIAL)) {
CRIT_ERR_FREE(obj, free_at_crash,
"nvidia: invalid argument"
" specified: '%s'",
@@ -1905,7 +1909,8 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
obj->callbacks.free = &free_nvidia;
END OBJ_ARG(
nvidiabar, 0,
"nvidiabar needs an argument") if (set_nvidia_query(obj, arg, BAR)) {
"nvidiabar needs an argument") if (set_nvidia_query(obj, arg,
text_node_t::BAR)) {
CRIT_ERR_FREE(obj, free_at_crash,
"nvidiabar: invalid argument"
" specified: '%s'",
@@ -1915,7 +1920,9 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
obj->callbacks.free = &free_nvidia;
END OBJ_ARG(
nvidiagraph, 0,
"nvidiagraph needs an argument") if (set_nvidia_query(obj, arg, GRAPH)) {
"nvidiagraph needs an argument") if (set_nvidia_query(obj, arg,
text_node_t::
GRAPH)) {
CRIT_ERR_FREE(obj, free_at_crash,
"nvidiagraph: invalid argument"
" specified: '%s'",
@@ -1925,7 +1932,9 @@ struct text_object *construct_text_object(char *s, const char *arg, long line,
obj->callbacks.free = &free_nvidia;
END OBJ_ARG(
nvidiagauge, 0,
"nvidiagauge needs an argument") if (set_nvidia_query(obj, arg, GAUGE)) {
"nvidiagauge needs an argument") if (set_nvidia_query(obj, arg,
text_node_t::
GAUGE)) {
CRIT_ERR_FREE(obj, free_at_crash,
"nvidiagauge: invalid argument"
" specified: '%s'",

View File

@@ -43,9 +43,11 @@ namespace {
conky::display_output_console console_output("console");
} // namespace
void init_console_output() {}
namespace priv {} // namespace priv
template <>
void register_output<output_t::CONSOLE>(display_outputs_t &outputs) {
outputs.push_back(&console_output);
}
display_output_console::display_output_console(const std::string &name_)
: display_output_base(name_) {

View File

@@ -49,9 +49,10 @@ namespace {
conky::display_output_file file_output("file");
} // namespace
extern void init_file_output() {}
namespace priv {} // namespace priv
template <>
void register_output<output_t::FILE>(display_outputs_t &outputs) {
outputs.push_back(&file_output);
}
display_output_file::display_output_file(const std::string &name_)
: display_output_base(name_) {

View File

@@ -33,26 +33,20 @@
#include <sstream>
#include <unordered_map>
#ifdef BUILD_HTTP
#include <microhttpd.h>
#endif /* BUILD_HTTP */
namespace conky {
namespace {
#ifdef BUILD_HTTP
conky::display_output_http http_output;
#else
conky::disabled_display_output http_output_disabled("http", "BUILD_HTTP");
#endif
} // namespace
extern void init_http_output() {}
template <>
void register_output<output_t::HTTP>(display_outputs_t &outputs) {
outputs.push_back(&http_output);
}
// TODO: cleanup namespace
// namespace priv {
#ifdef BUILD_HTTP
#ifdef MHD_YES
/* older API */
#define MHD_Result int
@@ -130,12 +124,8 @@ std::string string_replace_all(std::string original, const std::string &oldpart,
return original;
}
#endif /* BUILD_HTTP */
//} // namespace priv
#ifdef BUILD_HTTP
display_output_http::display_output_http() : display_output_base("http") {
priority = 0;
httpd = NULL;
@@ -192,6 +182,4 @@ void display_output_http::draw_string(const char *s, int) {
webpage.append("<br />");
}
#endif /* BUILD_HTTP */
} // namespace conky

View File

@@ -23,6 +23,8 @@
#ifndef DISPLAY_HTTP_HH
#define DISPLAY_HTTP_HH
#include "config.h"
#include <limits>
#include <string>
#include <type_traits>

View File

@@ -35,33 +35,24 @@
#include <iostream>
#include <sstream>
#include <unordered_map>
#ifdef BUILD_NCURSES
#include <ncurses.h>
#endif
#ifdef BUILD_NCURSES
#include <ncurses.h>
extern WINDOW* ncurses_window;
#endif
namespace conky {
namespace {
#ifdef BUILD_NCURSES
conky::display_output_ncurses ncurses_output;
#else
conky::disabled_display_output ncurses_output_disabled("ncurses",
"BUILD_NCURSES");
#endif
} // namespace
extern void init_ncurses_output() {}
template <>
void register_output<output_t::NCURSES>(display_outputs_t& outputs) {
outputs.push_back(&ncurses_output);
}
// namespace priv {
//} // namespace priv
#ifdef BUILD_NCURSES
#define COLORS_BUILTIN 8
Colour ncurses_colors[COLORS_BUILTIN + COLORS_CUSTOM] = {
@@ -96,7 +87,7 @@ Colour from_ncurses(int nccolor) {
if (nccolor >= 0 && nccolor < COLORS_BUILTIN + COLORS_CUSTOM) {
return ncurses_colors[nccolor];
}
return error_colour;
return ERROR_COLOUR;
}
display_output_ncurses::display_output_ncurses()
@@ -179,7 +170,4 @@ void display_output_ncurses::flush() {
refresh();
clear();
}
#endif /* BUILD_NCURSES */
} // namespace conky

View File

@@ -23,6 +23,8 @@
#ifndef DISPLAY_NCURSES_HH
#define DISPLAY_NCURSES_HH
#include "config.h"
#include <limits>
#include <string>
#include <type_traits>

View File

@@ -27,7 +27,6 @@
#include <config.h>
#include "display-output.hh"
#include "logging.h"
#include <algorithm>
#include <iostream>
@@ -35,28 +34,37 @@
#include <unordered_map>
namespace conky {
namespace {
typedef std::unordered_map<std::string, display_output_base *>
display_outputs_t;
/*
* We cannot construct this object statically, because order of object
* construction in different modules is not defined, so register_source could be
* called before this object is constructed. Therefore, we create it on the
* first call to register_source.
*/
display_outputs_t *display_outputs;
} // namespace
// HACK: force the linker to link all the objects in with test enabled
extern void init_console_output();
extern void init_ncurses_output();
extern void init_file_output();
extern void init_http_output();
extern void init_x11_output();
extern void init_wayland_output();
inline void log_missing(const char *name, const char *flag) {
DBGP(
"%s display output disabled. Enable by recompiling with '%s' "
"flag enabled.",
name, flag);
}
#ifndef BUILD_HTTP
template <>
void register_output<output_t::HTTP>(display_outputs_t &outputs) {
log_missing("HTTP", "BUILD_HTTP");
}
#endif
#ifndef BUILD_NCURSES
template <>
void register_output<output_t::NCURSES>(display_outputs_t &outputs) {
log_missing("ncurses", "BUILD_NCURSES");
}
#endif
#ifndef BUILD_WAYLAND
template <>
void register_output<output_t::WAYLAND>(display_outputs_t &outputs) {
log_missing("Wayland", "BUILD_WAYLAND");
}
#endif
#ifndef BUILD_X11
template <>
void register_output<output_t::X11>(display_outputs_t &outputs) {
log_missing("X11", "BUILD_X11");
}
#endif
/*
* The selected and active display output.
@@ -69,55 +77,18 @@ std::vector<display_output_base *> active_display_outputs;
*/
std::vector<conky::display_output_base *> current_display_outputs;
namespace priv {
void do_register_display_output(const std::string &name,
display_output_base *output) {
struct display_output_constructor {
display_output_constructor() { display_outputs = new display_outputs_t(); }
~display_output_constructor() {
delete display_outputs;
display_outputs = nullptr;
}
};
static display_output_constructor constructor;
bool inserted = display_outputs->insert({name, output}).second;
if (!inserted) {
throw std::logic_error("Display output with name '" + name +
"' already registered");
}
}
} // namespace priv
display_output_base::display_output_base(const std::string &name_)
: name(name_), is_active(false), is_graphical(false), priority(-1) {
priv::do_register_display_output(name, this);
}
disabled_display_output::disabled_display_output(const std::string &name,
const std::string &define)
: display_output_base(name) {
priority = -2;
// XXX some generic way of reporting errors? NORM_ERR?
DBGP(
"Support for display output '%s' has been disabled during compilation. "
"Please recompile with '%s'",
name.c_str(), define.c_str());
}
bool initialize_display_outputs() {
init_console_output();
init_ncurses_output();
init_file_output();
init_http_output();
init_x11_output();
init_wayland_output();
std::vector<display_output_base *> outputs;
outputs.reserve(display_outputs->size());
outputs.reserve(static_cast<size_t>(output_t::OUTPUT_COUNT));
register_output<output_t::CONSOLE>(outputs);
register_output<output_t::NCURSES>(outputs);
register_output<output_t::FILE>(outputs);
register_output<output_t::HTTP>(outputs);
register_output<output_t::X11>(outputs);
register_output<output_t::WAYLAND>(outputs);
for (auto out : outputs) { NORM_ERR("FOUND: %s", out->name.c_str()); }
for (auto &output : *display_outputs) { outputs.push_back(output.second); }
// Sort display outputs by descending priority, to try graphical ones first.
sort(outputs.begin(), outputs.end(), &display_output_base::priority_compare);

View File

@@ -30,6 +30,7 @@
#include <vector>
#include "colours.h"
#include "logging.h"
#include "luamm.hh"
namespace conky {
@@ -57,11 +58,11 @@ class display_output_base {
public:
const std::string name;
bool is_active;
bool is_graphical;
int priority;
bool is_active = false;
bool is_graphical = false;
int priority = -1;
explicit display_output_base(const std::string &name_);
explicit display_output_base(const std::string &name) : name(name){};
virtual ~display_output_base() {}
@@ -106,7 +107,11 @@ class display_output_base {
virtual void draw_arc(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a1*/,
int /*a2*/) {}
virtual void move_win(int /*x*/, int /*y*/) {}
virtual int dpi_scale(int value) { return value; }
template <typename T, typename = typename std::enable_if<
std::is_arithmetic<T>::value, T>::type>
T dpi_scale(T value) {
return value;
}
virtual void begin_draw_stuff() {}
virtual void end_draw_stuff() {}
@@ -137,6 +142,20 @@ class display_output_base {
virtual bool active() { return is_active; }
};
using display_outputs_t = std::vector<display_output_base *>;
enum class output_t : uint32_t {
CONSOLE,
NCURSES,
FILE,
HTTP,
X11,
WAYLAND,
OUTPUT_COUNT
};
template <output_t Output>
void register_output(display_outputs_t &outputs);
/*
* The selected and active display outputs.
*/
@@ -148,17 +167,6 @@ extern std::vector<display_output_base *> active_display_outputs;
*/
extern std::vector<conky::display_output_base *> current_display_outputs;
/*
* Use this to declare a display output that has been disabled during
* compilation. We can then print a nice error message telling the used which
* setting to enable.
*/
class disabled_display_output : public display_output_base {
public:
const std::string define;
disabled_display_output(const std::string &name, const std::string &define);
};
} // namespace conky
// XXX: move to namespace?
@@ -178,6 +186,21 @@ static inline conky::display_output_base *display_output() {
return nullptr;
}
template <typename T, typename = typename std::enable_if<
std::is_arithmetic<T>::value, T>::type>
inline T dpi_scale(T value) {
#ifdef BUILD_GUI
auto output = display_output();
if (output) {
return output->dpi_scale(value);
} else {
return value;
}
#else /* BUILD_GUI */
return value;
#endif /* BUILD_GUI */
}
static inline void unset_display_output() {
conky::current_display_outputs.clear();
}

View File

@@ -24,9 +24,8 @@
*
*/
#include <config.h>
#include "display-wayland.hh"
#ifdef BUILD_WAYLAND
#include <wayland-client.h>
// #include "wayland.h"
#include <cairo.h>
@@ -44,23 +43,18 @@
#include <wlr-layer-shell-client-protocol.h>
#include <xdg-shell-client-protocol.h>
#endif /* BUILD_WAYLAND */
#include <cstdint>
#include <iostream>
#include <sstream>
#include "conky.h"
#include "display-wayland.hh"
#include "display-output.hh"
#include "gui.h"
#include "llua.h"
#include "logging.h"
#ifdef BUILD_X11
#include "x11.h"
#endif
#ifdef BUILD_WAYLAND
#include "fonts.h"
#endif
#ifdef BUILD_MOUSE_EVENTS
#include <array>
#include <map>
@@ -69,9 +63,6 @@
#pragma GCC diagnostic ignored "-Wunused-parameter"
/* TODO: cleanup global namespace */
#ifdef BUILD_WAYLAND
static int set_cloexec_or_close(int fd) {
long flags;
@@ -238,24 +229,15 @@ static void wayland_create_window() {
update_text_area(); /* to get initial size of the window */
}
#endif /* BUILD_WAYLAND */
namespace conky {
namespace {
#ifdef BUILD_WAYLAND
conky::display_output_wayland wayland_output;
#else
conky::disabled_display_output wayland_output_disabled("wayland",
"BUILD_WAYLAND");
#endif
} // namespace
extern void init_wayland_output() {}
namespace priv {} // namespace priv
#ifdef BUILD_WAYLAND
template <>
void register_output<output_t::WAYLAND>(display_outputs_t &outputs) {
outputs.push_back(&wayland_output);
}
display_output_wayland::display_output_wayland()
: display_output_base("wayland") {
@@ -489,7 +471,11 @@ static void on_pointer_button(void *data, struct wl_pointer *pointer,
size_t abs_y = w->rectangle.y + y;
mouse_button_event event{
mouse_event_t::MOUSE_RELEASE, x, y, abs_x, abs_y,
mouse_event_t::RELEASE,
x,
y,
abs_x,
abs_y,
static_cast<mouse_button_t>(button),
};
@@ -498,7 +484,7 @@ static void on_pointer_button(void *data, struct wl_pointer *pointer,
// pass; default is MOUSE_RELEASE
break;
case WL_POINTER_BUTTON_STATE_PRESSED:
event.type = mouse_event_t::MOUSE_PRESS;
event.type = mouse_event_t::PRESS;
break;
default:
return;
@@ -519,17 +505,17 @@ void on_pointer_axis(void *data, struct wl_pointer *pointer, std::uint32_t time,
size_t abs_y = w->rectangle.y + y;
mouse_scroll_event event{
x, y, abs_x, abs_y, scroll_direction_t::SCROLL_UP,
x, y, abs_x, abs_y, scroll_direction_t::UP,
};
switch (static_cast<wl_pointer_axis>(axis)) {
case WL_POINTER_AXIS_VERTICAL_SCROLL:
event.direction = value > 0 ? scroll_direction_t::SCROLL_DOWN
: scroll_direction_t::SCROLL_UP;
event.direction =
value > 0 ? scroll_direction_t::DOWN : scroll_direction_t::UP;
break;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
event.direction = value > 0 ? scroll_direction_t::SCROLL_RIGHT
: scroll_direction_t::SCROLL_LEFT;
event.direction =
value > 0 ? scroll_direction_t::RIGHT : scroll_direction_t::LEFT;
break;
default:
return;
@@ -577,7 +563,9 @@ bool display_output_wayland::initialize() {
wl_display_roundtrip(global_display);
if (wl_globals.layer_shell == nullptr) {
CRIT_ERR("Compositor doesn't support wlr-layer-shell-unstable-v1. Can't run conky.");
CRIT_ERR(
"Compositor doesn't support wlr-layer-shell-unstable-v1. Can't run "
"conky.");
}
struct wl_surface *surface =
@@ -705,48 +693,34 @@ bool display_output_wayland::main_loop_wait(double t) {
/* update struts */
if (changed != 0) {
int anchor = -1;
int anchor = 0;
DBGP("%s", _(PACKAGE_NAME ": defining struts\n"));
fflush(stderr);
switch (text_alignment.get(*state)) {
case TOP_LEFT:
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
alignment text_align = text_alignment.get(*state);
switch (vertical_alignment(text_align)) {
case axis_align::START:
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
break;
case TOP_RIGHT:
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
case axis_align::END:
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
break;
case TOP_MIDDLE: {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
default:
break;
}
case BOTTOM_LEFT:
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
break;
case BOTTOM_RIGHT:
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
break;
case BOTTOM_MIDDLE: {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
break;
}
case MIDDLE_LEFT: {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
break;
}
case MIDDLE_RIGHT: {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
break;
}
case NONE:
case MIDDLE_MIDDLE: /* XXX What about these? */;
}
switch (horizontal_alignment(text_align)) {
case axis_align::START:
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
break;
case axis_align::END:
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
break;
default:
break;
}
// middle anchor alignment is the default and requires no special
// handling.
if (anchor != -1) {
zwlr_layer_surface_v1_set_anchor(global_window->layer_surface, anchor);
@@ -939,8 +913,10 @@ void display_output_wayland::move_win(int x, int y) {
// window.y = y;
// TODO
}
int display_output_wayland::dpi_scale(int value) { return value; }
template <typename T, typename>
T display_output_wayland::dpi_scale(T value) {
return value;
}
void display_output_wayland::end_draw_stuff() {
window_commit_buffer(global_window);
@@ -1292,6 +1268,4 @@ void window_get_width_height(struct window *window, int *w, int *h) {
*h = window->rectangle.height;
}
#endif /* BUILD_WAYLAND */
} // namespace conky

View File

@@ -23,6 +23,8 @@
#ifndef DISPLAY_WAYLAND_HH
#define DISPLAY_WAYLAND_HH
#include "config.h"
#include <limits>
#include <string>
#include <type_traits>
@@ -69,7 +71,9 @@ class display_output_wayland : public display_output_base {
virtual void fill_rect(int, int, int, int);
virtual void draw_arc(int, int, int, int, int, int);
virtual void move_win(int, int);
virtual int dpi_scale(int);
template <typename T, typename = typename std::enable_if<
std::is_arithmetic<T>::value, T>::type>
T dpi_scale(T value);
virtual void end_draw_stuff();
virtual void clear_text(int);

View File

@@ -24,10 +24,8 @@
*
*/
#include <X11/extensions/XI2.h>
#include <config.h>
#include "config.h"
#ifdef BUILD_X11
#include <X11/X.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
@@ -43,13 +41,14 @@
#ifdef BUILD_IMLIB2
#include "conky-imlib2.h"
#endif /* BUILD_IMLIB2 */
#ifdef BUILD_MOUSE_EVENTS
#if defined(BUILD_MOUSE_EVENTS) || defined(BUILD_XINPUT)
#include "mouse-events.h"
#endif /* BUILD_MOUSE_EVENTS || BUILD_XINPUT */
#ifdef BUILD_XINPUT
#include <X11/extensions/XI2.h>
#include <X11/extensions/XInput2.h>
#undef COUNT
#endif /* BUILD_XINPUT */
#endif /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_X11 */
#include <cstdint>
#include <iostream>
@@ -65,9 +64,6 @@
#include "gui.h"
#include "llua.h"
/* TODO: cleanup global namespace */
#ifdef BUILD_X11
#include "logging.h"
#include "x11.h"
@@ -195,23 +191,15 @@ static void X11_create_window() {
update_text_area(); /* to get initial size of the window */
}
#endif /* BUILD_X11 */
namespace conky {
namespace {
#ifdef BUILD_X11
conky::display_output_x11 x11_output;
#else
conky::disabled_display_output x11_output_disabled("x11", "BUILD_X11");
#endif
} // namespace
extern void init_x11_output() {}
namespace priv {} // namespace priv
#ifdef BUILD_X11
template <>
void register_output<output_t::X11>(display_outputs_t &outputs) {
outputs.push_back(&x11_output);
}
display_output_x11::display_output_x11() : display_output_base("x11") {
is_graphical = true;
@@ -324,39 +312,38 @@ bool display_output_x11::main_loop_wait(double t) {
}
/* update struts */
if ((changed != 0) && own_window_type.get(*state) == TYPE_PANEL) {
if ((changed != 0) && own_window_type.get(*state) == window_type::PANEL) {
int sidenum = -1;
DBGP("%s", _(PACKAGE_NAME ": defining struts\n"));
fflush(stderr);
NORM_ERR("defining struts");
switch (text_alignment.get(*state)) {
case TOP_LEFT:
case TOP_RIGHT:
case TOP_MIDDLE: {
alignment align = text_alignment.get(*state);
switch (align) {
case alignment::TOP_LEFT:
case alignment::TOP_RIGHT:
case alignment::TOP_MIDDLE: {
sidenum = 2;
break;
}
case BOTTOM_LEFT:
case BOTTOM_RIGHT:
case BOTTOM_MIDDLE: {
case alignment::BOTTOM_LEFT:
case alignment::BOTTOM_RIGHT:
case alignment::BOTTOM_MIDDLE: {
sidenum = 3;
break;
}
case MIDDLE_LEFT: {
case alignment::MIDDLE_LEFT: {
sidenum = 0;
break;
}
case MIDDLE_RIGHT: {
case alignment::MIDDLE_RIGHT: {
sidenum = 1;
break;
}
case NONE:
case MIDDLE_MIDDLE: /* XXX What about these? */;
default:
break;
}
set_struts(sidenum);
if (sidenum != -1) set_struts(sidenum);
}
}
#endif
@@ -425,11 +412,10 @@ bool display_output_x11::main_loop_wait(double t) {
return true;
}
enum x_event_handler {
enum class x_event_handler {
XINPUT_MOTION,
MOUSE_INPUT,
PROPERTY_NOTIFY,
EXPOSE,
REPARENT,
CONFIGURE,
@@ -485,8 +471,6 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
Window event_window =
query_x11_window_at_pos(display, data->root_x, data->root_y);
// query_result is not window.window in some cases.
modifier_state_t mods = x11_modifier_state(data->mods.effective);
bool same_window = query_x11_top_parent(display, event_window) ==
query_x11_top_parent(display, window.window);
@@ -518,6 +502,10 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
return true;
}
#ifdef BUILD_MOUSE_EVENTS
// query_result is not window.window in some cases.
modifier_state_t mods = x11_modifier_state(data->mods.effective);
if (data->evtype == XI_Motion) {
// TODO: Make valuator_index names configurable?
@@ -556,20 +544,18 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
double vertical_value = vertical.value_or(0.0);
if (vertical_value != 0.0) {
scroll_direction = vertical_value < 0.0
? scroll_direction_t::SCROLL_UP
: scroll_direction_t::SCROLL_DOWN;
scroll_direction = vertical_value < 0.0 ? scroll_direction_t::UP
: scroll_direction_t::DOWN;
} else {
auto horizontal = data->valuator_relative_value(valuator_t::SCROLL_X);
double horizontal_value = horizontal.value_or(0.0);
if (horizontal_value != 0.0) {
scroll_direction = horizontal_value < 0.0
? scroll_direction_t::SCROLL_LEFT
: scroll_direction_t::SCROLL_RIGHT;
scroll_direction = horizontal_value < 0.0 ? scroll_direction_t::LEFT
: scroll_direction_t::RIGHT;
}
}
if (scroll_direction != scroll_direction_t::SCROLL_UNKNOWN) {
if (scroll_direction != scroll_direction_t::UNKNOWN) {
*consumed = llua_mouse_hook(
mouse_scroll_event(data->event_x, data->event_y, data->root_x,
data->root_y, scroll_direction, mods));
@@ -583,16 +569,16 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
return true;
}
mouse_event_t type = mouse_event_t::MOUSE_PRESS;
if (data->evtype == XI_ButtonRelease) {
type = mouse_event_t::MOUSE_RELEASE;
}
mouse_event_t type = mouse_event_t::PRESS;
if (data->evtype == XI_ButtonRelease) { type = mouse_event_t::RELEASE; }
mouse_button_t button = x11_mouse_button_code(data->detail);
*consumed = llua_mouse_hook(mouse_button_event(type, data->event_x,
data->event_y, data->root_x,
data->root_y, button, mods));
}
#endif /* BUILD_MOUSE_EVENTS */
#else /* BUILD_XINPUT */
if (ev.type != ButtonPress && ev.type != ButtonRelease &&
ev.type != MotionNotify)
@@ -612,9 +598,10 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
} else {
mouse_button_t button = x11_mouse_button_code(ev.xbutton.button);
*consumed = llua_mouse_hook(mouse_button_event(
mouse_event_t::MOUSE_PRESS, ev.xbutton.x, ev.xbutton.y,
ev.xbutton.x_root, ev.xbutton.y_root, button, mods));
mouse_event_t::PRESS, ev.xbutton.x, ev.xbutton.y, ev.xbutton.x_root,
ev.xbutton.y_root, button, mods));
}
break;
}
case ButtonRelease: {
/* don't report scroll release events */
@@ -623,31 +610,35 @@ bool handle_event<x_event_handler::MOUSE_INPUT>(
modifier_state_t mods = x11_modifier_state(ev.xbutton.state);
mouse_button_t button = x11_mouse_button_code(ev.xbutton.button);
*consumed = llua_mouse_hook(mouse_button_event(
mouse_event_t::MOUSE_RELEASE, ev.xbutton.x, ev.xbutton.y,
ev.xbutton.x_root, ev.xbutton.y_root, button, mods));
mouse_event_t::RELEASE, ev.xbutton.x, ev.xbutton.y, ev.xbutton.x_root,
ev.xbutton.y_root, button, mods));
break;
}
case MotionNotify: {
modifier_state_t mods = x11_modifier_state(ev.xmotion.state);
*consumed = llua_mouse_hook(mouse_move_event(ev.xmotion.x, ev.xmotion.y,
ev.xmotion.x_root,
ev.xmotion.y_root, mods));
break;
}
}
#else /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_XINPUT */
#ifndef BUILD_MOUSE_EVENTS
// always propagate mouse input if not handling mouse events
*consumed = false;
#endif /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_XINPUT */
if (!own_window.get(*state)) return true;
switch (own_window_type.get(*state)) {
case window_type::TYPE_NORMAL:
case window_type::TYPE_UTILITY:
case window_type::NORMAL:
case window_type::UTILITY:
// decorated normal windows always consume events
if (!TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) {
if (!TEST_HINT(own_window_hints.get(*state), window_hints::UNDECORATED)) {
*consumed = true;
}
break;
case window_type::TYPE_DESKTOP:
case window_type::DESKTOP:
// assume conky is always on bottom; nothing to propagate events to
*consumed = true;
default:
@@ -714,6 +705,31 @@ bool handle_event<x_event_handler::CONFIGURE>(
return true;
}
#ifdef BUILD_MOUSE_EVENTS
template <>
bool handle_event<x_event_handler::BORDER_CROSSING>(
conky::display_output_x11 *surface, Display *display, XEvent &ev,
bool *consumed, void **cookie) {
if (ev.type != EnterNotify && ev.type != LeaveNotify) return false;
if (window.xi_opcode != 0) return true; // handled by mouse_input already
bool not_over_conky = ev.xcrossing.x_root <= window.x ||
ev.xcrossing.y_root <= window.y ||
ev.xcrossing.x_root >= window.x + window.width ||
ev.xcrossing.y_root >= window.y + window.height;
if ((not_over_conky && ev.xcrossing.type == LeaveNotify) ||
(!not_over_conky && ev.xcrossing.type == EnterNotify)) {
llua_mouse_hook(mouse_crossing_event(
ev.xcrossing.type == EnterNotify ? mouse_event_t::AREA_ENTER
: mouse_event_t::AREA_LEAVE,
ev.xcrossing.x, ev.xcrossing.y, ev.xcrossing.x_root,
ev.xcrossing.y_root));
}
return true;
}
#endif /* BUILD_MOUSE_EVENTS */
#endif /* OWN_WINDOW */
template <>
@@ -757,29 +773,6 @@ bool handle_event<x_event_handler::EXPOSE>(conky::display_output_x11 *surface,
return true;
}
template <>
bool handle_event<x_event_handler::BORDER_CROSSING>(
conky::display_output_x11 *surface, Display *display, XEvent &ev,
bool *consumed, void **cookie) {
if (ev.type != EnterNotify && ev.type != LeaveNotify) return false;
if (window.xi_opcode != 0) return true; // handled by mouse_input already
bool not_over_conky = ev.xcrossing.x_root <= window.x ||
ev.xcrossing.y_root <= window.y ||
ev.xcrossing.x_root >= window.x + window.width ||
ev.xcrossing.y_root >= window.y + window.height;
if ((not_over_conky && ev.xcrossing.type == LeaveNotify) ||
(!not_over_conky && ev.xcrossing.type == EnterNotify)) {
llua_mouse_hook(mouse_crossing_event(
ev.xcrossing.type == EnterNotify ? mouse_event_t::AREA_ENTER
: mouse_event_t::AREA_LEAVE,
ev.xcrossing.x, ev.xcrossing.y, ev.xcrossing.x_root,
ev.xcrossing.y_root));
}
return true;
}
#ifdef BUILD_XDAMAGE
template <>
bool handle_event<x_event_handler::DAMAGE>(conky::display_output_x11 *surface,
@@ -820,6 +813,8 @@ bool process_event(conky::display_output_x11 *surface, Display *display,
HANDLE_EV(BORDER_CROSSING)
HANDLE_EV(DAMAGE)
#undef HANDLE_EV
// event not handled
return false;
}
@@ -889,7 +884,7 @@ void display_output_x11::set_foreground_color(Colour c) {
}
#endif /* BUILD_ARGB */
XSetForeground(display, window.gc,
current_color.to_x11_color(display, screen));
current_color.to_x11_color(display, screen, have_argb_visual));
}
int display_output_x11::calc_text_width(const char *s) {
@@ -918,7 +913,7 @@ void display_output_x11::draw_string_at(int x, int y, const char *s, int w) {
XColor c{};
XftColor c2{};
c.pixel = current_color.to_x11_color(display, screen);
c.pixel = current_color.to_x11_color(display, screen, have_argb_visual);
// query color on custom colormap
XQueryColor(display, window.colourmap, &c);
@@ -972,15 +967,19 @@ 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.x = x;
window.y = y;
XMoveWindow(display, window.window, x, y);
#endif /* OWN_WINDOW */
}
int display_output_x11::dpi_scale(int value) {
const size_t PIXELS_PER_INCH = 96;
template <typename T, typename>
T display_output_x11::dpi_scale(T value) {
#if defined(BUILD_XFT)
if (use_xft.get(*state) && xft_dpi > 0) {
return (value * xft_dpi + (value > 0 ? 48 : -48)) / 96;
return (value * xft_dpi + (value > 0 ? 48 : -48)) / PIXELS_PER_INCH;
} else {
return value;
}
@@ -1171,6 +1170,4 @@ void display_output_x11::load_fonts(bool utf8) {
}
}
#endif /* BUILD_X11 */
} // namespace conky

View File

@@ -23,6 +23,8 @@
#ifndef DISPLAY_X11_HH
#define DISPLAY_X11_HH
#include "config.h"
#include <limits>
#include <string>
#include <type_traits>
@@ -67,7 +69,9 @@ class display_output_x11 : public display_output_base {
virtual void fill_rect(int, int, int, int);
virtual void draw_arc(int, int, int, int, int, int);
virtual void move_win(int, int);
virtual int dpi_scale(int);
template <typename T, typename = typename std::enable_if<
std::is_arithmetic<T>::value, T>::type>
T dpi_scale(T value);
virtual void end_draw_stuff();
virtual void clear_text(int);

View File

@@ -32,11 +32,14 @@
#include "config.h"
#include "conky.h"
#include "logging.h"
#include "wl.h"
#ifdef BUILD_IMLIB2
#include "conky-imlib2.h"
#endif /* BUILD_IMLIB2 */
#ifdef BUILD_WAYLAND
#include "wl.h"
#endif /* BUILD_WAYLAND */
// #ifdef BUILD_IMLIB2
// #include "conky-imlib2.h"
// #endif /* BUILD_IMLIB2 */
#ifndef OWN_WINDOW
#include <iostream>
#endif
@@ -103,41 +106,46 @@ void own_window_setting::lua_setter(lua::state &l, bool init) {
template <>
conky::lua_traits<alignment>::Map conky::lua_traits<alignment>::map = {
{"top_left", TOP_LEFT},
{"top_right", TOP_RIGHT},
{"top_middle", TOP_MIDDLE},
{"bottom_left", BOTTOM_LEFT},
{"bottom_right", BOTTOM_RIGHT},
{"bottom_middle", BOTTOM_MIDDLE},
{"middle_left", MIDDLE_LEFT},
{"middle_middle", MIDDLE_MIDDLE},
{"middle_right", MIDDLE_RIGHT},
{"tl", TOP_LEFT},
{"tr", TOP_RIGHT},
{"tm", TOP_MIDDLE},
{"bl", BOTTOM_LEFT},
{"br", BOTTOM_RIGHT},
{"bm", BOTTOM_MIDDLE},
{"ml", MIDDLE_LEFT},
{"mm", MIDDLE_MIDDLE},
{"mr", MIDDLE_RIGHT},
{"none", NONE}};
{"top_left", alignment::TOP_LEFT},
{"top_right", alignment::TOP_RIGHT},
{"top_middle", alignment::TOP_MIDDLE},
{"top", alignment::TOP_MIDDLE},
{"bottom_left", alignment::BOTTOM_LEFT},
{"bottom_right", alignment::BOTTOM_RIGHT},
{"bottom_middle", alignment::BOTTOM_MIDDLE},
{"bottom", alignment::BOTTOM_MIDDLE},
{"middle_left", alignment::MIDDLE_LEFT},
{"left", alignment::MIDDLE_LEFT},
{"middle_middle", alignment::MIDDLE_MIDDLE},
{"center", alignment::MIDDLE_MIDDLE},
{"middle_right", alignment::MIDDLE_RIGHT},
{"right", alignment::MIDDLE_RIGHT},
{"tl", alignment::TOP_LEFT},
{"tr", alignment::TOP_RIGHT},
{"tm", alignment::TOP_MIDDLE},
{"bl", alignment::BOTTOM_LEFT},
{"br", alignment::BOTTOM_RIGHT},
{"bm", alignment::BOTTOM_MIDDLE},
{"ml", alignment::MIDDLE_LEFT},
{"mm", alignment::MIDDLE_MIDDLE},
{"mr", alignment::MIDDLE_RIGHT},
{"none", alignment::NONE}};
#ifdef OWN_WINDOW
template <>
conky::lua_traits<window_type>::Map conky::lua_traits<window_type>::map = {
{"normal", TYPE_NORMAL}, {"dock", TYPE_DOCK},
{"panel", TYPE_PANEL}, {"desktop", TYPE_DESKTOP},
{"utility", TYPE_UTILITY}, {"override", TYPE_OVERRIDE}};
{"normal", window_type::NORMAL}, {"dock", window_type::DOCK},
{"panel", window_type::PANEL}, {"desktop", window_type::DESKTOP},
{"utility", window_type::UTILITY}, {"override", window_type::OVERRIDE}};
template <>
conky::lua_traits<window_hints>::Map conky::lua_traits<window_hints>::map = {
{"undecorated", HINT_UNDECORATED},
{"below", HINT_BELOW},
{"above", HINT_ABOVE},
{"sticky", HINT_STICKY},
{"skip_taskbar", HINT_SKIP_TASKBAR},
{"skip_pager", HINT_SKIP_PAGER}};
{"undecorated", window_hints::UNDECORATED},
{"below", window_hints::BELOW},
{"above", window_hints::ABOVE},
{"sticky", window_hints::STICKY},
{"skip_taskbar", window_hints::SKIP_TASKBAR},
{"skip_pager", window_hints::SKIP_PAGER}};
std::pair<uint16_t, bool> window_hints_traits::convert(
lua::state &l, int index, const std::string &name) {
@@ -185,7 +193,8 @@ std::string gethostnamecxx() {
* setting.cc.
*/
conky::simple_config_setting<alignment> text_alignment("alignment", BOTTOM_LEFT,
conky::simple_config_setting<alignment> text_alignment("alignment",
alignment::BOTTOM_LEFT,
false);
priv::colour_setting default_shade_color("default_shade_color", black_argb32);
@@ -209,7 +218,8 @@ conky::simple_config_setting<std::string> own_window_title(
conky::simple_config_setting<std::string> own_window_class("own_window_class",
PACKAGE_NAME, false);
conky::simple_config_setting<window_type> own_window_type("own_window_type",
TYPE_NORMAL, false);
window_type::NORMAL,
false);
conky::simple_config_setting<uint16_t, window_hints_traits> own_window_hints(
"own_window_hints", 0, false);
#endif /* OWN_WINDOW && BUILD_X11 */

156
src/gui.h
View File

@@ -25,14 +25,146 @@
#include "config.h"
#ifdef BUILD_X11
#include "x11.h"
#endif /* BUILD_X11 */
#include "colour-settings.h"
#include "colours.h"
#include "setting.hh"
#include "colour-settings.h"
#ifdef BUILD_X11
#include <X11/Xlib.h>
#include "x11-settings.h"
#endif /* BUILD_X11 */
/// @brief Represents alignment on a single axis.
enum class axis_align : uint8_t {
/// No alignment
NONE = 0,
/// Top or left alignment
START = 0b01,
/// Middle alignment
MIDDLE = 0b10,
/// Bottom or right alignment
END = 0b11,
};
constexpr uint8_t operator*(axis_align index) {
return static_cast<uint8_t>(index);
}
/// @brief Represents alignment on a 2D plane.
///
/// Values are composed of 2 `axis_align` values: 2 bits (at 0x0C) for vertical
/// aligment and 2 least significant bits for horizontal.
enum class alignment : uint8_t {
NONE = 0,
NONE_LEFT = 0b0001,
NONE_MIDDLE = 0b0010,
NONE_RIGHT = 0b0011,
TOP_LEFT = 0b0101,
TOP_MIDDLE = 0b0110,
TOP_RIGHT = 0b0111,
MIDDLE_LEFT = 0b1001,
MIDDLE_MIDDLE = 0b1010,
MIDDLE_RIGHT = 0b1011,
BOTTOM_LEFT = 0b1101,
BOTTOM_MIDDLE = 0b1110,
BOTTOM_RIGHT = 0b1111,
};
constexpr uint8_t operator*(alignment index) {
return static_cast<uint8_t>(index);
}
/// @brief Returns the horizontal axis alignment component of `alignment`.
/// @param of 2D alignment to extract axis alignment from
/// @return horizontal `axis_align`
[[nodiscard]] inline axis_align horizontal_alignment(alignment of) {
return static_cast<axis_align>(static_cast<uint8_t>(of) & 0b11);
}
/// @brief Returns the vertical axis alignment component of `alignment`.
/// @param of 2D alignment to extract axis alignment from
/// @return vertical `axis_align`
[[nodiscard]] inline axis_align vertical_alignment(alignment of) {
return static_cast<axis_align>((static_cast<uint8_t>(of) >> 2) & 0b11);
}
/// @brief Describes how and where a window should be mounted, as well as its
/// behavior.
///
/// We assume the following order of layers:
/// - Background - behind conky and any other windows, contains icons and
/// desktop menus
/// - Background widgets and docks
/// - Windows
/// - Panels - contains content that covers windows
/// - Override windows - input-override windows on X11, custom overlays, lock
/// screens, etc.
///
/// See also:
/// - [X11 wm-spec `_NET_WM_WINDOW_TYPE` property](
/// https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html#idm45684324619328)
/// - [wlr-layer-shell layers](
/// https://wayland.app/protocols/wlr-layer-shell-unstable-v1#zwlr_layer_shell_v1:enum:layer)
/// - [xdg-positioner::anchor](
/// https://wayland.app/protocols/xdg-shell#xdg_positioner:enum:anchor)
enum class window_type : uint8_t {
/// @brief Acts as a normal window - has decorations, above
/// background, widgets and docks, below panels.
NORMAL = 0,
/// @brief Screen background, no decorations, positioned at the very bottom
/// and behind widgets and docks.
DESKTOP,
/// @brief Normal window, always shown above parent window (group).
///
/// See: [Popup](https://wayland.app/protocols/xdg-shell#xdg_popup) XDG shell
/// surface.
UTILITY,
/// @brief No decorations, between windows and background, attached to screen
/// edge.
DOCK,
/// @brief No decorations, above windows, attached to screen edge, reserves
/// space.
PANEL,
#ifdef BUILD_X11
/// @brief On top of everything else, not controlled by WM.
OVERRIDE,
#endif /* BUILD_X11 */
};
constexpr uint8_t operator*(window_type index) {
return static_cast<uint8_t>(index);
}
#if defined(BUILD_X11) && defined(OWN_WINDOW)
// Only works in X11 because Wayland doesn't support
/// @brief Hints are used to tell WM how it should treat a window.
///
/// See: [X11 wm-spec `_NET_WM_STATE` property](
/// https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html#idm45684324611552)
enum class window_hints : uint16_t {
UNDECORATED = 0,
BELOW,
ABOVE,
STICKY,
SKIP_TASKBAR,
SKIP_PAGER
};
constexpr uint8_t operator*(window_hints index) {
return static_cast<uint8_t>(index);
}
inline void SET_HINT(window_hints &mask, window_hints hint) {
mask = static_cast<window_hints>(*mask | (1 << (*hint)));
}
inline void SET_HINT(uint16_t &mask, window_hints hint) {
mask = mask | (1 << (*hint));
}
inline bool TEST_HINT(window_hints mask, window_hints hint) {
return (*mask & (1 << (*hint))) != 0;
}
inline bool TEST_HINT(uint16_t mask, window_hints hint) {
return (mask & (1 << (*hint))) != 0;
}
#endif
#ifdef BUILD_X11
extern Display *display;
#endif /* BUILD_X11 */
@@ -70,20 +202,6 @@ void xdbe_swap_buffers(void);
void xpmdb_swap_buffers(void);
#endif /* BUILD_XDBE */
/* alignments */
enum alignment {
TOP_LEFT,
TOP_RIGHT,
TOP_MIDDLE,
BOTTOM_LEFT,
BOTTOM_RIGHT,
BOTTOM_MIDDLE,
MIDDLE_LEFT,
MIDDLE_MIDDLE,
MIDDLE_RIGHT,
NONE
};
extern conky::simple_config_setting<alignment> text_alignment;
namespace priv {

View File

@@ -27,13 +27,13 @@
#include "conky.h"
#include "logging.h"
#ifdef BUILD_GUI
#include "gui.h"
#ifdef BUILD_X11
#include "x11.h"
#endif /* BUILD_X11 */
#ifdef BUILD_GUI
#include "gui.h"
#ifdef BUILD_MOUSE_EVENTS
#include "mouse-events.h"
#endif /* BUILD_MOUSE_EVENTS */

View File

@@ -32,12 +32,9 @@ extern "C" {
#include <config.h>
#ifdef BUILD_X11
#include "x11.h"
#ifdef BUILD_MOUSE_EVENTS
#include "mouse-events.h"
#endif /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_X11 */
#define LUAPREFIX "conky_"

View File

@@ -41,6 +41,7 @@ extern "C" {
namespace conky {
#ifdef BUILD_MOUSE_EVENTS
/* Lua helper functions */
void push_table_value(lua_State *L, std::string key, std::string value) {
lua_pushstring(L, key.c_str());
@@ -105,22 +106,22 @@ inline std::size_t current_time_ms() {
void push_table_value(lua_State *L, std::string key, mouse_event_t type) {
lua_pushstring(L, key.c_str());
switch (type) {
case MOUSE_PRESS:
case mouse_event_t::PRESS:
lua_pushstring(L, "button_down");
break;
case MOUSE_RELEASE:
case mouse_event_t::RELEASE:
lua_pushstring(L, "button_up");
break;
case MOUSE_SCROLL:
case mouse_event_t::SCROLL:
lua_pushstring(L, "mouse_scroll");
break;
case MOUSE_MOVE:
case mouse_event_t::MOVE:
lua_pushstring(L, "mouse_move");
break;
case AREA_ENTER:
case mouse_event_t::AREA_ENTER:
lua_pushstring(L, "mouse_enter");
break;
case AREA_LEAVE:
case mouse_event_t::AREA_LEAVE:
lua_pushstring(L, "mouse_leave");
break;
default:
@@ -134,16 +135,16 @@ void push_table_value(lua_State *L, std::string key,
scroll_direction_t direction) {
lua_pushstring(L, key.c_str());
switch (direction) {
case SCROLL_DOWN:
case scroll_direction_t::DOWN:
lua_pushstring(L, "down");
break;
case SCROLL_UP:
case scroll_direction_t::UP:
lua_pushstring(L, "up");
break;
case SCROLL_LEFT:
case scroll_direction_t::LEFT:
lua_pushstring(L, "left");
break;
case SCROLL_RIGHT:
case scroll_direction_t::RIGHT:
lua_pushstring(L, "right");
break;
default:
@@ -156,19 +157,19 @@ void push_table_value(lua_State *L, std::string key,
void push_table_value(lua_State *L, std::string key, mouse_button_t button) {
lua_pushstring(L, key.c_str());
switch (button) {
case BUTTON_LEFT:
case mouse_button_t::LEFT:
lua_pushstring(L, "left");
break;
case BUTTON_RIGHT:
case mouse_button_t::RIGHT:
lua_pushstring(L, "right");
break;
case BUTTON_MIDDLE:
case mouse_button_t::MIDDLE:
lua_pushstring(L, "middle");
break;
case BUTTON_BACK:
case mouse_button_t::BACK:
lua_pushstring(L, "back");
break;
case BUTTON_FORWARD:
case mouse_button_t::FORWARD:
lua_pushstring(L, "forward");
break;
default:
@@ -213,6 +214,7 @@ void mouse_button_event::push_lua_data(lua_State *L) const {
push_table_value(L, "button", this->button);
push_mods(L, this->mods);
}
#endif /* BUILD_MOUSE_EVENTS */
#ifdef BUILD_XINPUT
/// Last global device id.
@@ -271,10 +273,10 @@ void handle_xi_device_change(const XIHierarchyEvent *event) {
/// some device (unlikely).
size_t fixed_valuator_index(Display *display, XIDeviceInfo *device,
valuator_t valuator) {
const std::array<const char *, valuator_t::VALUATOR_COUNT> atom_names = {
const std::array<const char *, VALUATOR_COUNT> atom_names = {
"ConkyValuatorMoveX", "ConkyValuatorMoveY", "ConkyValuatorScrollX",
"ConkyValuatorScrollY"};
Atom override_atom = XInternAtom(display, atom_names[valuator], False);
Atom override_atom = XInternAtom(display, atom_names[*valuator], False);
unsigned char *value;
Atom type_return;
int format_return;
@@ -290,7 +292,7 @@ size_t fixed_valuator_index(Display *display, XIDeviceInfo *device,
NORM_ERR(
"invalid '%s' option value, expected a single integer; value will "
"be ignored",
atom_names[valuator]);
atom_names[*valuator]);
XFree(value);
break;
}
@@ -299,7 +301,7 @@ size_t fixed_valuator_index(Display *display, XIDeviceInfo *device,
return static_cast<size_t>(result);
}
} while (true);
return valuator;
return *valuator;
}
/// Allows override of valuator value type in `xorg.conf` in case they're wrong
@@ -312,7 +314,7 @@ bool fixed_valuator_relative(Display *display, XIDeviceInfo *device,
"ConkyValuatorScrollMode",
};
Atom override_atom = XInternAtom(display, atom_names[valuator >> 1], False);
Atom override_atom = XInternAtom(display, atom_names[*valuator >> 1], False);
unsigned char *value_return;
Atom type_return;
int format_return;
@@ -329,7 +331,7 @@ bool fixed_valuator_relative(Display *display, XIDeviceInfo *device,
NORM_ERR(
"invalid '%s' option value, expected an atom (string); value will "
"be ignored",
atom_names[valuator >> 1]);
atom_names[*valuator >> 1]);
XFree(value_return);
break;
}
@@ -348,7 +350,7 @@ bool fixed_valuator_relative(Display *display, XIDeviceInfo *device,
"unknown '%s' option value: '%s', expected 'absolute' or "
"'relative'; "
"value will be ignored",
atom_names[valuator >> 1]);
atom_names[*valuator >> 1]);
XFree(value);
break;
}
@@ -372,8 +374,8 @@ void device_info::init_xi_device(
}
if (device == nullptr) return;
std::array<size_t, valuator_t::VALUATOR_COUNT> valuator_indices;
for (size_t i = 0; i < valuator_t::VALUATOR_COUNT; i++) {
std::array<size_t, VALUATOR_COUNT> valuator_indices;
for (size_t i = 0; i < VALUATOR_COUNT; i++) {
valuator_indices[i] =
fixed_valuator_index(display, device, static_cast<valuator_t>(i));
}
@@ -384,14 +386,14 @@ void device_info::init_xi_device(
XIValuatorClassInfo *class_info = (XIValuatorClassInfo *)device->classes[i];
// check if one of used (mapped) valuators
valuator_t valuator = valuator_t::VALUATOR_COUNT;
for (size_t i = 0; i < valuator_t::VALUATOR_COUNT; i++) {
valuator_t valuator = valuator_t::UNKNOWN;
for (size_t i = 0; i < VALUATOR_COUNT; i++) {
if (valuator_indices[i] == class_info->number) {
valuator = static_cast<valuator_t>(i);
break;
}
}
if (valuator == valuator_t::VALUATOR_COUNT) { continue; }
if (valuator == valuator_t::UNKNOWN) { continue; }
auto info = conky_valuator_info{
.index = static_cast<size_t>(class_info->number),
@@ -402,7 +404,7 @@ void device_info::init_xi_device(
fixed_valuator_relative(display, device, valuator, class_info),
};
this->valuators[valuator] = info;
this->valuators[*valuator] = info;
}
if (std::holds_alternative<xi_device_id>(source)) {
@@ -410,7 +412,7 @@ void device_info::init_xi_device(
}
}
conky_valuator_info &device_info::valuator(valuator_t valuator) {
return this->valuators[valuator];
return this->valuators[*valuator];
}
xi_event_data *xi_event_data::read_cookie(Display *display, const void *data) {
@@ -460,7 +462,7 @@ xi_event_data *xi_event_data::read_cookie(Display *display, const void *data) {
.valuators_relative = {0.0, 0.0, 0.0, 0.0},
};
for (size_t v = 0; v < valuator_t::VALUATOR_COUNT; v++) {
for (size_t v = 0; v < VALUATOR_COUNT; v++) {
valuator_t valuator = static_cast<valuator_t>(v);
auto &valuator_info = device->valuator(valuator);
@@ -497,7 +499,7 @@ std::optional<double> xi_event_data::valuator_value(valuator_t valuator) const {
std::optional<double> xi_event_data::valuator_relative_value(
valuator_t valuator) const {
return this->valuators_relative.at(valuator);
return this->valuators_relative.at(*valuator);
}
std::vector<std::tuple<int, XEvent *>> xi_event_data::generate_events(

View File

@@ -77,42 +77,50 @@ extern "C" {
namespace conky {
enum mouse_event_t {
MOUSE_PRESS = 0,
MOUSE_RELEASE = 1,
MOUSE_SCROLL = 2,
MOUSE_MOVE = 3,
#ifdef BUILD_MOUSE_EVENTS
enum class mouse_event_t : uint32_t {
PRESS = 0,
RELEASE = 1,
SCROLL = 2,
MOVE = 3,
AREA_ENTER = 4,
AREA_LEAVE = 5,
MOUSE_EVENT_COUNT = 6,
};
const size_t MOUSE_EVENT_COUNT =
static_cast<size_t>(mouse_event_t::AREA_LEAVE) + 1;
constexpr uint32_t operator*(mouse_event_t index) {
return static_cast<uint32_t>(index);
}
enum mouse_button_t : std::uint32_t {
BUTTON_LEFT = BTN_LEFT,
BUTTON_RIGHT = BTN_RIGHT,
BUTTON_MIDDLE = BTN_MIDDLE,
BUTTON_BACK = BTN_BACK,
BUTTON_FORWARD = BTN_FORWARD,
enum class mouse_button_t : uint32_t {
LEFT = BTN_LEFT,
RIGHT = BTN_RIGHT,
MIDDLE = BTN_MIDDLE,
BACK = BTN_BACK,
FORWARD = BTN_FORWARD,
};
constexpr uint32_t operator*(mouse_button_t index) {
return static_cast<uint32_t>(index);
}
#ifdef BUILD_X11
inline mouse_button_t x11_mouse_button_code(unsigned int x11_mouse_button) {
mouse_button_t button;
switch (x11_mouse_button) {
case Button1:
button = BUTTON_LEFT;
button = mouse_button_t::LEFT;
break;
case Button2:
button = BUTTON_MIDDLE;
button = mouse_button_t::MIDDLE;
break;
case Button3:
button = BUTTON_RIGHT;
button = mouse_button_t::RIGHT;
break;
case 8:
button = BUTTON_BACK;
button = mouse_button_t::BACK;
break;
case 9:
button = BUTTON_FORWARD;
button = mouse_button_t::FORWARD;
break;
default:
DBGP("X11 button %d is not mapped", x11_mouse_button);
@@ -145,26 +153,29 @@ struct mouse_positioned_event : public mouse_event {
};
typedef std::bitset<6> modifier_state_t;
enum modifier_key : std::uint32_t {
MOD_SHIFT = 0,
MOD_CONTROL = 1,
MOD_ALT = 2,
enum class modifier_key : uint32_t {
SHIFT = 0,
CONTROL = 1,
ALT = 2,
// Windows/MacOS key on most keyboards
MOD_SUPER = 3,
MOD_CAPS_LOCK = 4,
MOD_NUM_LOCK = 5,
SUPER = 3,
CAPS_LOCK = 4,
NUM_LOCK = 5,
};
constexpr uint32_t operator*(modifier_key index) {
return static_cast<uint32_t>(index);
}
std::string modifier_name(modifier_key key);
#ifdef BUILD_X11
inline modifier_state_t x11_modifier_state(unsigned int mods) {
modifier_state_t result;
result[MOD_SHIFT] = mods & ShiftMask;
result[MOD_CONTROL] = mods & ControlMask;
result[MOD_ALT] = mods & Mod1Mask;
result[MOD_SUPER] = mods & Mod4Mask;
result[MOD_CAPS_LOCK] = mods & LockMask;
result[MOD_NUM_LOCK] = mods & Mod2Mask;
result[*modifier_key::SHIFT] = mods & ShiftMask;
result[*modifier_key::CONTROL] = mods & ControlMask;
result[*modifier_key::ALT] = mods & Mod1Mask;
result[*modifier_key::SUPER] = mods & Mod4Mask;
result[*modifier_key::CAPS_LOCK] = mods & LockMask;
result[*modifier_key::NUM_LOCK] = mods & Mod2Mask;
return result;
}
#endif /* BUILD_X11 */
@@ -174,35 +185,38 @@ struct mouse_move_event : public mouse_positioned_event {
mouse_move_event(std::size_t x, std::size_t y, std::size_t x_abs,
std::size_t y_abs, modifier_state_t mods = 0)
: mouse_positioned_event{mouse_event_t::MOUSE_MOVE, x, y, x_abs, y_abs},
: mouse_positioned_event{mouse_event_t::MOVE, x, y, x_abs, y_abs},
mods(mods){};
void push_lua_data(lua_State *L) const;
};
enum scroll_direction_t : std::uint8_t {
SCROLL_UNKNOWN = 0,
SCROLL_UP,
SCROLL_DOWN,
SCROLL_LEFT,
SCROLL_RIGHT,
enum class scroll_direction_t : uint8_t {
UNKNOWN = 0,
UP,
DOWN,
LEFT,
RIGHT,
};
constexpr uint8_t operator*(scroll_direction_t index) {
return static_cast<uint8_t>(index);
}
#ifdef BUILD_X11
inline scroll_direction_t x11_scroll_direction(unsigned int x11_mouse_button) {
scroll_direction_t direction = SCROLL_UNKNOWN;
scroll_direction_t direction = scroll_direction_t::UNKNOWN;
switch (x11_mouse_button) {
case Button4:
direction = SCROLL_UP;
direction = scroll_direction_t::UP;
break;
case Button5:
direction = SCROLL_DOWN;
direction = scroll_direction_t::DOWN;
break;
case 6:
direction = SCROLL_LEFT;
direction = scroll_direction_t::LEFT;
break;
case 7:
direction = SCROLL_RIGHT;
direction = scroll_direction_t::RIGHT;
break;
}
return direction;
@@ -216,7 +230,7 @@ struct mouse_scroll_event : public mouse_positioned_event {
mouse_scroll_event(std::size_t x, std::size_t y, std::size_t x_abs,
std::size_t y_abs, scroll_direction_t direction,
modifier_state_t mods = 0)
: mouse_positioned_event{mouse_event_t::MOUSE_SCROLL, x, y, x_abs, y_abs},
: mouse_positioned_event{mouse_event_t::SCROLL, x, y, x_abs, y_abs},
direction(direction),
mods(mods){};
@@ -242,12 +256,17 @@ struct mouse_crossing_event : public mouse_positioned_event {
std::size_t x_abs, std::size_t y_abs)
: mouse_positioned_event{type, x, y, x_abs, y_abs} {};
};
#endif /* BUILD_MOUSE_EVENTS */
#ifdef BUILD_XINPUT
typedef int xi_device_id;
typedef int xi_event_type;
enum valuator_t : size_t { MOVE_X, MOVE_Y, SCROLL_X, SCROLL_Y, VALUATOR_COUNT };
enum class valuator_t : size_t { MOVE_X, MOVE_Y, SCROLL_X, SCROLL_Y, UNKNOWN };
const size_t VALUATOR_COUNT = static_cast<size_t>(valuator_t::UNKNOWN);
constexpr uint8_t operator*(valuator_t index) {
return static_cast<uint8_t>(index);
}
struct conky_valuator_info {
size_t index;
@@ -261,7 +280,7 @@ struct device_info {
/// @brief Device name.
xi_device_id id;
std::string name;
std::array<conky_valuator_info, valuator_t::VALUATOR_COUNT> valuators{};
std::array<conky_valuator_info, VALUATOR_COUNT> valuators{};
static device_info *from_xi_id(xi_device_id id, Display *display = nullptr);
@@ -305,7 +324,7 @@ struct xi_event_data {
// Extra data
/// Precomputed relative values
std::array<double, valuator_t::VALUATOR_COUNT> valuators_relative;
std::array<double, VALUATOR_COUNT> valuators_relative;
static xi_event_data *read_cookie(Display *display, const void *data);

View File

@@ -99,6 +99,8 @@
#include "conky.h"
#include "logging.h"
#include "temphelper.h"
// Current implementation uses X11 specific system utils
#include "x11.h"
#include <memory>
@@ -422,7 +424,7 @@ nvidia_display_setting nvidia_display;
// Evaluate module parameters and prepare query
int set_nvidia_query(struct text_object *obj, const char *arg,
unsigned int special_type) {
text_node_t special_type) {
nvidia_s *nvs;
int aid;
int ilen;
@@ -451,15 +453,15 @@ int set_nvidia_query(struct text_object *obj, const char *arg,
// Extract arguments for nvidiabar, etc, and run set_nvidia_query
switch (special_type) {
case BAR:
case text_node_t::BAR:
arg = scan_bar(obj, arg, 100);
break;
case GRAPH: {
case text_node_t::GRAPH: {
auto [buf, skip] = scan_command(arg);
scan_graph(obj, arg + skip, 100);
arg = buf;
} break;
case GAUGE:
case text_node_t::GAUGE:
arg = scan_gauge(obj, arg, 100);
break;
default:
@@ -483,7 +485,7 @@ int set_nvidia_query(struct text_object *obj, const char *arg,
// Save pointers to the arg and command strings for debugging and printing
nvs->arg = translate_module_argument[aid];
nvs->command = translate_nvidia_special_type[special_type];
nvs->command = translate_nvidia_special_type[*special_type];
// Evaluate parameter
switch (aid) {

View File

@@ -30,7 +30,9 @@
#ifndef NVIDIA_CONKY_H
#define NVIDIA_CONKY_H
int set_nvidia_query(struct text_object *, const char *, unsigned int);
#include "specials.h"
int set_nvidia_query(struct text_object *, const char *, text_node_t);
void print_nvidia_value(struct text_object *, char *, unsigned int);
double get_nvidia_barval(struct text_object *);
void free_nvidia(struct text_object *);

View File

@@ -323,7 +323,8 @@ void print_scroll(struct text_object *obj, char *p, unsigned int p_max_size) {
#ifdef BUILD_GUI
// reset color when scroll is finished
if (display_output() && display_output()->graphical()) {
new_special(p + strlen(p), FG)->arg = sd->resetcolor.to_argb32();
new_special(p + strlen(p), text_node_t::FG)->arg =
sd->resetcolor.to_argb32();
}
#endif
}

View File

@@ -46,7 +46,7 @@
#include "conky.h"
#include "display-output.hh"
struct special_t *specials = nullptr;
struct special_node *specials = nullptr;
int special_count;
int graph_count = 0;
@@ -354,8 +354,8 @@ bool scan_graph(struct text_object *obj, const char *argstr, double defscale) {
* Printing various special text objects
*/
struct special_t *new_special_t_node() {
auto *newnode = new special_t;
struct special_node *new_special_t_node() {
auto *newnode = new special_node;
memset(newnode, 0, sizeof *newnode);
return newnode;
@@ -369,8 +369,8 @@ struct special_t *new_special_t_node() {
* @param[in] t special type enum, e.g. alignc, alignr, fg, bg, ...
* @return pointer to the newly inserted special of type t
**/
struct special_t *new_special(char *buf, enum special_types t) {
special_t *current;
struct special_node *new_special(char *buf, text_node_t t) {
special_node *current;
buf[0] = SPECIAL_CHAR;
buf[1] = '\0';
@@ -397,14 +397,14 @@ void new_gauge_in_shell(struct text_object *obj, char *p,
#ifdef BUILD_GUI
void new_gauge_in_gui(struct text_object *obj, char *buf, double usage) {
struct special_t *s = nullptr;
struct special_node *s = nullptr;
auto *g = static_cast<struct gauge *>(obj->special_data);
if (display_output() == nullptr || !display_output()->graphical()) { return; }
if (g == nullptr) { return; }
s = new_special(buf, GAUGE);
s = new_special(buf, text_node_t::GAUGE);
s->arg = usage;
s->width = dpi_scale(g->width);
@@ -439,14 +439,14 @@ void new_gauge(struct text_object *obj, char *p, unsigned int p_max_size,
#ifdef BUILD_GUI
void new_font(struct text_object *obj, char *p, unsigned int p_max_size) {
struct special_t *s;
struct special_node *s;
unsigned int tmp = selected_font;
if (display_output() == nullptr || !display_output()->graphical()) { return; }
if (p_max_size == 0) { return; }
s = new_special(p, FONT);
s = new_special(p, text_node_t::FONT);
if (obj->data.s != nullptr) {
if (s->font_added >= static_cast<int>(fonts.size()) ||
@@ -463,7 +463,7 @@ void new_font(struct text_object *obj, char *p, unsigned int p_max_size) {
/**
* Adds value f to graph possibly truncating and scaling the graph
**/
static void graph_append(struct special_t *graph, double f, char showaslog) {
static void graph_append(struct special_node *graph, double f, char showaslog) {
int i;
/* do nothing if we don't even have a graph yet */
@@ -494,7 +494,7 @@ static void graph_append(struct special_t *graph, double f, char showaslog) {
}
}
void new_graph_in_shell(struct special_t *s, char *buf, int buf_max_size) {
void new_graph_in_shell(struct special_node *s, char *buf, int buf_max_size) {
// Split config string on comma to avoid the hassle of dealing with the
// idiosyncrasies of multi-byte unicode on different platforms.
// TODO(brenden): Parse config string once and cache result.
@@ -537,7 +537,7 @@ double *retrieve_graph(int graph_id, int graph_width) {
}
}
void store_graph(int graph_id, struct special_t *s) {
void store_graph(int graph_id, struct special_node *s) {
if (s->graph == nullptr) {
graphs[graph_id] = nullptr;
} else {
@@ -556,12 +556,12 @@ void store_graph(int graph_id, struct special_t *s) {
**/
void new_graph(struct text_object *obj, char *buf, int buf_max_size,
double val) {
struct special_t *s = nullptr;
struct special_node *s = nullptr;
auto *g = static_cast<struct graph *>(obj->special_data);
if ((g == nullptr) || (buf_max_size == 0)) { return; }
s = new_special(buf, GRAPH);
s = new_special(buf, text_node_t::GRAPH);
/* set graph (special) width to width in obj */
s->width = dpi_scale(g->width);
@@ -628,7 +628,7 @@ void new_hr(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, HORIZONTAL_LINE)->height = dpi_scale(obj->data.l);
new_special(p, text_node_t::HORIZONTAL_LINE)->height = dpi_scale(obj->data.l);
}
void scan_stippled_hr(struct text_object *obj, const char *arg) {
@@ -651,14 +651,14 @@ void scan_stippled_hr(struct text_object *obj, const char *arg) {
void new_stippled_hr(struct text_object *obj, char *p,
unsigned int p_max_size) {
struct special_t *s = nullptr;
struct special_node *s = nullptr;
auto *sh = static_cast<struct stippled_hr *>(obj->special_data);
if (display_output() == nullptr || !display_output()->graphical()) { return; }
if ((sh == nullptr) || (p_max_size == 0)) { return; }
s = new_special(p, STIPPLED_HR);
s = new_special(p, text_node_t::STIPPLED_HR);
s->height = dpi_scale(sh->height);
s->arg = dpi_scale(sh->arg);
@@ -674,7 +674,7 @@ void new_fg(struct text_object *obj, char *p, unsigned int p_max_size) {
|| out_to_ncurses.get(*state)
#endif /* BUILD_NCURSES */
) {
new_special(p, FG)->arg = obj->data.l;
new_special(p, text_node_t::FG)->arg = obj->data.l;
}
UNUSED(obj);
UNUSED(p);
@@ -687,7 +687,7 @@ void new_bg(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, BG)->arg = obj->data.l;
new_special(p, text_node_t::BG)->arg = obj->data.l;
}
#endif /* BUILD_GUI */
@@ -716,14 +716,14 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer,
#ifdef BUILD_GUI
static void new_bar_in_gui(struct text_object *obj, char *buf, double usage) {
struct special_t *s = nullptr;
struct special_node *s = nullptr;
auto *b = static_cast<struct bar *>(obj->special_data);
if (display_output() == nullptr || !display_output()->graphical()) { return; }
if (b == nullptr) { return; }
s = new_special(buf, BAR);
s = new_special(buf, text_node_t::BAR);
s->arg = usage;
s->width = dpi_scale(b->width);
@@ -759,39 +759,39 @@ void new_bar(struct text_object *obj, char *p, unsigned int p_max_size,
void new_outline(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, OUTLINE)->arg = obj->data.l;
new_special(p, text_node_t::OUTLINE)->arg = obj->data.l;
}
void new_offset(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, OFFSET)->arg = dpi_scale(obj->data.l);
new_special(p, text_node_t::OFFSET)->arg = dpi_scale(obj->data.l);
}
void new_voffset(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, VOFFSET)->arg = dpi_scale(obj->data.l);
new_special(p, text_node_t::VOFFSET)->arg = dpi_scale(obj->data.l);
}
void new_save_coordinates(struct text_object *obj, char *p,
unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, SAVE_COORDINATES)->arg = obj->data.l;
new_special(p, text_node_t::SAVE_COORDINATES)->arg = obj->data.l;
}
void new_alignr(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, ALIGNR)->arg = dpi_scale(obj->data.l);
new_special(p, text_node_t::ALIGNR)->arg = dpi_scale(obj->data.l);
}
// A positive offset pushes the text further left
void new_alignc(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, ALIGNC)->arg = dpi_scale(obj->data.l);
new_special(p, text_node_t::ALIGNC)->arg = dpi_scale(obj->data.l);
}
void new_goto(struct text_object *obj, char *p, unsigned int p_max_size) {
if (p_max_size == 0) { return; }
new_special(p, GOTO)->arg = dpi_scale(obj->data.l);
new_special(p, text_node_t::GOTO)->arg = dpi_scale(obj->data.l);
}
void scan_tab(struct text_object *obj, const char *arg) {
@@ -813,12 +813,12 @@ void scan_tab(struct text_object *obj, const char *arg) {
}
void new_tab(struct text_object *obj, char *p, unsigned int p_max_size) {
struct special_t *s = nullptr;
struct special_node *s = nullptr;
auto *t = static_cast<struct tab *>(obj->special_data);
if ((t == nullptr) || (p_max_size == 0)) { return; }
s = new_special(p, TAB);
s = new_special(p, text_node_t::TAB);
s->width = dpi_scale(t->width);
s->arg = dpi_scale(t->arg);
}

View File

@@ -40,7 +40,7 @@
#define LOGGRAPH "-l"
#define TEMPGRAD "-t"
enum special_types {
enum class text_node_t : uint32_t {
NONSPECIAL = 0,
HORIZONTAL_LINE = 1,
STIPPLED_HR,
@@ -59,9 +59,12 @@ enum special_types {
GOTO,
TAB
};
constexpr uint32_t operator*(text_node_t index) {
return static_cast<uint32_t>(index);
}
struct special_t {
int type;
struct special_node {
text_node_t type;
short height;
short width;
double arg;
@@ -77,11 +80,11 @@ struct special_t {
Colour last_colour;
short font_added;
char tempgrad;
struct special_t *next;
struct special_node *next;
};
/* direct access to the registered specials (FIXME: bad encapsulation) */
extern struct special_t *specials;
extern struct special_node *specials;
extern int special_count;
/* forward declare to avoid mutual inclusion between specials.h and
@@ -119,6 +122,6 @@ void new_tab(struct text_object *, char *, unsigned int);
void clear_stored_graphs();
struct special_t *new_special(char *buf, enum special_types t);
struct special_node *new_special(char *buf, enum text_node_t t);
#endif /* _SPECIALS_H */

View File

@@ -29,11 +29,19 @@
#ifndef _TEXT_OBJECT_H
#define _TEXT_OBJECT_H
#include <stdint.h> /* uint8_t */
#include "config.h" /* for the defines */
#include "config.h"
#include "exec.h"
#include "specials.h" /* enum special_types */
#include <cstdint> /* uint8_t */
enum class draw_mode_t : uint32_t {
BG = static_cast<uint32_t>(text_node_t::BG),
FG = static_cast<uint32_t>(text_node_t::FG),
OUTLINE = static_cast<uint32_t>(text_node_t::OUTLINE),
};
/* text object callbacks */
struct obj_cb {
/* text object: print obj's output to p */

View File

@@ -27,9 +27,15 @@
*
*/
#if defined(BUILD_WAYLAND) && !defined(CONKY_WL_H)
#ifndef CONKY_WL_H
#define CONKY_WL_H
#include "config.h"
#ifndef BUILD_WAYLAND
#error wl.h included when BUILD_WAYLAND is disabled
#endif
#include <wayland-client.h>
#include "setting.hh"

View File

@@ -1566,15 +1566,12 @@ static const BuiltinColor BuiltinColors[] = {
#define NUM_BUILTIN_COLORS (sizeof(BuiltinColors) / sizeof(BuiltinColors[0]))
int OsLookupColor(int screen, const char *name, unsigned int len,
unsigned short *pred, unsigned short *pgreen,
unsigned short *pblue) {
int OsLookupColor(const char *name, unsigned int len, unsigned short *pred,
unsigned short *pgreen, unsigned short *pblue) {
const BuiltinColor *c;
int low, mid, high;
int r;
(void)screen;
low = 0;
high = NUM_BUILTIN_COLORS - 1;
while (high >= low) {

View File

@@ -1,4 +1,3 @@
/* from xorg-server's oscolor.c */
int OsLookupColor(int screen, const char *name, unsigned int len,
unsigned short *pred, unsigned short *pgreen,
unsigned short *pblue);
int OsLookupColor(const char *name, unsigned int len, unsigned short *pred,
unsigned short *pgreen, unsigned short *pblue);

126
src/x11-settings.cc Normal file
View File

@@ -0,0 +1,126 @@
#include "x11-settings.h"
#include "x11.h"
#include "conky-imlib2.h"
#include <X11/Xlib.h>
conky::simple_config_setting<std::string> display_name("display", std::string(),
false);
namespace priv {
void out_to_x_setting::lua_setter(lua::state &l, bool init) {
lua::stack_sentry s(l, -2);
Base::lua_setter(l, init);
if (init && do_convert(l, -1).first) { init_x11(); }
++s;
}
void out_to_x_setting::cleanup(lua::state &l) {
lua::stack_sentry s(l, -1);
if (do_convert(l, -1).first) { deinit_x11(); }
l.pop();
}
#ifdef BUILD_XDBE
bool use_xdbe_setting::set_up(lua::state &l) {
// double_buffer makes no sense when not drawing to X
if (!out_to_x.get(l) || !display || !window.window) { return false; }
int major, minor;
if (XdbeQueryExtension(display, &major, &minor) == 0) {
NORM_ERR("No compatible double buffer extension found");
return false;
}
window.back_buffer =
XdbeAllocateBackBufferName(display, window.window, XdbeBackground);
if (window.back_buffer != None) {
window.drawable = window.back_buffer;
} else {
NORM_ERR("Failed to allocate back buffer");
return false;
}
XFlush(display);
return true;
}
void use_xdbe_setting::lua_setter(lua::state &l, bool init) {
lua::stack_sentry s(l, -2);
Base::lua_setter(l, init);
if (init && do_convert(l, -1).first) {
if (!set_up(l)) {
l.pop();
l.pushboolean(false);
}
NORM_ERR("drawing to %s buffer",
do_convert(l, -1).first ? "double" : "single");
}
++s;
}
#else
bool use_xpmdb_setting::set_up(lua::state &l) {
// double_buffer makes no sense when not drawing to X
if (!out_to_x.get(l)) return false;
window.back_buffer =
XCreatePixmap(display, window.window, window.width + 1, window.height + 1,
DefaultDepth(display, screen));
if (window.back_buffer != None) {
window.drawable = window.back_buffer;
} else {
NORM_ERR("Failed to allocate back buffer");
return false;
}
XFlush(display);
return true;
}
void use_xpmdb_setting::lua_setter(lua::state &l, bool init) {
lua::stack_sentry s(l, -2);
Base::lua_setter(l, init);
if (init && do_convert(l, -1).first) {
if (!set_up(l)) {
l.pop();
l.pushboolean(false);
}
NORM_ERR("drawing to %s buffer",
do_convert(l, -1).first ? "double" : "single");
}
++s;
}
#endif
} // namespace priv
conky::simple_config_setting<int> head_index("xinerama_head", 0, true);
priv::out_to_x_setting out_to_x;
#ifdef BUILD_XFT
conky::simple_config_setting<bool> use_xft("use_xft", false, false);
#endif
conky::simple_config_setting<bool> forced_redraw("forced_redraw", false, false);
#ifdef BUILD_XDBE
priv::use_xdbe_setting use_xdbe;
#else
priv::use_xpmdb_setting use_xpmdb;
#endif

60
src/x11-settings.h Normal file
View File

@@ -0,0 +1,60 @@
#ifndef CONKY_X11_SETTINGS_H
#define CONKY_X11_SETTINGS_H
#include "setting.hh"
extern conky::simple_config_setting<std::string> display_name;
namespace priv {
class out_to_x_setting : public conky::simple_config_setting<bool> {
typedef conky::simple_config_setting<bool> Base;
protected:
virtual void lua_setter(lua::state &l, bool init);
virtual void cleanup(lua::state &l);
public:
out_to_x_setting() : Base("out_to_x", true, false) {}
};
#ifdef BUILD_XDBE
class use_xdbe_setting : public conky::simple_config_setting<bool> {
typedef conky::simple_config_setting<bool> Base;
bool set_up(lua::state &l);
protected:
virtual void lua_setter(lua::state &l, bool init);
public:
use_xdbe_setting() : Base("double_buffer", false, false) {}
};
#else
class use_xpmdb_setting : public conky::simple_config_setting<bool> {
typedef conky::simple_config_setting<bool> Base;
bool set_up(lua::state &l);
protected:
virtual void lua_setter(lua::state &l, bool init);
public:
use_xpmdb_setting() : Base("double_buffer", false, false) {}
};
#endif
} /* namespace priv */
extern priv::out_to_x_setting out_to_x;
#ifdef BUILD_XFT
extern conky::simple_config_setting<bool> use_xft;
#endif
#ifdef BUILD_XDBE
extern priv::use_xdbe_setting use_xdbe;
#else
extern priv::use_xpmdb_setting use_xpmdb;
#endif
#endif /* CONKY_X11_SETTINGS_H */

View File

@@ -43,13 +43,19 @@
#include <vector>
#endif
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <string>
// #ifndef OWN_WINDOW
// #include <iostream>
// #endif
extern "C" {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
@@ -64,9 +70,6 @@ extern "C" {
#ifdef BUILD_IMLIB2
#include "conky-imlib2.h"
#endif /* BUILD_IMLIB2 */
#ifndef OWN_WINDOW
#include <iostream>
#endif
#ifdef BUILD_XFT
#include <X11/Xft/Xft.h>
#endif
@@ -100,144 +103,12 @@ xcb_errors_context_t *xcb_errors_ctx;
/* Window stuff */
struct conky_x11_window window;
#ifdef BUILD_ARGB
bool have_argb_visual;
#endif /* BUILD_ARGB */
conky::simple_config_setting<std::string> display_name("display", std::string(),
false);
bool have_argb_visual = false;
/* local prototypes */
static void update_workarea();
static Window find_desktop_window(Window *p_root, Window *p_desktop);
static Window find_subwindow(Window win, int w, int h);
static void init_x11();
/********************* <SETTINGS> ************************/
namespace priv {
void out_to_x_setting::lua_setter(lua::state &l, bool init) {
lua::stack_sentry s(l, -2);
Base::lua_setter(l, init);
if (init && do_convert(l, -1).first) { init_x11(); }
++s;
}
void out_to_x_setting::cleanup(lua::state &l) {
lua::stack_sentry s(l, -1);
if (do_convert(l, -1).first) { deinit_x11(); }
l.pop();
}
#ifdef BUILD_XDBE
bool use_xdbe_setting::set_up(lua::state &l) {
// double_buffer makes no sense when not drawing to X
if (!out_to_x.get(l) || !display || !window.window) { return false; }
int major, minor;
if (XdbeQueryExtension(display, &major, &minor) == 0) {
NORM_ERR("No compatible double buffer extension found");
return false;
}
window.back_buffer =
XdbeAllocateBackBufferName(display, window.window, XdbeBackground);
if (window.back_buffer != None) {
window.drawable = window.back_buffer;
} else {
NORM_ERR("Failed to allocate back buffer");
return false;
}
XFlush(display);
return true;
}
void use_xdbe_setting::lua_setter(lua::state &l, bool init) {
lua::stack_sentry s(l, -2);
Base::lua_setter(l, init);
if (init && do_convert(l, -1).first) {
if (!set_up(l)) {
l.pop();
l.pushboolean(false);
}
NORM_ERR("drawing to %s buffer",
do_convert(l, -1).first ? "double" : "single");
}
++s;
}
#else
bool use_xpmdb_setting::set_up(lua::state &l) {
// double_buffer makes no sense when not drawing to X
if (!out_to_x.get(l)) return false;
window.back_buffer =
XCreatePixmap(display, window.window, window.width + 1, window.height + 1,
DefaultDepth(display, screen));
if (window.back_buffer != None) {
window.drawable = window.back_buffer;
} else {
NORM_ERR("Failed to allocate back buffer");
return false;
}
XFlush(display);
return true;
}
void use_xpmdb_setting::lua_setter(lua::state &l, bool init) {
lua::stack_sentry s(l, -2);
Base::lua_setter(l, init);
if (init && do_convert(l, -1).first) {
if (!set_up(l)) {
l.pop();
l.pushboolean(false);
}
NORM_ERR("drawing to %s buffer",
do_convert(l, -1).first ? "double" : "single");
}
++s;
}
#endif
} // namespace priv
conky::simple_config_setting<int> head_index("xinerama_head", 0, true);
priv::out_to_x_setting out_to_x;
#ifdef BUILD_XFT
conky::simple_config_setting<bool> use_xft("use_xft", false, false);
#endif
conky::simple_config_setting<bool> forced_redraw("forced_redraw", false, false);
#ifdef BUILD_XDBE
priv::use_xdbe_setting use_xdbe;
#else
priv::use_xpmdb_setting use_xpmdb;
#endif
#ifdef BUILD_IMLIB2
/*
* the only reason this is not in imlib2.cc is so that we can be sure it's
* setter executes after use_xdbe
*/
imlib_cache_size_setting imlib_cache_size;
#endif
/******************** </SETTINGS> ************************/
/* WARNING, this type not in Xlib spec */
static int x11_error_handler(Display *d, XErrorEvent *err) {
@@ -362,7 +233,7 @@ inline Window DefaultVRootWindow(Display *display) {
}
/* X11 initializer */
static void init_x11() {
void init_x11() {
DBGP("enter init_x11()");
if (display == nullptr) {
const std::string &dispstr = display_name.get(*state);
@@ -494,7 +365,8 @@ namespace {
void do_set_background(Window win, uint8_t alpha) {
Colour colour = background_colour.get(*state);
colour.alpha = alpha;
unsigned long xcolor = colour.to_x11_color(display, screen, true);
unsigned long xcolor =
colour.to_x11_color(display, screen, have_argb_visual, true);
XSetWindowBackground(display, win, xcolor);
}
} // namespace
@@ -624,7 +496,7 @@ void x11_init_window(lua::state &l, bool own) {
classHint.res_name = const_cast<char *>(class_name.c_str());
classHint.res_class = classHint.res_name;
if (own_window_type.get(l) == TYPE_OVERRIDE) {
if (own_window_type.get(l) == window_type::OVERRIDE) {
/* An override_redirect True window.
* No WM hints or button processing needed. */
XSetWindowAttributes attrs = {ParentRelative,
@@ -678,7 +550,7 @@ void x11_init_window(lua::state &l, bool own) {
StructureNotifyMask | ExposureMask | ButtonPressMask |
ButtonReleaseMask,
0L,
own_window_type.get(l) == TYPE_UTILITY ? True : False,
own_window_type.get(l) == window_type::UTILITY ? True : False,
0,
0};
@@ -694,7 +566,9 @@ void x11_init_window(lua::state &l, bool own) {
}
#endif /* BUILD_ARGB */
if (own_window_type.get(l) == TYPE_DOCK) { window.x = window.y = 0; }
if (own_window_type.get(l) == window_type::DOCK) {
window.x = window.y = 0;
}
/* Parent is root window so WM can take control */
window.window =
XCreateWindow(display, window.root, window.x, window.y, b, b, 0,
@@ -704,10 +578,10 @@ void x11_init_window(lua::state &l, bool own) {
wmHint.flags = InputHint | StateHint;
/* allow decorated windows to be given input focus by WM */
wmHint.input = TEST_HINT(hints, HINT_UNDECORATED) ? False : True;
wmHint.input = TEST_HINT(hints, window_hints::UNDECORATED) ? False : True;
#ifdef BUILD_XSHAPE
#ifdef BUILD_XFIXES
if (own_window_type.get(l) == TYPE_UTILITY) {
if (own_window_type.get(l) == window_type::UTILITY) {
XRectangle rect;
XserverRegion region = XFixesCreateRegion(display, &rect, 1);
XFixesSetWindowShapeRegion(display, window.window, ShapeInput, 0, 0,
@@ -723,18 +597,18 @@ void x11_init_window(lua::state &l, bool own) {
NORM_ERR("Input shapes are not supported");
} else {
if (own_window.get(*state) &&
(own_window_type.get(*state) != TYPE_NORMAL ||
((TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) !=
0))) {
(own_window_type.get(*state) != window_type::NORMAL ||
((TEST_HINT(own_window_hints.get(*state),
window_hints::UNDECORATED)) != 0))) {
XShapeCombineRectangles(display, window.window, ShapeInput, 0, 0,
nullptr, 0, ShapeSet, Unsorted);
}
}
}
#endif /* BUILD_XSHAPE */
if (own_window_type.get(l) == TYPE_DOCK ||
own_window_type.get(l) == TYPE_PANEL) {
wmHint.initial_state = WithdrawnState;
if (own_window_type.get(l) == window_type::DOCK ||
own_window_type.get(l) == window_type::PANEL) {
// wmHint.initial_state = WithdrawnState;
} else {
wmHint.initial_state = NormalState;
}
@@ -751,23 +625,23 @@ void x11_init_window(lua::state &l, bool own) {
Atom prop;
switch (own_window_type.get(l)) {
case TYPE_DESKTOP:
case window_type::DESKTOP:
prop = ATOM(_NET_WM_WINDOW_TYPE_DESKTOP);
NORM_ERR("window type - desktop");
break;
case TYPE_DOCK:
case window_type::DOCK:
prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
NORM_ERR("window type - dock");
break;
case TYPE_PANEL:
case window_type::PANEL:
prop = ATOM(_NET_WM_WINDOW_TYPE_DOCK);
NORM_ERR("window type - panel");
break;
case TYPE_UTILITY:
case window_type::UTILITY:
prop = ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
NORM_ERR("window type - utility");
break;
case TYPE_NORMAL:
case window_type::NORMAL:
default:
prop = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
NORM_ERR("window type - normal");
@@ -781,7 +655,7 @@ void x11_init_window(lua::state &l, bool own) {
/* Set desired hints */
/* Window decorations */
if (TEST_HINT(hints, HINT_UNDECORATED)) {
if (TEST_HINT(hints, window_hints::UNDECORATED)) {
DBGP("hint - undecorated");
xa = ATOM(_MOTIF_WM_HINTS);
if (xa != None) {
@@ -792,7 +666,7 @@ void x11_init_window(lua::state &l, bool own) {
}
/* Below other windows */
if (TEST_HINT(hints, HINT_BELOW)) {
if (TEST_HINT(hints, window_hints::BELOW)) {
DBGP("hint - below");
xa = ATOM(_WIN_LAYER);
if (xa != None) {
@@ -814,7 +688,7 @@ void x11_init_window(lua::state &l, bool own) {
}
/* Above other windows */
if (TEST_HINT(hints, HINT_ABOVE)) {
if (TEST_HINT(hints, window_hints::ABOVE)) {
DBGP("hint - above");
xa = ATOM(_WIN_LAYER);
if (xa != None) {
@@ -836,7 +710,7 @@ void x11_init_window(lua::state &l, bool own) {
}
/* Sticky */
if (TEST_HINT(hints, HINT_STICKY)) {
if (TEST_HINT(hints, window_hints::STICKY)) {
DBGP("hint - sticky");
xa = ATOM(_NET_WM_DESKTOP);
if (xa != None) {
@@ -858,7 +732,7 @@ void x11_init_window(lua::state &l, bool own) {
}
/* Skip taskbar */
if (TEST_HINT(hints, HINT_SKIP_TASKBAR)) {
if (TEST_HINT(hints, window_hints::SKIP_TASKBAR)) {
DBGP("hint - skip taskbar");
xa = ATOM(_NET_WM_STATE);
if (xa != None) {
@@ -871,7 +745,7 @@ void x11_init_window(lua::state &l, bool own) {
}
/* Skip pager */
if (TEST_HINT(hints, HINT_SKIP_PAGER)) {
if (TEST_HINT(hints, window_hints::SKIP_PAGER)) {
DBGP("hint - skip pager");
xa = ATOM(_NET_WM_STATE);
if (xa != None) {
@@ -909,9 +783,12 @@ void x11_init_window(lua::state &l, bool own) {
int64_t input_mask = ExposureMask | PropertyChangeMask;
#ifdef OWN_WINDOW
if (own_window.get(l)) {
input_mask |= StructureNotifyMask | ButtonPressMask | ButtonReleaseMask;
input_mask |= StructureNotifyMask;
#if !defined(BUILD_XINPUT)
input_mask |= ButtonPressMask | ButtonReleaseMask;
#endif
}
#ifdef BUILD_MOUSE_EVENTS
#if defined(BUILD_MOUSE_EVENTS) || defined(BUILD_XINPUT)
bool xinput_ok = false;
#ifdef BUILD_XINPUT
// not a loop; substitutes goto with break - if checks fail
@@ -934,7 +811,9 @@ void x11_init_window(lua::state &l, bool own) {
const std::size_t mask_size = (XI_LASTEVENT + 7) / 8;
unsigned char mask_bytes[mask_size] = {0}; /* must be zeroed! */
XISetMask(mask_bytes, XI_HierarchyChanged);
#ifdef BUILD_MOUSE_EVENTS
XISetMask(mask_bytes, XI_Motion);
#endif /* BUILD_MOUSE_EVENTS */
// Capture click events for "override" window type
if (!own) {
XISetMask(mask_bytes, XI_ButtonPress);
@@ -948,7 +827,9 @@ void x11_init_window(lua::state &l, bool own) {
XISelectEvents(display, window.root, ev_masks, 1);
if (own) {
#ifdef BUILD_MOUSE_EVENTS
XIClearMask(mask_bytes, XI_Motion);
#endif /* BUILD_MOUSE_EVENTS */
XISetMask(mask_bytes, XI_ButtonPress);
XISetMask(mask_bytes, XI_ButtonRelease);
@@ -974,10 +855,12 @@ void x11_init_window(lua::state &l, bool own) {
// Fallback to basic X11 enter/leave events if xinput fails to init.
// It's not recommended to add event masks to special windows in X; causes a
// crash (thus own_window_type != TYPE_DESKTOP)
if (!xinput_ok && own && own_window_type.get(l) != TYPE_DESKTOP) {
#ifdef BUILD_MOUSE_EVENTS
if (!xinput_ok && own && own_window_type.get(l) != window_type::DESKTOP) {
input_mask |= PointerMotionMask | EnterWindowMask | LeaveWindowMask;
}
#endif /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_MOUSE_EVENTS || BUILD_XINPUT */
#endif /* OWN_WINDOW */
window.event_mask = input_mask;
XSelectInput(display, window.window, input_mask);
@@ -1205,6 +1088,25 @@ void print_desktop_name(struct text_object *obj, char *p,
}
#ifdef OWN_WINDOW
enum class x11_strut : size_t {
LEFT,
RIGHT,
TOP,
BOTTOM,
LEFT_START_Y,
LEFT_END_Y,
RIGHT_START_Y,
RIGHT_END_Y,
TOP_START_X,
TOP_END_X,
BOTTOM_START_X,
BOTTOM_END_X,
};
const size_t STRUT_COUNT = static_cast<size_t>(x11_strut::BOTTOM_END_X) + 1;
constexpr size_t operator*(x11_strut index) {
return static_cast<size_t>(index);
}
/* reserve window manager space */
void set_struts(int sidenum) {
Atom strut;

View File

@@ -22,10 +22,14 @@
*
*/
#pragma once
#ifndef CONKY_X11_H
#define CONKY_X11_H
#include "config.h"
#include "setting.hh"
#ifndef BUILD_X11
#error x11.h included when BUILD_X11 is disabled
#endif
#include <X11/Xatom.h>
#pragma GCC diagnostic push
@@ -44,36 +48,16 @@
#include <functional>
#include <vector>
#ifdef BUILD_ARGB
// TODO: remove lua requirement from x11_init_window
#include "llua.h"
#include "gui.h"
/* true if use_argb_visual=true and argb visual was found*/
extern bool have_argb_visual;
#endif /* BUILD_ARGB */
#define ATOM(a) XInternAtom(display, #a, False)
#ifdef OWN_WINDOW
enum window_type {
TYPE_NORMAL = 0,
TYPE_DOCK,
TYPE_PANEL,
TYPE_DESKTOP,
TYPE_OVERRIDE,
TYPE_UTILITY
};
enum window_hints {
HINT_UNDECORATED = 0,
HINT_BELOW,
HINT_ABOVE,
HINT_STICKY,
HINT_SKIP_TASKBAR,
HINT_SKIP_PAGER
};
#define SET_HINT(mask, hint) (mask |= (1 << (hint)))
#define TEST_HINT(mask, hint) (mask & (1 << (hint)))
#endif
extern Display *display;
struct conky_x11_window {
@@ -99,10 +83,10 @@ struct conky_x11_window {
#ifdef BUILD_XFT
XftDraw *xftdraw;
#endif /*BUILD_XFT*/
#ifdef BUILD_MOUSE_EVENTS
#if defined(BUILD_MOUSE_EVENTS) || defined(BUILD_XINPUT)
// Don't feature gate with BUILD_XINPUT; controls fallback.
std::int32_t xi_opcode;
#endif /* BUILD_MOUSE_EVENTS */
#endif /* BUILD_MOUSE_EVENTS || BUILD_XINPUT */
int width;
int height;
@@ -113,8 +97,8 @@ struct conky_x11_window {
};
extern struct conky_x11_window window;
extern conky::simple_config_setting<std::string> display_name;
void init_x11();
void destroy_window(void);
void create_gc(void);
void set_transparent_background(Window win);
@@ -195,54 +179,4 @@ void xdbe_swap_buffers(void);
void xpmdb_swap_buffers(void);
#endif /* BUILD_XDBE */
namespace priv {
class out_to_x_setting : public conky::simple_config_setting<bool> {
typedef conky::simple_config_setting<bool> Base;
protected:
virtual void lua_setter(lua::state &l, bool init);
virtual void cleanup(lua::state &l);
public:
out_to_x_setting() : Base("out_to_x", true, false) {}
};
#ifdef BUILD_XDBE
class use_xdbe_setting : public conky::simple_config_setting<bool> {
typedef conky::simple_config_setting<bool> Base;
bool set_up(lua::state &l);
protected:
virtual void lua_setter(lua::state &l, bool init);
public:
use_xdbe_setting() : Base("double_buffer", false, false) {}
};
#else
class use_xpmdb_setting : public conky::simple_config_setting<bool> {
typedef conky::simple_config_setting<bool> Base;
bool set_up(lua::state &l);
protected:
virtual void lua_setter(lua::state &l, bool init);
public:
use_xpmdb_setting() : Base("double_buffer", false, false) {}
};
#endif
} /* namespace priv */
extern priv::out_to_x_setting out_to_x;
#ifdef BUILD_XFT
extern conky::simple_config_setting<bool> use_xft;
#endif
#ifdef BUILD_XDBE
extern priv::use_xdbe_setting use_xdbe;
#else
extern priv::use_xpmdb_setting use_xpmdb;
#endif
#endif /* CONKY_X11_H */