From d11742ae184a9d70415bbf8ede917b13593e2fa5 Mon Sep 17 00:00:00 2001 From: bi4k8 Date: Mon, 28 Nov 2022 19:23:23 +0000 Subject: [PATCH] build, colours, core, gui, wayland, wl, x11: implement wayland display backend --- cmake/ConkyBuildOptions.cmake | 5 + cmake/ConkyPlatformChecks.cmake | 35 + cmake/FindWayland.cmake | 59 ++ cmake/config.h.in | 2 + src/CMakeLists.txt | 21 +- src/colours.cc | 45 +- src/conky.cc | 14 +- src/core.cc | 5 +- src/display-output.cc | 2 + src/display-wayland.cc | 1104 +++++++++++++++++++++++++++++++ src/display-wayland.hh | 89 +++ src/fonts.cc | 11 +- src/fonts.h | 1 - src/gradient.cc | 1 + src/gui.cc | 259 ++++++++ src/gui.h | 181 +++++ src/llua.cc | 18 + src/llua.h | 4 - src/scroll.cc | 1 - src/specials.cc | 9 +- src/wl.cc | 118 ++++ src/wl.h | 52 ++ src/x11.cc | 104 +-- src/x11.h | 127 +--- 24 files changed, 2030 insertions(+), 237 deletions(-) create mode 100644 cmake/FindWayland.cmake create mode 100644 src/display-wayland.cc create mode 100644 src/display-wayland.hh create mode 100644 src/gui.cc create mode 100644 src/gui.h create mode 100644 src/wl.cc create mode 100644 src/wl.h diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index 5fc6020e..9ad62dd3 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -177,6 +177,8 @@ else(BUILD_NCURSES) FORCE) endif(BUILD_NCURSES) +option(BUILD_WAYLAND "Build Wayland support" true) + option(BUILD_X11 "Build X11 support" true) if(BUILD_X11) option(OWN_WINDOW "Enable own_window support" true) @@ -208,6 +210,9 @@ endif(BUILD_X11) if(BUILD_X11) set(BUILD_GUI true) endif(BUILD_X11) +if(BUILD_WAYLAND) + set(BUILD_GUI true) +endif(BUILD_WAYLAND) if(OWN_WINDOW) option(BUILD_ARGB "Build ARGB (real transparency) support" true) diff --git a/cmake/ConkyPlatformChecks.cmake b/cmake/ConkyPlatformChecks.cmake index bee9ac1d..0e7a277a 100644 --- a/cmake/ConkyPlatformChecks.cmake +++ b/cmake/ConkyPlatformChecks.cmake @@ -352,6 +352,35 @@ if(BUILD_X11) endif(X11_FOUND) endif(BUILD_X11) +if(BUILD_WAYLAND) + find_package(Wayland REQUIRED) + set(conky_libs ${conky_libs} ${WAYLAND_CLIENT_LIBRARY}) + set(conky_includes ${conky_includes} ${WAYLAND_CLIENT_INCLUDE_DIR}) + + find_package(PkgConfig) + + pkg_check_modules(wayland-protocols QUIET wayland-protocols>=1.13) + if(WAYLAND_CLIENT_FOUND AND wayland-protocols_FOUND) + #target_sources( ${COMPONENT} PRIVATE display-wayland.cxx ) + + # find Wayland protocols + pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) + + # find 'wayland-scanner' executable + pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner) + else(WAYLAND_CLIENT_FOUND AND wayland-protocols_FOUND) + message(FATAL_ERROR "Unable to find wayland-scanner and xdg-shell protocol") + endif(WAYLAND_CLIENT_FOUND AND wayland-protocols_FOUND) + + pkg_check_modules(PANGOCAIRO pangocairo) + set(conky_libs ${conky_libs} ${PANGOCAIRO_LIBRARIES}) + set(conky_includes ${conky_includes} ${PANGOCAIRO_INCLUDE_DIRS}) + + pkg_check_modules(PANGOFC pangofc) + set(conky_libs ${conky_libs} ${PANGOFC_LIBRARIES}) + set(conky_includes ${conky_includes} ${PANGOFC_INCLUDE_DIRS}) +endif(BUILD_WAYLAND) + # Otherwise, use the most recent Lua version pkg_search_module(LUA REQUIRED @@ -454,6 +483,12 @@ if(BUILD_PULSEAUDIO) set(conky_includes ${conky_includes} ${PULSEAUDIO_INCLUDE_DIRS}) endif(BUILD_PULSEAUDIO) +if(WANT_CURL) + pkg_check_modules(CURL REQUIRED libcurl) + set(conky_libs ${conky_libs} ${CURL_LIBRARIES}) + set(conky_includes ${conky_includes} ${CURL_INCLUDE_DIRS}) +endif(WANT_CURL) + # Common libraries if(WANT_GLIB) pkg_check_modules(GLIB REQUIRED glib-2.0>=2.36) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake new file mode 100644 index 00000000..e9009f55 --- /dev/null +++ b/cmake/FindWayland.cmake @@ -0,0 +1,59 @@ +find_path( + WAYLAND_CLIENT_INCLUDE_DIR + NAMES wayland-client.h +) + +find_library( + WAYLAND_CLIENT_LIBRARY + NAMES wayland-client libwayland-client +) + +if(WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY) + add_library(wayland::client UNKNOWN IMPORTED) + + set_target_properties( + wayland::client PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_CLIENT_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${WAYLAND_CLIENT_LIBRARY}" + ) +endif() + +find_path( + WAYLAND_SERVER_INCLUDE_DIR + NAMES wayland-server.h +) + +find_library( + WAYLAND_SERVER_LIBRARY + NAMES wayland-server libwayland-server +) + +if(WAYLAND_SERVER_INCLUDE_DIR AND WAYLAND_SERVER_LIBRARY) + add_library(wayland::server UNKNOWN IMPORTED) + + set_target_properties( + wayland::server PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${WAYLAND_SERVER_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${WAYLAND_SERVER_LIBRARY}" + ) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + WAYLAND_CLIENT + REQUIRED_VARS WAYLAND_CLIENT_LIBRARY WAYLAND_CLIENT_INCLUDE_DIR +) + +find_package_handle_standard_args( + WAYLAND_SERVER + REQUIRED_VARS WAYLAND_SERVER_LIBRARY WAYLAND_SERVER_INCLUDE_DIR +) + +mark_as_advanced( + WAYLAND_CLIENT_INCLUDE_DIR + WAYLAND_CLIENT_LIBRARY + WAYLAND_SERVER_INCLUDE_DIR + WAYLAND_SERVER_LIBRARY +) \ No newline at end of file diff --git a/cmake/config.h.in b/cmake/config.h.in index 39a48dd1..2d4f6ed4 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -42,6 +42,8 @@ #cmakedefine HAVE_CLOCK_GETTIME 1 +#cmakedefine BUILD_WAYLAND 1 + #cmakedefine BUILD_X11 1 #cmakedefine OWN_WINDOW 1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4544b48f..d5b8f043 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -120,6 +120,8 @@ set(conky_sources display-http.hh display-x11.cc display-x11.hh + display-wayland.cc + display-wayland.hh lua-config.cc lua-config.hh setting.cc @@ -227,7 +229,7 @@ if(BUILD_PORT_MONITORS) endif(BUILD_PORT_MONITORS) if(BUILD_GUI) - set(gui fonts.cc fonts.h) + set(gui fonts.cc fonts.h gui.cc gui.h) set(optional_sources ${optional_sources} ${gui}) endif(BUILD_GUI) @@ -241,6 +243,23 @@ if(BUILD_X11) endif(BUILD_XINERAMA) endif(BUILD_X11) +if(BUILD_WAYLAND) + set(wl_srcs wl.cc wl.h xdg-shell-protocol.c) + set(optional_sources ${optional_sources} ${wl_srcs}) + # generate protocol implementation + set(XDG_PROT_DEF "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml") + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xdg-shell-client-protocol.h + COMMAND ${WAYLAND_SCANNER} client-header ${XDG_PROT_DEF} xdg-shell-client-protocol.h) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xdg-shell-protocol.c + COMMAND ${WAYLAND_SCANNER} private-code ${XDG_PROT_DEF} xdg-shell-protocol.c + DEPENDS xdg-shell-client-protocol.h) + + # include output dir in include path + include_directories(${CMAKE_CURRENT_BINARY_DIR}) +endif(BUILD_WAYLAND) + if(BUILD_HDDTEMP) set(hddtemp hddtemp.cc hddtemp.h) set(optional_sources ${optional_sources} ${hddtemp}) diff --git a/src/colours.cc b/src/colours.cc index ab1a009b..afd28fba 100644 --- a/src/colours.cc +++ b/src/colours.cc @@ -83,8 +83,23 @@ unsigned int adjust_colours(unsigned int colour) { return colour; } -#ifdef BUILD_X11 + +#ifdef BUILD_GUI +#ifndef 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; +} +#endif /* !BUILD_X11 */ + long get_x11_color(const char *name) { +#ifdef BUILD_X11 XColor color; color.pixel = 0; @@ -108,9 +123,35 @@ long get_x11_color(const char *name) { } return static_cast(color.pixel); +#else /*BUILD_X11*/ + if (name[0] == '#') { + name++; + } + size_t len = strlen(name); + if (len == 6 || len == 8) + { + unsigned char argb[4] = {0xff, 0, 0, 0}; + 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; + } + int val = (nib1 << 4) + nib2; + + argb[3 - i / 2] = val; + } + long out; + memcpy(static_cast(&out), argb, 4); + return out; + } + err: + NORM_ERR("can't parse X color '%s'", name); + return 0xFF00FF; +#endif /*BUILD_X11*/ } long get_x11_color(const std::string &colour) { return get_x11_color(colour.c_str()); } -#endif +#endif /*BUILD_GUI*/ diff --git a/src/conky.cc b/src/conky.cc index 082e1d3a..7a6e4703 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -54,6 +54,9 @@ #include #pragma clang diagnostic pop #endif /* HAVE_SYS_INOTIFY_H */ +#ifdef BUILD_WAYLAND +#include "wl.h" +#endif /* BUILD_WAYLAND */ #ifdef BUILD_X11 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvariadic-macros" @@ -90,6 +93,7 @@ #include "exec.h" #ifdef BUILD_GUI #include "fonts.h" +#include "gui.h" #endif #include "fs.h" #ifdef BUILD_ICONV @@ -1930,11 +1934,19 @@ static void set_default_configurations() { info.xmms2.status = nullptr; info.xmms2.playlist = nullptr; #endif /* BUILD_XMMS2 */ + +/* Enable a single output by default based on what was enabled at build-time */ +#ifdef BUILD_WAYLAND + state->pushboolean(true); + out_to_wayland.lua_set(*state); +#else +#ifdef BUILD_X11 state->pushboolean(true); -#ifdef BUILD_GUI out_to_x.lua_set(*state); #else + state->pushboolean(true); out_to_stdout.lua_set(*state); +#endif #endif info.users.number = 1; diff --git a/src/core.cc b/src/core.cc index 7e3d1db7..156afb41 100644 --- a/src/core.cc +++ b/src/core.cc @@ -54,6 +54,7 @@ #include "irc.h" #endif /* BUILD_IRC */ #ifdef BUILD_GUI +#include "gui.h" #include "fonts.h" #endif /* BUILD_GUI */ #include "fs.h" @@ -749,7 +750,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, #endif /* BUILD_GUI */ END OBJ(color, nullptr) #ifdef BUILD_GUI - if (out_to_x.get(*state)) { + if (out_to_gui(*state)) { obj->data.l = arg != nullptr ? get_x11_color(arg) : default_color.get(*state); set_current_text_color(obj->data.l); @@ -883,7 +884,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_cat; obj->callbacks.free = &gen_free_opaque; -#ifdef BUILD_GUI +#ifdef BUILD_X11 END OBJ(key_num_lock, 0) obj->callbacks.print = &print_key_num_lock; END OBJ(key_caps_lock, 0) obj->callbacks.print = &print_key_caps_lock; END OBJ(key_scroll_lock, 0) obj->callbacks.print = &print_key_scroll_lock; diff --git a/src/display-output.cc b/src/display-output.cc index a06e5e02..cad36e97 100644 --- a/src/display-output.cc +++ b/src/display-output.cc @@ -56,6 +56,7 @@ 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(); /* * The selected and active display output. @@ -111,6 +112,7 @@ bool initialize_display_outputs() { init_file_output(); init_http_output(); init_x11_output(); + init_wayland_output(); std::vector outputs; outputs.reserve(display_outputs->size()); diff --git a/src/display-wayland.cc b/src/display-wayland.cc new file mode 100644 index 00000000..f3db62a7 --- /dev/null +++ b/src/display-wayland.cc @@ -0,0 +1,1104 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (C) 2018-2021 François Revol et al. + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include + +#ifdef BUILD_WAYLAND +#include +//#include "wayland.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#endif /* BUILD_WAYLAND */ + +#include +#include + +#include "conky.h" +#include "display-wayland.hh" +#include "llua.h" +#include "gui.h" +#ifdef BUILD_X11 +#include "x11.h" +#endif +#ifdef BUILD_WAYLAND +#include "fonts.h" +#endif + +/* TODO: cleanup global namespace */ +#ifdef BUILD_WAYLAND + +static int +set_cloexec_or_close(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto err; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + return fd; + +err: + close(fd); + return -1; +} + +static int +create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficent, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +static int +os_create_anonymous_file(off_t size) +{ + static const char templ[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = static_cast(malloc(strlen(path) + sizeof(templ))); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, templ); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } + return fd; +} + +// TODO: cleanup externs (move to conky.h ?) +#ifdef OWN_WINDOW +extern int fixed_size, fixed_pos; +#endif +extern int text_start_x, text_start_y; /* text start position in window */ +extern int text_offset_x, text_offset_y; /* offset for start position */ +extern int text_width, + text_height; /* initially 1 so no zero-sized window is created */ +extern double current_update_time, next_update_time, last_update_time; +void update_text(); +extern int need_to_update; +int get_border_total(); +extern conky::range_config_setting maximum_width; +extern long current_color; + +/* for pango_fonts */ +struct pango_font { + PangoFontDescription *desc; + + struct { + uint32_t ascent; + uint32_t descent; + } metrics; + int font_alpha; + + pango_font() + : desc(nullptr), + metrics({0, 0}), + font_alpha(0xffff) + { + } +}; + +static std::vector pango_fonts; /* indexed by selected_font */ + +namespace { +class textalpha_setting : public conky::simple_config_setting { + using Base = conky::simple_config_setting; + + protected: + void lua_setter(lua::state &l, bool init) override { + lua::stack_sentry s(l, -2); + + Base::lua_setter(l, init); + + if (init) { + pango_fonts.resize(std::max(1, static_cast(fonts.size()))); + pango_fonts[0].desc = nullptr; + pango_fonts[0].font_alpha = do_convert(l, -1).first * 0xffff; + } + + ++s; + } + + public: + textalpha_setting() : Base("textalpha", 1.0, false) {} +}; + +textalpha_setting textalpha; +} // namespace + +static void wayland_create_window(); + +static void wayland_create_window() { + setup_fonts(); + load_fonts(utf8_mode.get(*state)); + update_text_area(); /* to position text/window on screen */ + +#ifdef OWN_WINDOW + if (own_window.get(*state)) { + if (fixed_pos == 0) { + //XMoveWindow(display, window.window, window.x, window.y); + //TODO + } + + //set_transparent_background(window.window); + } +#endif + + selected_font = 0; + 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 + +display_output_wayland::display_output_wayland() : display_output_base("wayland") { + is_graphical = true; + priority = 2; +} + +bool display_output_wayland::detect() { + if (out_to_wayland.get(*state)) { + DBGP2("Wayland display output '%s' enabled in config.", name.c_str()); + return true; + } + return false; +} + +static int epoll_fd; +static struct epoll_event ep[1]; + +static struct window *global_window; +static wl_display *global_display; + +struct rectangle { + size_t x, y, width, height; +}; + +struct window { + struct rectangle rectangle; + struct wl_shm *shm; + struct wl_surface *surface; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + cairo_surface_t *cairo_surface; + cairo_t *cr; + PangoLayout *layout; + PangoContext* pango_context; +}; + +struct { + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shm *shm; +/* struct wl_shell *shell; + struct wl_shell_surface *shell_surface;*/ + struct wl_surface *surface; + struct wl_seat *seat; +/* struct wl_pointer *pointer;*/ + struct wl_output *output; + struct xdg_wm_base *shell; +} wl_globals; + + +static void +xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) +{ + xdg_wm_base_pong(shell, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + .ping = &xdg_wm_base_ping, +}; + + +void +registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, + const char *interface, uint32_t version) { + if(strcmp(interface, "wl_compositor") == 0) { + wl_globals.compositor = static_cast(wl_registry_bind(registry, name, + &wl_compositor_interface, 3)); + } else if(strcmp(interface, "wl_shm") == 0) { + wl_globals.shm = static_cast(wl_registry_bind(registry, name, &wl_shm_interface, 1)); + } else if(strcmp(interface, "wl_seat") == 0) { + wl_globals.seat = static_cast(wl_registry_bind(registry, name, + &wl_seat_interface, 1)); + } else if(strcmp(interface, "wl_output") == 0) { + wl_globals.output = static_cast(wl_registry_bind(registry, name, &wl_output_interface, 1)); + } else if(strcmp(interface, "xdg_wm_base") == 0) { + wl_globals.shell = static_cast(wl_registry_bind(registry, name, &xdg_wm_base_interface, 1)); + xdg_wm_base_add_listener(wl_globals.shell, &xdg_wm_base_listener, nullptr); + } +} + +void +registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { +} + + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + + +static void +xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, + int32_t width, int32_t height, struct wl_array *states) +{ +} + +static void +xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) +{ +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = &xdg_toplevel_configure, + .close = &xdg_toplevel_close, +}; + +static void +xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, + uint32_t serial) +{ + xdg_surface_ack_configure(xdg_surface, serial); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = &xdg_surface_configure, +}; + +struct window * +window_create(struct wl_surface* surface, struct wl_shm* shm, int width, int height); + +void +window_resize(struct window *window, int width, int height); + +void +window_destroy(struct window *window); + +void +window_commit_buffer(struct window *window); + +void +window_get_width_height(struct window *window, int *w, int *h); + +bool display_output_wayland::initialize() { + epoll_fd = epoll_create1(0); + if(epoll_fd < 0) { + perror("conky: epoll_create"); + return false; + } + global_display = wl_display_connect(NULL); + if (!global_display) { + perror("conky: wl_display_connect"); + return false; + } + + wl_globals.registry = wl_display_get_registry(global_display); + wl_registry_add_listener(wl_globals.registry, ®istry_listener, NULL); + + wl_display_roundtrip(global_display); + + struct wl_surface *surface = wl_compositor_create_surface(wl_globals.compositor); + global_window = window_create(surface, wl_globals.shm, 1, 1); + + global_window->xdg_surface = xdg_wm_base_get_xdg_surface(wl_globals.shell, global_window->surface); + xdg_surface_add_listener(global_window->xdg_surface, &xdg_surface_listener, nullptr); + + global_window->xdg_toplevel = xdg_surface_get_toplevel(global_window->xdg_surface); + xdg_toplevel_add_listener(global_window->xdg_toplevel, &xdg_toplevel_listener, nullptr); + + xdg_toplevel_set_app_id(global_window->xdg_toplevel, "conky"); + xdg_toplevel_set_title(global_window->xdg_toplevel, "conky"); + xdg_toplevel_set_parent(global_window->xdg_toplevel, 0); + wl_surface_set_buffer_scale(global_window->surface, 1); + wl_surface_commit(global_window->surface); + wl_display_roundtrip(global_display); + + wayland_create_window(); + return true; +} + +typedef void (*display_global_handler_t)(struct display *display, + uint32_t name, + const char *interface, + uint32_t version, void *data); +typedef void (*display_output_handler_t)(struct output *output, void *data); + +bool display_output_wayland::shutdown() { return false; } + +#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0])) + +static bool added = false; + +bool display_output_wayland::main_loop_wait(double t) { + while (wl_display_prepare_read(global_display) != 0) + wl_display_dispatch_pending(global_display); + wl_display_flush(global_display); + + if (t < 0.0) { + t = 0.0; + } + int ms = t * 1000; + + /* add fd to epoll set the first time around */ + if (!added) { + ep[0].events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLET; + ep[0].data.ptr = nullptr; + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, wl_display_get_fd(global_display), &ep[0]) == -1) { + perror("conky: epoll_ctl: add"); + return false; + } + added = true; + } + + /* wait for Wayland event or timeout */ + int ep_count = epoll_wait(epoll_fd, ep, ARRAY_LENGTH(ep), ms); + if (ep_count > 0) { + if (ep[0].events & (EPOLLERR | EPOLLHUP)) { + NORM_ERR("output closed"); + exit(1); + return false; + } + } + + wl_display_dispatch_pending(global_display); + + wl_display_flush(global_display); + + /* timeout */ + if (ep_count == 0) { update_text(); } + + if (need_to_update != 0) { + + need_to_update = 0; + selected_font = 0; + update_text_area(); + + int changed = 0; + int border_total = get_border_total(); + + int width, height; + window_get_width_height(global_window, &width, &height); + + int fixed_size = 0; + + /* resize window if it isn't right size */ + if ((fixed_size == 0) && + (text_width + 2 * border_total != width || + text_height + 2 * border_total != height)) { + width = text_width + 2 * border_total; + height = text_height + 2 * border_total; + window_resize(global_window, width, height); /* resize window */ + + changed++; + /* update lua window globals */ + llua_update_window_table(text_start_x, text_start_y, text_width, + text_height); + } + + /* move window if it isn't in right position */ + #ifdef POSITION + if ((fixed_pos == 0) && (window.x != wx || window.y != wy)) { + //XMoveWindow(display, window.window, window.x, window.y); + changed++; + } + #endif + + /* update struts */ + if (changed != 0) { + int sidenum = -1; + + DBGP("%s", _(PACKAGE_NAME ": defining struts\n")); + fflush(stderr); + + switch (text_alignment.get(*state)) { + case TOP_LEFT: + case TOP_RIGHT: + case TOP_MIDDLE: { + sidenum = 2; + break; + } + case BOTTOM_LEFT: + case BOTTOM_RIGHT: + case BOTTOM_MIDDLE: { + sidenum = 3; + break; + } + case MIDDLE_LEFT: { + sidenum = 0; + break; + } + case MIDDLE_RIGHT: { + sidenum = 1; + break; + } + + case NONE: + case MIDDLE_MIDDLE: /* XXX What about these? */; + } + + //set_struts(sidenum); + } + + clear_text(1); + draw_stuff(); + } + wl_display_flush(global_display); + +#ifdef INPUT +#ifdef X_EVENT + case ButtonPress: + if (own_window.get(*state)) { + /* if an ordinary window with decorations */ + if ((own_window_type.get(*state) == TYPE_NORMAL && + !TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) || + own_window_type.get(*state) == TYPE_DESKTOP) { + /* allow conky to hold input focus. */ + break; + } + /* forward the click to the desktop window */ + XUngrabPointer(display, ev.xbutton.time); + ev.xbutton.window = window.desktop; + ev.xbutton.x = ev.xbutton.x_root; + ev.xbutton.y = ev.xbutton.y_root; + XSendEvent(display, ev.xbutton.window, False, ButtonPressMask, &ev); + XSetInputFocus(display, ev.xbutton.window, RevertToParent, + ev.xbutton.time); + } + break; + + case ButtonRelease: + if (own_window.get(*state)) { + /* if an ordinary window with decorations */ + if ((own_window_type.get(*state) == TYPE_NORMAL) && + !TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) { + /* allow conky to hold input focus. */ + break; + } + /* forward the release to the desktop window */ + ev.xbutton.window = window.desktop; + ev.xbutton.x = ev.xbutton.x_root; + ev.xbutton.y = ev.xbutton.y_root; + XSendEvent(display, ev.xbutton.window, False, ButtonReleaseMask, &ev); + } + break; +#endif /*X_EVENT*/ +#endif /*INPUT*/ + + // handled + return true; +} + +void display_output_wayland::sigterm_cleanup() { +} + +void display_output_wayland::cleanup() { + if (global_window != nullptr) { + window_destroy(global_window); + global_window = nullptr; + } + free_fonts(utf8_mode.get(*state)); +} + +void display_output_wayland::set_foreground_color(long c) { +#ifdef BUILD_ARGB + current_color = (c & ~0xff) | own_window_argb_value.get(*state); +#else + current_color = c; +#endif /* BUILD_ARGB */ + uint8_t r = current_color >> 24; + uint8_t g = current_color >> 16; + uint8_t b = current_color >> 8; + uint8_t a = current_color; + if (global_window->cr) { + cairo_set_source_rgba(global_window->cr, r / 255.0, g / 255.0, b / 255.0, a / 255.0); + } +} + +int display_output_wayland::calc_text_width(const char *s) { + struct window *window = global_window; + size_t slen = strlen(s); + pango_layout_set_text(window->layout, s, slen); + PangoRectangle margin_rect; + pango_layout_set_font_description(window->layout, pango_fonts[selected_font].desc); + pango_layout_get_pixel_extents(window->layout, nullptr, &margin_rect); + return margin_rect.width; +} + +static void adjust_coords(int& x, int& y) { + x -= text_start_x; + y -= text_start_y; + int border = get_border_total(); + x += border; + y += border; +} + +void display_output_wayland::draw_string_at(int x, int y, const char *s, int w) { + struct window *window = global_window; + y -= pango_fonts[selected_font].metrics.ascent; + adjust_coords(x, y); + pango_layout_set_text(window->layout, s, strlen(s)); + cairo_save(window->cr); + uint8_t r = current_color >> 24; + uint8_t g = current_color >> 16; + uint8_t b = current_color >> 8; + unsigned int a = pango_fonts[selected_font].font_alpha; + cairo_set_source_rgba(global_window->cr, r / 255.0, g / 255.0, b / 255.0, a / 65535.); + cairo_move_to(window->cr, x, y); + pango_cairo_show_layout(window->cr, window->layout); + cairo_restore(window->cr); +} + +void display_output_wayland::set_line_style(int w, bool solid) { + struct window *window = global_window; + static double dashes[2] = {1.0, 1.0}; + if(solid) + cairo_set_dash(window->cr, nullptr, 0, 0); + else + cairo_set_dash(window->cr, dashes, 2, 0); + cairo_set_line_width(window->cr, w); +} + +void display_output_wayland::set_dashes(char *s) { + struct window *window = global_window; + size_t len = strlen(s); + double* dashes = new double[len]; + for (size_t i = 0; i < len; i++) { + dashes[i] = s[i]; + } + cairo_set_dash(window->cr, dashes, len, 0); + delete[] dashes; +} + +void display_output_wayland::draw_line(int x1, int y1, int x2, int y2) { + struct window *window = global_window; + adjust_coords(x1, y1); + adjust_coords(x2, y2); + cairo_save(window->cr); + cairo_move_to(window->cr, x1 - 0.5, y1 - 0.5); + cairo_line_to(window->cr, x2 - 0.5, y2 - 0.5); + cairo_stroke(window->cr); + cairo_restore(window->cr); +} + +static void do_rect(int x, int y, int w, int h, bool fill) { + struct window *window = global_window; + adjust_coords(x, y); + + cairo_save(window->cr); + if (fill) { + /* Note that cairo interprets fill and stroke coordinates differently, + so here we don't add 0.5 to move between centers and corners of pixels. */ + cairo_rectangle(window->cr, x, y, w - 1, h - 1); + cairo_fill(window->cr); + } else { + cairo_rectangle(window->cr, x - 0.5, y - 0.5, w, h); + cairo_stroke(window->cr); + } + cairo_restore(window->cr); +} + +void display_output_wayland::draw_rect(int x, int y, int w, int h) { + do_rect(x, y, w, h, false); +} + +void display_output_wayland::fill_rect(int x, int y, int w, int h) { + do_rect(x, y, w, h, true); +} + +void display_output_wayland::draw_arc(int x, int y, int w, int h, int a1, int a2) { + struct window *window = global_window; + adjust_coords(x, y); + cairo_save(window->cr); + cairo_translate(window->cr, x + w / 2. - 0.5, y + h / 2. - 0.5); + cairo_scale(window->cr, w / 2., h / 2.); + cairo_set_line_width(window->cr, 2. / (w + h)); + double mult = M_PI / (180. * 64.); + cairo_arc_negative(window->cr, 0., 0., 1., a1 * mult, a2 * mult); + cairo_stroke(window->cr); + cairo_restore(window->cr); +} + +void display_output_wayland::move_win(int x, int y) { + //window.x = x; + //window.y = y; + //TODO +} + +int display_output_wayland::dpi_scale(int value) { + return value; +} + +void display_output_wayland::end_draw_stuff() { + window_commit_buffer(global_window); +} + +void display_output_wayland::clear_text(int exposures) { + struct window *window = global_window; + cairo_save (window->cr); + long color = 0; +#ifdef OWN_WINDOW + color = background_colour.get(*state); + if (set_transparent.get(*state)) { + color &= ~0xff; + } else { +#ifdef BUILD_ARGB + color |= (own_window_argb_value.get(*state)); +#else + color |= 0xff; +#endif + } +#endif + uint8_t r = color >> 24; + uint8_t g = color >> 16; + uint8_t b = color >> 8; + uint8_t a = color; + cairo_set_source_rgba (window->cr, r / 255.0, g / 255.0, b / 255.0, a / 255.); + cairo_set_operator (window->cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (window->cr); + cairo_restore (window->cr); +} + +int display_output_wayland::font_height(unsigned int f) { + if (pango_fonts.size() == 0) { + return 2; + } + assert(f < pango_fonts.size()); + return pango_fonts[f].metrics.ascent + pango_fonts[f].metrics.descent; +} + +int display_output_wayland::font_ascent(unsigned int f) { + if (pango_fonts.size() == 0) { + return 1; + } + assert(f < pango_fonts.size()); + return pango_fonts[f].metrics.ascent; +} + +int display_output_wayland::font_descent(unsigned int f) { + if (pango_fonts.size() == 0) { + return 1; + } + assert(f < pango_fonts.size()); + return pango_fonts[f].metrics.descent; +} + +void display_output_wayland::setup_fonts(void) { + /* Nothing to do here */ +} + +void display_output_wayland::set_font(unsigned int f) { + assert(f < pango_fonts.size()); + if (pango_fonts.size() > f && pango_fonts[f].desc != nullptr) { + pango_layout_set_font_description(global_window->layout, pango_fonts[f].desc); + } +} + +void display_output_wayland::free_fonts(bool utf8) { + for (auto &font : pango_fonts) { + if (font.desc != nullptr) { pango_font_description_free(font.desc); font.desc = nullptr; } + } + pango_fonts.clear(); +} + +void display_output_wayland::load_fonts(bool utf8) { + free_fonts(utf8); + pango_fonts.resize(fonts.size()); + for (unsigned int i = 0; i < fonts.size(); i++) { + auto &font = fonts[i]; + auto &pango_font_entry = pango_fonts[i]; + FcPattern* fc_pattern = FcNameParse(reinterpret_cast(font.name.c_str())); + pango_font_entry.desc = pango_fc_font_description_from_pattern(fc_pattern, true); + + // Handle pixel size ourselves because pango_fc_font_description_from_pattern does not + double pixel_size = -1; + if (FcPatternGetDouble (fc_pattern, FC_PIXEL_SIZE, 0, &pixel_size) == FcResultMatch) { + pango_font_description_set_absolute_size(pango_font_entry.desc, pixel_size * PANGO_SCALE); + } + FcPatternDestroy(fc_pattern); + + PangoFont* pango_font = pango_context_load_font(global_window->pango_context, pango_font_entry.desc); + PangoFontMetrics* font_metrics = pango_font_get_metrics(pango_font, nullptr); + auto ascent = pango_font_metrics_get_ascent(font_metrics) / PANGO_SCALE; + auto descent = pango_font_metrics_get_descent(font_metrics) / PANGO_SCALE; + pango_font_metrics_unref(font_metrics); + g_object_unref(pango_font); + + pango_font_entry.metrics.ascent = ascent; + pango_font_entry.metrics.descent = descent; + } +} + + +struct shm_pool { + struct wl_shm_pool *pool; + size_t size; + size_t used; + void *data; +}; + +struct shm_surface_data { + struct wl_buffer *buffer; + struct shm_pool *pool; +}; + +static const cairo_user_data_key_t shm_surface_data_key = {0}; + +struct wl_buffer * +get_buffer_from_cairo_surface(cairo_surface_t *surface) +{ + struct shm_surface_data *data; + + data = static_cast(cairo_surface_get_user_data(surface, &shm_surface_data_key)); + + return data->buffer; +} + +static void +shm_pool_destroy(struct shm_pool *pool); + +static void +shm_surface_data_destroy(void *p) +{ + struct shm_surface_data *data = static_cast(p); + wl_buffer_destroy(data->buffer); + if (data->pool) + shm_pool_destroy(data->pool); + + delete data; +} + +static struct wl_shm_pool * +make_shm_pool(struct wl_shm *shm, int size, void **data) +{ + struct wl_shm_pool *pool; + int fd; + + fd = os_create_anonymous_file(size); + if (fd < 0) { + fprintf(stderr, "creating a buffer file for %d B failed: %m\n", + size); + return NULL; + } + + *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (*data == MAP_FAILED) { + fprintf(stderr, "mmap failed: %m\n"); + close(fd); + return NULL; + } + + pool = wl_shm_create_pool(shm, fd, size); + + close(fd); + + return pool; +} + +static struct shm_pool * +shm_pool_create(struct wl_shm *shm, size_t size) +{ + struct shm_pool *pool = new struct shm_pool; + + if (!pool) + return NULL; + + pool->pool = make_shm_pool(shm, size, &pool->data); + if (!pool->pool) { + delete pool; + return NULL; + } + + pool->size = size; + pool->used = 0; + + return pool; +} + +static void * +shm_pool_allocate(struct shm_pool *pool, size_t size, int *offset) +{ + if (pool->used + size > pool->size) + return NULL; + + *offset = pool->used; + pool->used += size; + + return (char *) pool->data + *offset; +} + +/* destroy the pool. this does not unmap the memory though */ +static void +shm_pool_destroy(struct shm_pool *pool) +{ + munmap(pool->data, pool->size); + wl_shm_pool_destroy(pool->pool); + delete pool; +} + +static int +data_length_for_shm_surface(struct rectangle *rect) +{ + int stride; + + stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, + rect->width); + return stride * rect->height; +} + +static cairo_surface_t * +create_shm_surface_from_pool(void *none, + struct rectangle *rectangle, + struct shm_pool *pool) +{ + struct shm_surface_data *data; + uint32_t format; + cairo_surface_t *surface; + cairo_format_t cairo_format; + int stride, length, offset; + void *map; + + data = new struct shm_surface_data; + if (data == NULL) + return NULL; + + cairo_format = CAIRO_FORMAT_ARGB32; /*or CAIRO_FORMAT_RGB16_565 who knows??*/ + + stride = cairo_format_stride_for_width (cairo_format, rectangle->width); + length = stride * rectangle->height; + data->pool = NULL; + map = shm_pool_allocate(pool, length, &offset); + + if (!map) { + delete data; + return NULL; + } + + surface = cairo_image_surface_create_for_data (static_cast(map), + cairo_format, + rectangle->width, + rectangle->height, + stride); + + cairo_surface_set_user_data(surface, &shm_surface_data_key, + data, shm_surface_data_destroy); + + format = WL_SHM_FORMAT_ARGB8888; /*or WL_SHM_FORMAT_RGB565*/ + + data->buffer = wl_shm_pool_create_buffer(pool->pool, offset, + rectangle->width, + rectangle->height, + stride, format); + + return surface; +} + +void +window_allocate_buffer(struct window *window) { + assert(window->shm != nullptr); + struct shm_pool *pool; + pool = shm_pool_create(window->shm, + data_length_for_shm_surface(&window->rectangle)); + if (!pool) { + fprintf(stderr, "could not allocate shm pool\n"); + return; + } + + window->cairo_surface = + create_shm_surface_from_pool(window->shm, &window->rectangle, pool); + + if (!window->cairo_surface) { + shm_pool_destroy(pool); + return; + } + + window->cr = cairo_create(window->cairo_surface); + window->layout = pango_cairo_create_layout(window->cr); + window->pango_context = pango_cairo_create_context(window->cr); + + /* make sure we destroy the pool when the surface is destroyed */ + struct shm_surface_data *data; + data = static_cast(cairo_surface_get_user_data(window->cairo_surface, &shm_surface_data_key)); + data->pool = pool; +} + +struct window * +window_create(struct wl_surface* surface, struct wl_shm* shm, int width, int height) { + struct window *window; + window = new struct window; + + window->rectangle.x = 0; + window->rectangle.y = 0; + window->rectangle.width = width; + window->rectangle.height = height; + + window->surface = surface; + window->shm = shm; + + window_allocate_buffer(window); + + return window; +} + +void +window_free_buffer(struct window* window) { + cairo_surface_destroy(window->cairo_surface); + cairo_destroy(window->cr); + g_object_unref(window->layout); + g_object_unref(window->pango_context); + window->cairo_surface = nullptr; + window->cr = nullptr; + window->layout = nullptr; + window->pango_context = nullptr; +} + +void +window_destroy(struct window *window) { + cairo_surface_destroy(window->cairo_surface); + cairo_destroy(window->cr); + g_object_unref(window->layout); + g_object_unref(window->pango_context); +} + +void +window_resize(struct window *window, int width, int height) { + window_free_buffer(window); + window->rectangle.width = width; + window->rectangle.height = height; + window_allocate_buffer(window); +} + +void +window_commit_buffer(struct window *window) { + assert(window->cairo_surface != nullptr); + wl_surface_attach(window->surface, get_buffer_from_cairo_surface(window->cairo_surface), 0, 0); + /* repaint all the pixels in the surface, change size to only repaint changed area*/ + wl_surface_damage(window->surface, window->rectangle.x, + window->rectangle.y, + window->rectangle.width, + window->rectangle.height); + wl_surface_commit(window->surface); +} + +void +window_get_width_height(struct window *window, int *w, int *h) { + *w = window->rectangle.width; + *h = window->rectangle.height; +} + +#endif /* BUILD_WAYLAND */ + +} // namespace conky diff --git a/src/display-wayland.hh b/src/display-wayland.hh new file mode 100644 index 00000000..f29bd147 --- /dev/null +++ b/src/display-wayland.hh @@ -0,0 +1,89 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (C) 2018-2021 François Revol et al. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef DISPLAY_WAYLAND_HH +#define DISPLAY_WAYLAND_HH + +#include +#include +#include + +#include "display-output.hh" +#include "luamm.hh" +#include "wl.h" + +namespace conky { + +/* + * A base class for Wayland display output. + */ +class display_output_wayland : public display_output_base { + public: + explicit display_output_wayland(); + + virtual ~display_output_wayland() {} + + // check if available and enabled in settings + virtual bool detect(); + // connect to DISPLAY and other stuff + virtual bool initialize(); + virtual bool shutdown(); + + virtual bool main_loop_wait(double); + + virtual void sigterm_cleanup(); + virtual void cleanup(); + + // drawing primitives + virtual void set_foreground_color(long); + + virtual int calc_text_width(const char *); + + // GUI interface + virtual void draw_string_at(int, int, const char *, int ); + // X11 lookalikes + virtual void set_line_style(int, bool); + virtual void set_dashes(char *); + virtual void draw_line(int, int, int, int); + virtual void draw_rect(int, int, int, int); + 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); + + virtual void end_draw_stuff(); + virtual void clear_text(int); + + virtual int font_height(unsigned int); + virtual int font_ascent(unsigned int); + virtual int font_descent(unsigned int); + virtual void setup_fonts(void); + virtual void set_font(unsigned int); + virtual void free_fonts(bool); + virtual void load_fonts(bool); + + // Wayland-specific +}; + +} // namespace conky + +#endif /* DISPLAY_WAYLAND_HH */ diff --git a/src/fonts.cc b/src/fonts.cc index 87f23d06..74cbd17d 100644 --- a/src/fonts.cc +++ b/src/fonts.cc @@ -28,6 +28,7 @@ */ #include "fonts.h" +#include "gui.h" #include "display-output.hh" #include "logging.h" @@ -40,7 +41,7 @@ void font_setting::lua_setter(lua::state &l, bool init) { Base::lua_setter(l, init); - if (init && out_to_x.get(*state)) { + if (init) { if (fonts.empty()) { fonts.resize(1); } fonts[0].name = do_convert(l, -1).first; } @@ -66,7 +67,7 @@ void setup_fonts() { } int add_font(const char *data_in) { - if (!out_to_x.get(*state)) { return 0; } + if (!out_to_gui(*state)) { return 0; } fonts.emplace_back(); fonts.rbegin()->name = data_in; @@ -85,16 +86,16 @@ void load_fonts(bool utf8) { } int font_height() { - assert(selected_font < fonts.size()); + //assert(selected_font < fonts.size()); return display_output()->font_height(selected_font); } int font_ascent() { - assert(selected_font < fonts.size()); + //assert(selected_font < fonts.size()); return display_output()->font_ascent(selected_font); } int font_descent() { - assert(selected_font < fonts.size()); + //assert(selected_font < fonts.size()); return display_output()->font_descent(selected_font); } diff --git a/src/fonts.h b/src/fonts.h index 6f8a8c5c..da329675 100644 --- a/src/fonts.h +++ b/src/fonts.h @@ -32,7 +32,6 @@ #include #include "conky.h" -#include "x11.h" /* for fonts */ struct font_list { diff --git a/src/gradient.cc b/src/gradient.cc index af06fdc3..316aee22 100644 --- a/src/gradient.cc +++ b/src/gradient.cc @@ -32,6 +32,7 @@ #ifdef BUILD_X11 #include "x11.h" +#include "gui.h" #endif /* BUILD_X11 */ namespace conky { diff --git a/src/gui.cc b/src/gui.cc new file mode 100644 index 00000000..53adc2db --- /dev/null +++ b/src/gui.cc @@ -0,0 +1,259 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "common.h" +#include "config.h" +#include "conky.h" +#include "logging.h" +#include "gui.h" +#include "wl.h" + +#ifdef BUILD_IMLIB2 +#include "imlib2.h" +#endif /* BUILD_IMLIB2 */ +#ifndef OWN_WINDOW +#include +#endif + +#ifdef BUILD_ARGB +bool have_argb_visual; +#endif /* BUILD_ARGB */ + +/* basic display attributes */ +int display_width; +int display_height; +int screen; + +/* workarea where window / text is aligned (from _NET_WORKAREA on X11) */ +int workarea[4]; + +/* Window stuff */ +char window_created = 0; + +/* local prototypes */ +#ifdef BUILD_X11 +void x11_init_window(lua::state &l, bool own); +#endif /*BUILD_X11*/ + +/********************* ************************/ + + +priv::colour_setting background_colour("own_window_colour", 0); + +bool out_to_gui(lua::state &l) { + bool to_gui = false; +#ifdef BUILD_X11 + to_gui |= out_to_x.get(l); +#endif /* BUILD_X11 */ +#ifdef BUILD_WAYLAND + to_gui |= out_to_wayland.get(l); +#endif /* BUILD_WAYLAND */ + return to_gui; +} + +namespace priv { +void own_window_setting::lua_setter(lua::state &l, bool init) { + lua::stack_sentry s(l, -2); + + Base::lua_setter(l, init); + + if (init) { + if (do_convert(l, -1).first) { +#ifndef OWN_WINDOW + std::cerr << "Support for the own_window setting has been " + "disabled during compilation\n"; + l.pop(); + l.pushboolean(false); +#endif + } + + if (out_to_gui(l)) { +#ifdef BUILD_X11 + x11_init_window(l, do_convert(l, -1).first); +#endif /*BUILD_X11*/ + } else { + // own_window makes no sense when not drawing to X + l.pop(); + l.pushboolean(false); + } + } + + ++s; +} + +void colour_setting::lua_setter(lua::state &l, bool init) { + lua::stack_sentry s(l, -2); + Base::lua_setter(l, init); + ++s; +} +} // namespace priv + +template <> +conky::lua_traits::Map conky::lua_traits::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}}; + +#ifdef OWN_WINDOW +template <> +conky::lua_traits::Map conky::lua_traits::map = { + {"normal", TYPE_NORMAL}, + {"dock", TYPE_DOCK}, + {"panel", TYPE_PANEL}, + {"desktop", TYPE_DESKTOP}, + {"override", TYPE_OVERRIDE}}; + +template <> +conky::lua_traits::Map conky::lua_traits::map = { + {"undecorated", HINT_UNDECORATED}, + {"below", HINT_BELOW}, + {"above", HINT_ABOVE}, + {"sticky", HINT_STICKY}, + {"skip_taskbar", HINT_SKIP_TASKBAR}, + {"skip_pager", HINT_SKIP_PAGER}}; + +std::pair window_hints_traits::convert( + lua::state &l, int index, const std::string &name) { + lua::stack_sentry s(l); + l.checkstack(1); + + std::string hints = l.tostring(index); + // add a sentinel to simplify the following loop + hints += ','; + size_t pos = 0; + size_t newpos; + uint16_t ret = 0; + while ((newpos = hints.find_first_of(", ", pos)) != std::string::npos) { + if (newpos > pos) { + l.pushstring(hints.substr(pos, newpos - pos)); + auto t = conky::lua_traits::convert(l, -1, name); + if (!t.second) { return {0, false}; } + SET_HINT(ret, t.first); + l.pop(); + } + pos = newpos + 1; + } + return {ret, true}; +} +#endif + +#ifdef OWN_WINDOW +namespace { +// used to set the default value for own_window_title +std::string gethostnamecxx() { + update_uname(); + return info.uname_s.nodename; +} +} // namespace +#endif /* OWN_WINDOW */ + +/* + * The order of these settings cannot be completely arbitrary. Some of them + * depend on others, and the setters are called in the order in which they are + * defined. The order should be: x11_display_name -> out_to_x -> everything colour + * related + * -> border_*, own_window_*, etc -> own_window -> + * double_buffer -> imlib_cache_size + */ + +conky::simple_config_setting text_alignment("alignment", BOTTOM_LEFT, + false); +conky::simple_config_setting head_index("xinerama_head", 0, true); + +conky::simple_config_setting display_name("display", std::string(), + false); + +priv::colour_setting color[10] = {{"color0", 0xffffff}, {"color1", 0xffffff}, + {"color2", 0xffffff}, {"color3", 0xffffff}, + {"color4", 0xffffff}, {"color5", 0xffffff}, + {"color6", 0xffffff}, {"color7", 0xffffff}, + {"color8", 0xffffff}, {"color9", 0xffffff}}; +priv::colour_setting default_color("default_color", 0xffffff); +priv::colour_setting default_shade_color("default_shade_color", 0x000000); +priv::colour_setting default_outline_color("default_outline_color", 0x000000); + +conky::range_config_setting border_inner_margin( + "border_inner_margin", 0, std::numeric_limits::max(), 3, true); +conky::range_config_setting border_outer_margin( + "border_outer_margin", 0, std::numeric_limits::max(), 1, true); +conky::range_config_setting border_width("border_width", 0, + std::numeric_limits::max(), + 1, true); + +conky::simple_config_setting forced_redraw("forced_redraw", false, false); + +#ifdef OWN_WINDOW +conky::simple_config_setting set_transparent("own_window_transparent", + false, false); +conky::simple_config_setting own_window_class("own_window_class", + PACKAGE_NAME, false); + +conky::simple_config_setting own_window_title( + "own_window_title", PACKAGE_NAME " (" + gethostnamecxx() + ")", false); + +conky::simple_config_setting own_window_type("own_window_type", + TYPE_NORMAL, false); +conky::simple_config_setting own_window_hints( + "own_window_hints", 0, false); + +priv::colour_setting background_colour("own_window_colour", 0); + +#ifdef BUILD_ARGB +conky::simple_config_setting use_argb_visual("own_window_argb_visual", + false, false); +conky::range_config_setting own_window_argb_value("own_window_argb_value", + 0, 255, 255, false); +#endif /* BUILD_ARGB */ +#endif /* OWN_WINDOW */ +priv::own_window_setting own_window; + +#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 +/******************** ************************/ diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 00000000..aea307b2 --- /dev/null +++ b/src/gui.h @@ -0,0 +1,181 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Please see COPYING for details + * + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifdef BUILD_GUI +#ifndef GUI_H_ +#define GUI_H_ + +#include "colours.h" +#include "setting.hh" + +#ifdef OWN_WINDOW +enum window_type { + TYPE_NORMAL = 0, + TYPE_DOCK, + TYPE_PANEL, + TYPE_DESKTOP, + TYPE_OVERRIDE +}; + +enum window_hints { + HINT_UNDECORATED = 0, + HINT_BELOW, + HINT_ABOVE, + HINT_STICKY, + HINT_SKIP_TASKBAR, + HINT_SKIP_PAGER +}; +#endif /*OWN_WINDOW*/ + +#if defined(BUILD_ARGB) && defined(OWN_WINDOW) +/* true if use_argb_visual=true and argb visual was found*/ +extern bool have_argb_visual; +#endif + +#ifdef BUILD_X11 +extern Display *display; +#endif +extern int display_width; +extern int display_height; +extern int screen; +extern int workarea[4]; + +extern char window_created; + +void destroy_window(void); +void create_gc(void); +void set_struts(int); + +bool out_to_gui(lua::state &l); + +void print_monitor(struct text_object *, char *, unsigned int); +void print_monitor_number(struct text_object *, char *, unsigned int); +void print_desktop(struct text_object *, char *, unsigned int); +void print_desktop_number(struct text_object *, char *, unsigned int); +void print_desktop_name(struct text_object *, char *, unsigned int); + +/* Num lock, Scroll lock, Caps Lock */ +void print_key_num_lock(struct text_object *, char *, unsigned int); +void print_key_caps_lock(struct text_object *, char *, unsigned int); +void print_key_scroll_lock(struct text_object *, char *, unsigned int); + +/* Keyboard layout and mouse speed in percentage */ +void print_keyboard_layout(struct text_object *, char *, unsigned int); +void print_mouse_speed(struct text_object *, char *, unsigned int); + +#ifdef BUILD_XDBE +void xdbe_swap_buffers(void); +#else +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 text_alignment; + +namespace priv { +class own_window_setting : public conky::simple_config_setting { + typedef conky::simple_config_setting Base; + + protected: + virtual void lua_setter(lua::state &l, bool init); + + public: + own_window_setting() : Base("own_window", false, false) {} +}; + +struct colour_traits { + static const lua::Type type = lua::TSTRING; + typedef unsigned long Type; + + static inline std::pair convert(lua::state &l, int index, + const std::string &) { + return {get_x11_color(l.tostring(index)), true}; + } +}; + +class colour_setting + : public conky::simple_config_setting { + typedef conky::simple_config_setting Base; + + protected: + virtual void lua_setter(lua::state &l, bool init); + + public: + colour_setting(const std::string &name_, unsigned long default_value_ = 0) + : Base(name_, default_value_, true) {} +}; +} // namespace priv + +extern conky::simple_config_setting display_name; +extern conky::simple_config_setting head_index; +extern priv::colour_setting color[10]; +extern priv::colour_setting default_color; +extern priv::colour_setting default_shade_color; +extern priv::colour_setting default_outline_color; + +extern conky::range_config_setting border_inner_margin; +extern conky::range_config_setting border_outer_margin; +extern conky::range_config_setting border_width; + +extern conky::simple_config_setting forced_redraw; + +#ifdef OWN_WINDOW +extern conky::simple_config_setting set_transparent; +extern conky::simple_config_setting own_window_class; +extern conky::simple_config_setting own_window_title; +extern conky::simple_config_setting own_window_type; + +struct window_hints_traits { + static const lua::Type type = lua::TSTRING; + typedef uint16_t Type; + static std::pair convert(lua::state &l, int index, + const std::string &name); +}; +extern conky::simple_config_setting + own_window_hints; + +#ifdef BUILD_ARGB +extern conky::simple_config_setting use_argb_visual; + +/* range of 0-255 for alpha */ +extern conky::range_config_setting own_window_argb_value; +#endif /*BUILD_ARGB*/ +#endif /*OWN_WINDOW*/ +extern priv::own_window_setting own_window; + +#endif /*GUI_H_*/ +#endif /* BUILD_GUI */ diff --git a/src/llua.cc b/src/llua.cc index 93d264f4..404ecf22 100644 --- a/src/llua.cc +++ b/src/llua.cc @@ -27,6 +27,14 @@ #include "conky.h" #include "logging.h" +#ifdef BUILD_X11 +#include "x11.h" +#endif /* BUILD_X11 */ + +#ifdef BUILD_GUI +#include "gui.h" +#endif /* BUILD_GUI */ + extern "C" { #include } @@ -485,13 +493,20 @@ void llua_setup_window_table(int text_start_x, int text_start_y, int text_width, if (lua_L == nullptr) { return; } lua_newtable(lua_L); +#ifdef BUILD_X11 if (out_to_x.get(*state)) { llua_set_userdata("drawable", "Drawable", (void *)&window.drawable); llua_set_userdata("visual", "Visual", window.visual); llua_set_userdata("display", "Display", display); + } +#endif /*BUILD_X11*/ +#ifdef BUILD_GUI + if (out_to_gui(*state)) { +#ifdef BUILD_X11 llua_set_number("width", window.width); llua_set_number("height", window.height); +#endif /*BUILD_X11*/ llua_set_number("border_inner_margin", border_inner_margin.get(*state)); llua_set_number("border_outer_margin", border_outer_margin.get(*state)); llua_set_number("border_width", border_width.get(*state)); @@ -503,6 +518,7 @@ void llua_setup_window_table(int text_start_x, int text_start_y, int text_width, lua_setglobal(lua_L, "conky_window"); } +#endif /*BUILD_GUI*/ } void llua_update_window_table(int text_start_x, int text_start_y, @@ -516,8 +532,10 @@ void llua_update_window_table(int text_start_x, int text_start_y, return; } +#ifdef BUILD_X11 llua_set_number("width", window.width); llua_set_number("height", window.height); +#endif /*BUILD_X11*/ llua_set_number("text_start_x", text_start_x); llua_set_number("text_start_y", text_start_y); diff --git a/src/llua.h b/src/llua.h index 5f2ef2b3..fa8d1bd7 100644 --- a/src/llua.h +++ b/src/llua.h @@ -32,10 +32,6 @@ extern "C" { #include -#ifdef BUILD_X11 -#include "x11.h" -#endif /* BUILD_X11 */ - #define LUAPREFIX "conky_" #ifdef HAVE_SYS_INOTIFY_H diff --git a/src/scroll.cc b/src/scroll.cc index 92028d80..737947cc 100644 --- a/src/scroll.cc +++ b/src/scroll.cc @@ -33,7 +33,6 @@ #include "logging.h" #include "specials.h" #include "text_object.h" -#include "x11.h" /** * Length of a character in bytes. diff --git a/src/specials.cc b/src/specials.cc index 05c41b4c..b6c11c15 100644 --- a/src/specials.cc +++ b/src/specials.cc @@ -28,6 +28,7 @@ */ #include "conky.h" #ifdef BUILD_GUI +#include "gui.h" #include "fonts.h" #endif /* BUILD_GUI */ #include @@ -389,7 +390,7 @@ void new_gauge_in_shell(struct text_object *obj, char *p, } #ifdef BUILD_GUI -void new_gauge_in_x11(struct text_object *obj, char *buf, double usage) { +void new_gauge_in_gui(struct text_object *obj, char *buf, double usage) { struct special_t *s = nullptr; auto *g = static_cast(obj->special_data); @@ -420,7 +421,7 @@ void new_gauge(struct text_object *obj, char *p, unsigned int p_max_size, #ifdef BUILD_GUI if (display_output() && display_output()->graphical()) { - new_gauge_in_x11(obj, p, usage); + new_gauge_in_gui(obj, p, usage); } if (out_to_stdout.get(*state)) { new_gauge_in_shell(obj, p, p_max_size, usage); @@ -705,7 +706,7 @@ static void new_bar_in_shell(struct text_object *obj, char *buffer, } #ifdef BUILD_GUI -static void new_bar_in_x11(struct text_object *obj, char *buf, double usage) { +static void new_bar_in_gui(struct text_object *obj, char *buf, double usage) { struct special_t *s = nullptr; auto *b = static_cast(obj->special_data); @@ -737,7 +738,7 @@ void new_bar(struct text_object *obj, char *p, unsigned int p_max_size, #ifdef BUILD_GUI if (display_output() && display_output()->graphical()) { - new_bar_in_x11(obj, p, usage); + new_bar_in_gui(obj, p, usage); } if (out_to_stdout.get(*state)) { new_bar_in_shell(obj, p, p_max_size, usage); diff --git a/src/wl.cc b/src/wl.cc new file mode 100644 index 00000000..0cd61d90 --- /dev/null +++ b/src/wl.cc @@ -0,0 +1,118 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include +#include + +#include "conky.h" +#include "wl.h" + +#ifdef BUILD_WAYLAND + +namespace priv { +void out_to_wayland_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 + } + + ++s; +} + +void out_to_wayland_setting::cleanup(lua::state &l) { + lua::stack_sentry s(l, -1); + + if (do_convert(l, -1).first) { + //deinit + } + + l.pop(); +} +} // namespace priv + +priv::out_to_wayland_setting out_to_wayland; + +static const char NOT_IN_WAYLAND[] = "Not running in Wayland"; + +void print_monitor(struct text_object *obj, char *p, unsigned int p_max_size) { + (void)obj; + + if (!out_to_wayland.get(*state)) { + strncpy(p, NOT_IN_WAYLAND, p_max_size); + return; + } + snprintf(p, p_max_size, "%d", -1); +} + +void print_monitor_number(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + + if (!out_to_wayland.get(*state)) { + strncpy(p, NOT_IN_WAYLAND, p_max_size); + return; + } + snprintf(p, p_max_size, "%d", -1); +} + +void print_desktop(struct text_object *obj, char *p, unsigned int p_max_size) { + (void)obj; + + if (!out_to_wayland.get(*state)) { + strncpy(p, NOT_IN_WAYLAND, p_max_size); + return; + } + snprintf(p, p_max_size, "%d", -1); +} + +void print_desktop_number(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + + if (!out_to_wayland.get(*state)) { + strncpy(p, NOT_IN_WAYLAND, p_max_size); + return; + } + snprintf(p, p_max_size, "%d", -1); +} + +void print_desktop_name(struct text_object *obj, char *p, + unsigned int p_max_size) { + (void)obj; + + if (!out_to_wayland.get(*state)) { + strncpy(p, NOT_IN_WAYLAND, p_max_size); + } else { + strncpy(p, "NYI", p_max_size); + } +} +#endif diff --git a/src/wl.h b/src/wl.h new file mode 100644 index 00000000..af1f4754 --- /dev/null +++ b/src/wl.h @@ -0,0 +1,52 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2021 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#if defined(BUILD_WAYLAND) && !defined(CONKY_WL_H) +#define CONKY_WL_H + +#include + +#include "setting.hh" + +namespace priv { +class out_to_wayland_setting : public conky::simple_config_setting { + typedef conky::simple_config_setting Base; + + protected: + virtual void lua_setter(lua::state &l, bool init); + virtual void cleanup(lua::state &l); + + public: + out_to_wayland_setting() : Base("out_to_wayland", false, false) {} +}; +} // namespace priv + +extern priv::out_to_wayland_setting out_to_wayland; + +#endif /* CONKY_WL_H */ diff --git a/src/x11.cc b/src/x11.cc index b8cd4cbb..822ac760 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -58,22 +58,11 @@ #include #endif /* BUILD_XSHAPE */ -#ifdef BUILD_ARGB -bool have_argb_visual; -#endif /* BUILD_ARGB */ - /* some basic X11 stuff */ Display *display = nullptr; -int display_width; -int display_height; -int screen; - -/* workarea from _NET_WORKAREA, this is where window / text is aligned */ -int workarea[4]; /* Window stuff */ -struct conky_window window; -char window_created = 0; +struct conky_x11_window window; /* local prototypes */ static void update_workarea(); @@ -81,7 +70,6 @@ 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(); static void deinit_X11(); -static void init_window(lua::state &l, bool own); /********************* ************************/ namespace priv { @@ -103,33 +91,6 @@ void out_to_x_setting::cleanup(lua::state &l) { l.pop(); } -void own_window_setting::lua_setter(lua::state &l, bool init) { - lua::stack_sentry s(l, -2); - - Base::lua_setter(l, init); - - if (init) { - if (do_convert(l, -1).first) { -#ifndef OWN_WINDOW - std::cerr << "Support for the own_window setting has been " - "disabled during compilation\n"; - l.pop(); - l.pushboolean(false); -#endif - } - - if (out_to_x.get(l)) { - init_window(l, do_convert(l, -1).first); - } else { - // own_window makes no sense when not drawing to X - l.pop(); - l.pushboolean(false); - } - } - - ++s; -} - #ifdef BUILD_XDBE bool use_xdbe_setting::set_up(lua::state &l) { // double_buffer makes no sense when not drawing to X @@ -210,19 +171,6 @@ void use_xpmdb_setting::lua_setter(lua::state &l, bool init) { ++s; } #endif - -void colour_setting::lua_setter(lua::state &l, bool init) { - lua::stack_sentry s(l, -2); - - if (!out_to_x.get(l)) { - // ignore if we're not using X - l.replace(-2); - } else { - Base::lua_setter(l, init); - } - - ++s; -} } // namespace priv template <> @@ -300,38 +248,9 @@ std::string gethostnamecxx() { } // namespace #endif /* OWN_WINDOW */ -/* - * The order of these settings cannot be completely arbitrary. Some of them - * depend on others, and the setters are called in the order in which they are - * defined. The order should be: display_name -> out_to_x -> everything colour - * related - * -> border_*, own_window_*, etc -> own_window -> - * double_buffer -> imlib_cache_size - */ - -conky::simple_config_setting text_alignment("alignment", BOTTOM_LEFT, - false); -conky::simple_config_setting display_name("display", std::string(), - false); conky::simple_config_setting head_index("xinerama_head", 0, true); priv::out_to_x_setting out_to_x; -priv::colour_setting color[10] = {{"color0", 0xffffff}, {"color1", 0xffffff}, - {"color2", 0xffffff}, {"color3", 0xffffff}, - {"color4", 0xffffff}, {"color5", 0xffffff}, - {"color6", 0xffffff}, {"color7", 0xffffff}, - {"color8", 0xffffff}, {"color9", 0xffffff}}; -priv::colour_setting default_color("default_color", 0xffffff); -priv::colour_setting default_shade_color("default_shade_color", 0x000000); -priv::colour_setting default_outline_color("default_outline_color", 0x000000); - -conky::range_config_setting border_inner_margin( - "border_inner_margin", 0, std::numeric_limits::max(), 3, true); -conky::range_config_setting border_outer_margin( - "border_outer_margin", 0, std::numeric_limits::max(), 1, true); -conky::range_config_setting border_width("border_width", 0, - std::numeric_limits::max(), - 1, true); #ifdef BUILD_XFT conky::simple_config_setting use_xft("use_xft", false, false); #endif @@ -339,21 +258,11 @@ conky::simple_config_setting use_xft("use_xft", false, false); conky::simple_config_setting forced_redraw("forced_redraw", false, false); #ifdef OWN_WINDOW -conky::simple_config_setting set_transparent("own_window_transparent", - false, false); -conky::simple_config_setting own_window_class("own_window_class", - PACKAGE_NAME, false); - -conky::simple_config_setting own_window_title( - "own_window_title", PACKAGE_NAME " (" + gethostnamecxx() + ")", false); - -conky::simple_config_setting own_window_type("own_window_type", - TYPE_NORMAL, false); -conky::simple_config_setting own_window_hints( +conky::simple_config_setting own_window_x11_type("own_window_type", + TYPE_NORMAL, false); +conky::simple_config_setting own_window_x11_hints( "own_window_hints", 0, false); -priv::colour_setting background_colour("own_window_colour", 0); - #ifdef BUILD_ARGB conky::simple_config_setting use_argb_visual("own_window_argb_visual", false, false); @@ -361,7 +270,6 @@ conky::range_config_setting own_window_argb_value("own_window_argb_value", 0, 255, 255, false); #endif /* BUILD_ARGB */ #endif /* OWN_WINDOW */ -priv::own_window_setting own_window; #ifdef BUILD_XDBE priv::use_xdbe_setting use_xdbe; @@ -636,10 +544,10 @@ void destroy_window() { if (window.xftdraw != nullptr) { XftDrawDestroy(window.xftdraw); } #endif /* BUILD_XFT */ if (window.gc != nullptr) { XFreeGC(display, window.gc); } - memset(&window, 0, sizeof(struct conky_window)); + memset(&window, 0, sizeof(struct conky_x11_window)); } -static void init_window(lua::state &l __attribute__((unused)), bool own) { +void x11_init_window(lua::state &l __attribute__((unused)), bool own) { DBGP("enter init_window()"); // own is unused if OWN_WINDOW is not defined (void)own; diff --git a/src/x11.h b/src/x11.h index 598c89bd..76b07ba8 100644 --- a/src/x11.h +++ b/src/x11.h @@ -66,7 +66,9 @@ enum window_hints { #define TEST_HINT(mask, hint) (mask & (1 << (hint))) #endif -struct conky_window { +extern Display *display; + +struct conky_x11_window { Window root, window, desktop; Drawable drawable; Visual *visual; @@ -75,12 +77,12 @@ struct conky_window { #ifdef BUILD_XDBE XdbeBackBuffer back_buffer; -#else +#else /*BUILD_XDBE*/ Pixmap back_buffer; -#endif +#endif /*BUILD_XDBE*/ #ifdef BUILD_XFT XftDraw *xftdraw; -#endif +#endif /*BUILD_XFT*/ int width; int height; @@ -90,41 +92,14 @@ struct conky_window { #endif }; -#if defined(BUILD_ARGB) && defined(OWN_WINDOW) -/* true if use_argb_visual=true and argb visual was found*/ -extern bool have_argb_visual; -#endif - -extern Display *display; -extern int display_width; -extern int display_height; -extern int screen; - -extern int workarea[4]; - -extern struct conky_window window; -extern char window_created; +extern struct conky_x11_window window; void destroy_window(void); void create_gc(void); void set_transparent_background(Window win); void get_x11_desktop_info(Display *current_display, Atom atom); void set_struts(int); - -void print_monitor(struct text_object *, char *, unsigned int); -void print_monitor_number(struct text_object *, char *, unsigned int); -void print_desktop(struct text_object *, char *, unsigned int); -void print_desktop_number(struct text_object *, char *, unsigned int); -void print_desktop_name(struct text_object *, char *, unsigned int); - -/* Num lock, Scroll lock, Caps Lock */ -void print_key_num_lock(struct text_object *, char *, unsigned int); -void print_key_caps_lock(struct text_object *, char *, unsigned int); -void print_key_scroll_lock(struct text_object *, char *, unsigned int); - -/* Keyboard layout and mouse speed in percentage */ -void print_keyboard_layout(struct text_object *, char *, unsigned int); -void print_mouse_speed(struct text_object *, char *, unsigned int); +void x11_init_window(lua::state &l, bool own); #ifdef BUILD_XDBE void xdbe_swap_buffers(void); @@ -132,22 +107,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 text_alignment; - namespace priv { class out_to_x_setting : public conky::simple_config_setting { typedef conky::simple_config_setting Base; @@ -160,16 +119,6 @@ class out_to_x_setting : public conky::simple_config_setting { out_to_x_setting() : Base("out_to_x", true, false) {} }; -class own_window_setting : public conky::simple_config_setting { - typedef conky::simple_config_setting Base; - - protected: - virtual void lua_setter(lua::state &l, bool init); - - public: - own_window_setting() : Base("own_window", false, false) {} -}; - #ifdef BUILD_XDBE class use_xdbe_setting : public conky::simple_config_setting { typedef conky::simple_config_setting Base; @@ -196,72 +145,14 @@ class use_xpmdb_setting : public conky::simple_config_setting { use_xpmdb_setting() : Base("double_buffer", false, false) {} }; #endif - -struct colour_traits { - static const lua::Type type = lua::TSTRING; - typedef unsigned long Type; - - static inline std::pair convert(lua::state &l, int index, - const std::string &) { - return {get_x11_color(l.tostring(index)), true}; - } -}; - -class colour_setting - : public conky::simple_config_setting { - typedef conky::simple_config_setting Base; - - protected: - virtual void lua_setter(lua::state &l, bool init); - - public: - colour_setting(const std::string &name_, unsigned long default_value_ = 0) - : Base(name_, default_value_, true) {} -}; -} // namespace priv +} /* namespace priv */ extern priv::out_to_x_setting out_to_x; -extern conky::simple_config_setting display_name; -extern conky::simple_config_setting head_index; -extern priv::colour_setting color[10]; -extern priv::colour_setting default_color; -extern priv::colour_setting default_shade_color; -extern priv::colour_setting default_outline_color; - -extern conky::range_config_setting border_inner_margin; -extern conky::range_config_setting border_outer_margin; -extern conky::range_config_setting border_width; - -extern conky::simple_config_setting forced_redraw; #ifdef BUILD_XFT extern conky::simple_config_setting use_xft; #endif -#ifdef OWN_WINDOW -extern conky::simple_config_setting set_transparent; -extern conky::simple_config_setting own_window_class; -extern conky::simple_config_setting own_window_title; -extern conky::simple_config_setting own_window_type; - -struct window_hints_traits { - static const lua::Type type = lua::TSTRING; - typedef uint16_t Type; - static std::pair convert(lua::state &l, int index, - const std::string &name); -}; -extern conky::simple_config_setting - own_window_hints; - -#ifdef BUILD_ARGB -extern conky::simple_config_setting use_argb_visual; - -/* range of 0-255 for alpha */ -extern conky::range_config_setting own_window_argb_value; -#endif -#endif /*OWN_WINDOW*/ -extern priv::own_window_setting own_window; - #ifdef BUILD_XDBE extern priv::use_xdbe_setting use_xdbe; #else