diff --git a/.github/workflows/build-and-test-linux.yaml b/.github/workflows/build-and-test-linux.yaml index 80ab9385..cceab9c0 100644 --- a/.github/workflows/build-and-test-linux.yaml +++ b/.github/workflows/build-and-test-linux.yaml @@ -11,6 +11,7 @@ jobs: - ubuntu-20.04 - ubuntu-22.04 x11: [ON, OFF] + wayland: [ON, OFF] compiler: - clang - gcc @@ -74,6 +75,8 @@ jobs: libpulse-dev \ librsvg2-dev \ libsystemd-dev \ + libwayland-bin \ + libwayland-dev \ libx11-dev \ libxdamage-dev \ libxext-dev \ @@ -82,7 +85,8 @@ jobs: libxml2-dev \ libxmmsclient-dev \ libxnvctrl-dev \ - ncurses-dev + ncurses-dev \ + wayland-protocols - name: Install libc++ if: matrix.compiler == 'clang' run: | @@ -125,6 +129,7 @@ jobs: -DBUILD_RSS=ON \ -DBUILD_TESTS=ON \ -DBUILD_WLAN=ON \ + -DBUILD_WAYLAND=${{ matrix.wayland }}\ -DBUILD_X11=${{ matrix.x11 }} \ -DBUILD_XMMS2=ON \ -DCMAKE_C_COMPILER=$CC \ diff --git a/.github/workflows/build-and-test-macos.yaml b/.github/workflows/build-and-test-macos.yaml index f90f928a..933cbd67 100644 --- a/.github/workflows/build-and-test-macos.yaml +++ b/.github/workflows/build-and-test-macos.yaml @@ -32,6 +32,7 @@ jobs: cd build cmake .. \ -DMAINTAINER_MODE=ON \ + -DBUILD_WAYLAND=OFF \ -DBUILD_TESTS=ON - name: Compile working-directory: build diff --git a/.github/workflows/publish-appimage.yml b/.github/workflows/publish-appimage.yml index b4371c99..d3606189 100644 --- a/.github/workflows/publish-appimage.yml +++ b/.github/workflows/publish-appimage.yml @@ -41,6 +41,7 @@ jobs: libpulse-dev \ librsvg2-dev \ libsystemd-dev \ + libwayland-dev \ libx11-dev \ libxdamage-dev \ libxext-dev \ 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..cb96e5a5 100644 --- a/cmake/ConkyPlatformChecks.cmake +++ b/cmake/ConkyPlatformChecks.cmake @@ -352,6 +352,37 @@ 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) + # 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}) + + pkg_check_modules(PANGOFT2 pangoft2) + set(conky_libs ${conky_libs} ${PANGOFT2_LIBRARIES}) + set(conky_includes ${conky_includes} ${PANGOFT2_INCLUDE_DIRS}) +endif(BUILD_WAYLAND) + # Otherwise, use the most recent Lua version pkg_search_module(LUA REQUIRED @@ -454,6 +485,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..9a664236 --- /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 +) 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/doc/config_settings.yaml b/doc/config_settings.yaml index 0c9cc4f4..ca3ffa1e 100644 --- a/doc/config_settings.yaml +++ b/doc/config_settings.yaml @@ -344,6 +344,10 @@ values: will provide more useful things). - name: out_to_stderr desc: Print text to stderr. + - name: out_to_wayland + desc: |- + Open a Wayland window to display output. + default: no - name: out_to_x desc: |- When set to no, there will be no output in X (useful when diff --git a/extras/convert.lua b/extras/convert.lua index 14d01a7a..92f9d56c 100755 --- a/extras/convert.lua +++ b/extras/convert.lua @@ -36,6 +36,7 @@ local bool_setting = { background = true, disable_auto_reload = true, double_buffer = true, draw_borders = true, draw_graph_borders = true, draw_outline = true, draw_shades = true, extra_newline = true, format_human_readable = true, no_buffers = true, out_to_console = true, + out_to_wayland = true, out_to_ncurses = true, out_to_stderr = true, out_to_x = true, override_utf8_locale = true, own_window = true, own_window_argb_visual = true, own_window_transparent = true, short_units = true, show_graph_range = true, show_graph_scale = true, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4544b48f..8252264f 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,32 @@ if(BUILD_X11) endif(BUILD_XINERAMA) endif(BUILD_X11) +if(BUILD_WAYLAND) + set(wl_srcs wl.cc wl.h xdg-shell-protocol.c wlr-layer-shell-protocol.c x11-color.cc x11-color.h) + set(optional_sources ${optional_sources} ${wl_srcs}) + # generate protocol implementations + 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) + + set(WLR_LAYER_SHELL_PROT_DEF "${CMAKE_CURRENT_SOURCE_DIR}/wlr-layer-shell-unstable-v1.xml") + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/wlr-layer-shell-client-protocol.h + COMMAND ${WAYLAND_SCANNER} client-header ${WLR_LAYER_SHELL_PROT_DEF} wlr-layer-shell-client-protocol.h) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/wlr-layer-shell-protocol.c + COMMAND ${WAYLAND_SCANNER} private-code ${WLR_LAYER_SHELL_PROT_DEF} wlr-layer-shell-protocol.c + DEPENDS wlr-layer-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..dbff6491 100644 --- a/src/colours.cc +++ b/src/colours.cc @@ -28,9 +28,13 @@ */ #include "conky.h" #include "logging.h" +#include "gui.h" #ifdef BUILD_X11 #include "x11.h" -#endif +#endif /*BUILD_X11*/ +#ifdef BUILD_WAYLAND +#include "x11-color.h" +#endif /*BUILD_WAYLAND*/ /* precalculated: 31/255, and 63/255 */ #define CONST_8_TO_5_BITS 0.12156862745098 @@ -83,8 +87,61 @@ unsigned int adjust_colours(unsigned int colour) { return colour; } -#ifdef BUILD_X11 + +#ifdef BUILD_GUI +#ifdef BUILD_WAYLAND +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; +} + +long manually_get_x11_color(const char *name) { + unsigned short r, g, b; + size_t len = strlen(name); + if (OsLookupColor(-1, name, len, &r, &g, &b)) { + return 0x000000ff | ((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8); + } + if (name[0] == '#') { + name++; + len--; + } + 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' (%d)", name, len); + return 0xFF00FF; +} +#endif /* BUILD_WAYLAND */ + long get_x11_color(const char *name) { +#ifdef BUILD_X11 +#ifdef BUILD_WAYLAND + if (!display) { + return manually_get_x11_color(name); + } +#endif /*BUILD_WAYLAND*/ + assert(display != nullptr); XColor color; color.pixel = 0; @@ -108,9 +165,13 @@ long get_x11_color(const char *name) { } return static_cast(color.pixel); +#endif /*BUILD_X11*/ +#ifdef BUILD_WAYLAND + return manually_get_x11_color(name); +#endif /*BUILD_WAYLAND*/ } 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..7419d8ab 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 @@ -760,10 +764,13 @@ int get_border_total() { dpi_scale(border_width.get(*state)); } +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; - int idx = 1; int width = 0; long i; @@ -776,16 +783,16 @@ static int get_string_width_special(char *s, int special_index) { p = strndup(s, text_buffer_size.get(*state)); final = p; - for (i = 0; i < special_index; i++) { current = current->next; } - for (i = 0; i < idx; i++) { current = current->next; } + for (i = 0; i <= special_index; i++) { current = current->next; } while (*p != 0) { if (*p == SPECIAL_CHAR) { /* shift everything over by 1 so that the special char * doesn't mess up the size calculation */ - for (i = 0; i < static_cast(strlen(p)); i++) { + remove_first_char(p); + /*for (i = 0; i < static_cast(strlen(p)); i++) { *(p + i) = *(p + i + 1); - } + }*/ if (current->type == GRAPH || current->type == GAUGE || current->type == BAR) { width += current->width; @@ -795,6 +802,8 @@ static int get_string_width_special(char *s, int special_index) { // influenced_by_font but do not include specials char *influenced_by_font = strdup(p); special_t *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 @@ -803,10 +812,7 @@ static int get_string_width_special(char *s, int special_index) { influenced_by_font[i] = 0; break; } - { - memmove(&influenced_by_font[i], &influenced_by_font[i + 1], - strlen(&influenced_by_font[i + 1]) + 1); - } + remove_first_char(&influenced_by_font[i]); } } // add the length of influenced_by_font in the new font to width @@ -815,20 +821,19 @@ static int get_string_width_special(char *s, int special_index) { width += calc_text_width(influenced_by_font); selected_font = orig_font; free(influenced_by_font); - // make sure there chars counted in the new font are not again counted + // make sure the chars counted in the new font are not again counted // in the old font int specials_skipped = 0; while (i > 0) { - if (p[specials_skipped] != 1) { - memmove(&p[specials_skipped], &p[specials_skipped + 1], - strlen(&p[specials_skipped + 1]) + 1); + if (p[specials_skipped] != SPECIAL_CHAR) { + remove_first_char(&p[specials_skipped]); + // i only counts non-special chars, so only decrement it for those + i--; } else { specials_skipped++; } - i--; } } - idx++; current = current->next; } else { p++; @@ -1480,9 +1485,7 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) { cur_x, get_string_width_special(s), gap_x, current->arg, window.border_inner_margin, window.border_width); */ - if (pos_x > current->arg && pos_x > cur_x) { - cur_x = pos_x - current->arg; - } + cur_x = pos_x - current->arg; break; } @@ -1555,7 +1558,8 @@ static void draw_text() { for (auto output : display_outputs()) output->begin_draw_text(); #ifdef BUILD_GUI // XXX:only works if inside set_display_output() - if (display_output() && display_output()->graphical()) { + for (auto output : display_outputs()) { + if (output && output->graphical()) { cur_y = text_start_y; int bw = dpi_scale(border_width.get(*state)); @@ -1564,14 +1568,14 @@ static void draw_text() { if (stippled_borders.get(*state) != 0) { char ss[2] = {(char)dpi_scale(stippled_borders.get(*state)), (char)dpi_scale(stippled_borders.get(*state))}; - display_output()->set_line_style(bw, false); - display_output()->set_dashes(ss); + output->set_line_style(bw, false); + output->set_dashes(ss); } else { - display_output()->set_line_style(bw, true); + output->set_line_style(bw, true); } int offset = dpi_scale(border_inner_margin.get(*state)) + bw; - display_output()->draw_rect(text_offset_x + text_start_x - offset, + output->draw_rect(text_offset_x + text_start_x - offset, text_offset_y + text_start_y - offset, text_width + 2 * offset, text_height + 2 * offset); @@ -1579,6 +1583,7 @@ static void draw_text() { /* draw text */ } + } setup_fonts(); #endif /* BUILD_GUI */ for_each_line(text_buffer, draw_line); @@ -1930,11 +1935,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..47e2a326 --- /dev/null +++ b/src/display-wayland.cc @@ -0,0 +1,1197 @@ +/* + * + * 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 +#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 + +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* 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 zwlr_layer_surface_v1 *layer_surface; + int scale; + 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_surface *surface; + struct wl_seat *seat; +/* struct wl_pointer *pointer;*/ + struct wl_output *output; + struct xdg_wm_base *shell; + struct zwlr_layer_shell_v1 *layer_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, +}; + + +static void +output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, + int32_t physical_width, int32_t physical_height, + int32_t subpixel, const char *make, const char *model, + int32_t transform) +{} + +static void +output_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) +{} + +#ifdef WL_OUTPUT_DONE_SINCE_VERSION +static void +output_done(void *data, struct wl_output *wl_output) +{} +#endif + +#ifdef WL_OUTPUT_SCALE_SINCE_VERSION +void +output_scale(void *data, struct wl_output *wl_output, int32_t factor) +{ + /* For now, assume we have one output and adopt its scale unconditionally. */ + /* We should also re-render immediately when scale changes. */ + global_window->scale = factor; +} +#endif + +#ifdef WL_OUTPUT_NAME_SINCE_VERSION +static void +output_name(void *data, struct wl_output *wl_output, const char *name) +{} +#endif + +#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION +static void +output_description(void *data, struct wl_output *wl_output, + const char *description) +{} +#endif + +const struct wl_output_listener output_listener = { + /*.geometry =*/ output_geometry, + /*.mode =*/ output_mode, + #ifdef WL_OUTPUT_DONE_SINCE_VERSION + /*.done =*/ output_done, + #endif + #ifdef WL_OUTPUT_SCALE_SINCE_VERSION + /*.scale =*/ &output_scale, + #endif + #ifdef WL_OUTPUT_NAME_SINCE_VERSION + /*.name =*/ &output_name, + #endif + #ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION + /*.description =*/ &output_description, + #endif +}; + +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, 2)); + wl_output_add_listener(wl_globals.output, &output_listener, nullptr); + } 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); + } else if(strcmp(interface, "zwlr_layer_shell_v1") == 0) { + wl_globals.layer_shell = static_cast(wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1)); + } +} + +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 +layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *layer_surface, + uint32_t serial, uint32_t width, uint32_t height) +{ + zwlr_layer_surface_v1_ack_configure(layer_surface, serial); +} + +static void +layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *layer_surface) +{ +} + +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + /*.configure =*/ &layer_surface_configure, + /*.closed =*/ &layer_surface_closed, +}; + +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_allocate_buffer(struct window *window); + +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); + +void window_layer_surface_set_size(struct window *window) { + zwlr_layer_surface_v1_set_size(global_window->layer_surface, global_window->rectangle.width, global_window->rectangle.height); +} + +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->scale = 1; + window_allocate_buffer(global_window); + + global_window->layer_surface = zwlr_layer_shell_v1_get_layer_surface(wl_globals.layer_shell, + global_window->surface, nullptr, ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "conky_namespace"); + window_layer_surface_set_size(global_window); + zwlr_layer_surface_v1_add_listener(global_window->layer_surface, &layer_surface_listener, nullptr); + + wl_surface_set_buffer_scale(global_window->surface, global_window->scale); + 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_read_events(global_display); + + 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)) { + + /* clamp text_width to configured maximum */ + if (maximum_width.get(*state)) { + int mw = global_window->scale * maximum_width.get(*state); + if (text_width > mw && mw > 0) { text_width = mw; } + } + + 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 anchor = -1; + + 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; + break; + case TOP_RIGHT: + anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + break; + case TOP_MIDDLE: { + anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + 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? */; + } + + if (anchor != -1) { + zwlr_layer_surface_v1_set_anchor(global_window->layer_surface, anchor); + zwlr_layer_surface_v1_set_margin(global_window->layer_surface, gap_y.get(*state), gap_x.get(*state), gap_y.get(*state), gap_x.get(*state)); + } + } + + 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 +stride_for_shm_surface(struct rectangle *rect, int scale) { + return cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, rect->width * scale); +} + +static int +data_length_for_shm_surface(struct rectangle *rect, int scale) { + int stride; + + stride = stride_for_shm_surface(rect, scale); + return stride * rect->height * scale; +} + +static cairo_surface_t * +create_shm_surface_from_pool(void *none, + struct rectangle *rectangle, + struct shm_pool *pool, + int scale) +{ + 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 = stride_for_shm_surface (rectangle, scale); + length = data_length_for_shm_surface(rectangle, scale); + 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 * scale, + rectangle->height * scale, + 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 * scale, + rectangle->height * scale, + 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, window->scale)); + if (!pool) { + fprintf(stderr, "could not allocate shm pool\n"); + return; + } + + window->cairo_surface = + create_shm_surface_from_pool(window->shm, &window->rectangle, pool, window->scale); + cairo_surface_set_device_scale(window->cairo_surface, window->scale, window->scale); + + 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->scale = 1; + + window->surface = surface; + window->shm = shm; + + window->cairo_surface = nullptr; + window->cr = nullptr; + window->layout = nullptr; + window->pango_context = nullptr; + + 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) { + window_free_buffer(window); + zwlr_layer_surface_v1_destroy(window->layer_surface); + wl_surface_attach(window->surface, nullptr, 0, 0); + wl_surface_commit(window->surface); + wl_display_roundtrip(global_display); + wl_surface_destroy(window->surface); + wl_shm_destroy(window->shm); + delete window; +} + +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); + window_layer_surface_set_size(window); +} + +void +window_commit_buffer(struct window *window) { + assert(window->cairo_surface != nullptr); + wl_surface_set_buffer_scale(global_window->surface, global_window->scale); + 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/display-x11.cc b/src/display-x11.cc index 001ee003..a01edf5d 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -51,6 +51,7 @@ #include "display-x11.hh" #include "llua.h" #include "x11.h" +#include "gui.h" #ifdef BUILD_X11 #include "fonts.h" #endif @@ -139,6 +140,9 @@ struct _x11_stuff_s { } x11_stuff; static void X11_create_window() { + if (!window.window) { + return; + } setup_fonts(); load_fonts(utf8_mode.get(*state)); #ifdef BUILD_XFT @@ -221,6 +225,8 @@ bool display_output_x11::shutdown() { return false; } bool display_output_x11::main_loop_wait(double t) { /* wait for X event or timeout */ + if(!display || !window.gc) + return true; if (XPending(display) == 0) { fd_set fdsr; 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..c271f093 --- /dev/null +++ b/src/gui.cc @@ -0,0 +1,245 @@ +/* + * + * 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 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); + +#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); + +#ifdef BUILD_ARGB +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; + +/******************** ************************/ diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 00000000..7c71b14a --- /dev/null +++ b/src/gui.h @@ -0,0 +1,167 @@ +/* + * + * 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_ + +#ifdef BUILD_X11 +#include "x11.h" +#endif /*BUILD_X11*/ + +#include "colours.h" +#include "setting.hh" + +#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 priv::colour_setting background_colour; +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/imlib2.cc b/src/imlib2.cc index 5a89b59a..2ede76b4 100644 --- a/src/imlib2.cc +++ b/src/imlib2.cc @@ -70,6 +70,9 @@ void imlib_cache_size_setting::lua_setter(lua::state &l, bool init) { Base::lua_setter(l, init); + if (display == nullptr || window.visual == nullptr) + return; + if (init && out_to_x.get(l)) { image_list_start = image_list_end = nullptr; context = imlib_context_new(); 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..1f4c5615 --- /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"; + +__attribute__((weak)) 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); +} + +__attribute__((weak)) 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); +} + +__attribute__((weak)) 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); +} + +__attribute__((weak)) 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); +} + +__attribute__((weak)) 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/wlr-layer-shell-unstable-v1.xml b/src/wlr-layer-shell-unstable-v1.xml new file mode 100644 index 00000000..d8a8029a --- /dev/null +++ b/src/wlr-layer-shell-unstable-v1.xml @@ -0,0 +1,390 @@ + + + + Copyright © 2017 Drew DeVault + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + Clients can use this interface to assign the surface_layer role to + wl_surfaces. Such surfaces are assigned to a "layer" of the output and + rendered with a defined z-depth respective to each other. They may also be + anchored to the edges and corners of a screen and specify input handling + semantics. This interface should be suitable for the implementation of + many desktop shell components, and a broad number of other applications + that interact with the desktop. + + + + + Create a layer surface for an existing surface. This assigns the role of + layer_surface, or raises a protocol error if another role is already + assigned. + + Creating a layer surface from a wl_surface which has a buffer attached + or committed is a client error, and any attempts by a client to attach + or manipulate a buffer prior to the first layer_surface.configure call + must also be treated as errors. + + After creating a layer_surface object and setting it up, the client + must perform an initial commit without any buffer attached. + The compositor will reply with a layer_surface.configure event. + The client must acknowledge it and is then allowed to attach a buffer + to map the surface. + + You may pass NULL for output to allow the compositor to decide which + output to use. Generally this will be the one that the user most + recently interacted with. + + Clients can specify a namespace that defines the purpose of the layer + surface. + + + + + + + + + + + + + + + + + These values indicate which layers a surface can be rendered in. They + are ordered by z depth, bottom-most first. Traditional shell surfaces + will typically be rendered between the bottom and top layers. + Fullscreen shell surfaces are typically rendered at the top layer. + Multiple surfaces can share a single layer, and ordering within a + single layer is undefined. + + + + + + + + + + + + + This request indicates that the client will not use the layer_shell + object any more. Objects that have been created through this instance + are not affected. + + + + + + + An interface that may be implemented by a wl_surface, for surfaces that + are designed to be rendered as a layer of a stacked desktop-like + environment. + + Layer surface state (layer, size, anchor, exclusive zone, + margin, interactivity) is double-buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + + Attaching a null buffer to a layer surface unmaps it. + + Unmapping a layer_surface means that the surface cannot be shown by the + compositor until it is explicitly mapped again. The layer_surface + returns to the state it had right after layer_shell.get_layer_surface. + The client can re-map the surface by performing a commit without any + buffer attached, waiting for a configure event and handling it as usual. + + + + + Sets the size of the surface in surface-local coordinates. The + compositor will display the surface centered with respect to its + anchors. + + If you pass 0 for either value, the compositor will assign it and + inform you of the assignment in the configure event. You must set your + anchor to opposite edges in the dimensions you omit; not doing so is a + protocol error. Both values are 0 by default. + + Size is double-buffered, see wl_surface.commit. + + + + + + + + Requests that the compositor anchor the surface to the specified edges + and corners. If two orthogonal edges are specified (e.g. 'top' and + 'left'), then the anchor point will be the intersection of the edges + (e.g. the top left corner of the output); otherwise the anchor point + will be centered on that edge, or in the center if none is specified. + + Anchor is double-buffered, see wl_surface.commit. + + + + + + + Requests that the compositor avoids occluding an area with other + surfaces. The compositor's use of this information is + implementation-dependent - do not assume that this region will not + actually be occluded. + + A positive value is only meaningful if the surface is anchored to one + edge or an edge and both perpendicular edges. If the surface is not + anchored, anchored to only two perpendicular edges (a corner), anchored + to only two parallel edges or anchored to all edges, a positive value + will be treated the same as zero. + + A positive zone is the distance from the edge in surface-local + coordinates to consider exclusive. + + Surfaces that do not wish to have an exclusive zone may instead specify + how they should interact with surfaces that do. If set to zero, the + surface indicates that it would like to be moved to avoid occluding + surfaces with a positive exclusive zone. If set to -1, the surface + indicates that it would not like to be moved to accommodate for other + surfaces, and the compositor should extend it all the way to the edges + it is anchored to. + + For example, a panel might set its exclusive zone to 10, so that + maximized shell surfaces are not shown on top of it. A notification + might set its exclusive zone to 0, so that it is moved to avoid + occluding the panel, but shell surfaces are shown underneath it. A + wallpaper or lock screen might set their exclusive zone to -1, so that + they stretch below or over the panel. + + The default value is 0. + + Exclusive zone is double-buffered, see wl_surface.commit. + + + + + + + Requests that the surface be placed some distance away from the anchor + point on the output, in surface-local coordinates. Setting this value + for edges you are not anchored to has no effect. + + The exclusive zone includes the margin. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + + + + Types of keyboard interaction possible for layer shell surfaces. The + rationale for this is twofold: (1) some applications are not interested + in keyboard events and not allowing them to be focused can improve the + desktop experience; (2) some applications will want to take exclusive + keyboard focus. + + + + + This value indicates that this surface is not interested in keyboard + events and the compositor should never assign it the keyboard focus. + + This is the default value, set for newly created layer shell surfaces. + + This is useful for e.g. desktop widgets that display information or + only have interaction with non-keyboard input devices. + + + + + Request exclusive keyboard focus if this surface is above the shell surface layer. + + For the top and overlay layers, the seat will always give + exclusive keyboard focus to the top-most layer which has keyboard + interactivity set to exclusive. If this layer contains multiple + surfaces with keyboard interactivity set to exclusive, the compositor + determines the one receiving keyboard events in an implementation- + defined manner. In this case, no guarantee is made when this surface + will receive keyboard focus (if ever). + + For the bottom and background layers, the compositor is allowed to use + normal focus semantics. + + This setting is mainly intended for applications that need to ensure + they receive all keyboard events, such as a lock screen or a password + prompt. + + + + + This requests the compositor to allow this surface to be focused and + unfocused by the user in an implementation-defined manner. The user + should be able to unfocus this surface even regardless of the layer + it is on. + + Typically, the compositor will want to use its normal mechanism to + manage keyboard focus between layer shell surfaces with this setting + and regular toplevels on the desktop layer (e.g. click to focus). + Nevertheless, it is possible for a compositor to require a special + interaction to focus or unfocus layer shell surfaces (e.g. requiring + a click even if focus follows the mouse normally, or providing a + keybinding to switch focus between layers). + + This setting is mainly intended for desktop shell components (e.g. + panels) that allow keyboard interaction. Using this option can allow + implementing a desktop shell that can be fully usable without the + mouse. + + + + + + + Set how keyboard events are delivered to this surface. By default, + layer shell surfaces do not receive keyboard events; this request can + be used to change this. + + This setting is inherited by child surfaces set by the get_popup + request. + + Layer surfaces receive pointer, touch, and tablet events normally. If + you do not want to receive them, set the input region on your surface + to an empty region. + + Keyboard interactivity is double-buffered, see wl_surface.commit. + + + + + + + This assigns an xdg_popup's parent to this layer_surface. This popup + should have been created via xdg_surface::get_popup with the parent set + to NULL, and this request must be invoked before committing the popup's + initial state. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + + + + + + + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make an ack_configure request sometime before the commit + request, passing along the serial of the configure event. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + A client is not required to commit immediately after sending + an ack_configure request - it may even ack_configure several times + before its next surface commit. + + A client may send multiple ack_configure requests before committing, but + only the last request sent before a commit indicates which configure + event the client really is responding to. + + + + + + + This request destroys the layer surface. + + + + + + The configure event asks the client to resize its surface. + + Clients should arrange their surface for the new states, and then send + an ack_configure request with the serial sent in this configure event at + some point before committing the new surface. + + The client is free to dismiss all but the last configure event it + received. + + The width and height arguments specify the size of the window in + surface-local coordinates. + + The size is a hint, in the sense that the client is free to ignore it if + it doesn't resize, pick a smaller size (to satisfy aspect ratio or + resize in steps of NxM pixels). If the client picks a smaller size and + is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the + surface will be centered on this axis. + + If the width or height arguments are zero, it means the client should + decide its own window dimension. + + + + + + + + + The closed event is sent by the compositor when the surface will no + longer be shown. The output may have been destroyed or the user may + have asked for it to be removed. Further changes to the surface will be + ignored. The client should destroy the resource after receiving this + event, and create a new surface if they so choose. + + + + + + + + + + + + + + + + + + + + + + Change the layer that the surface is rendered on. + + Layer is double-buffered, see wl_surface.commit. + + + + + diff --git a/src/x11-color.cc b/src/x11-color.cc new file mode 100644 index 00000000..b8019bb1 --- /dev/null +++ b/src/x11-color.cc @@ -0,0 +1,1604 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include +#include + +typedef struct _builtinColor { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned short name; +} BuiltinColor; + +static const char BuiltinColorNames[] = { + "alice blue\0" + "AliceBlue\0" + "antique white\0" + "AntiqueWhite\0" + "AntiqueWhite1\0" + "AntiqueWhite2\0" + "AntiqueWhite3\0" + "AntiqueWhite4\0" + "aquamarine\0" + "aquamarine1\0" + "aquamarine2\0" + "aquamarine3\0" + "aquamarine4\0" + "azure\0" + "azure1\0" + "azure2\0" + "azure3\0" + "azure4\0" + "beige\0" + "bisque\0" + "bisque1\0" + "bisque2\0" + "bisque3\0" + "bisque4\0" + "black\0" + "blanched almond\0" + "BlanchedAlmond\0" + "blue\0" + "blue violet\0" + "blue1\0" + "blue2\0" + "blue3\0" + "blue4\0" + "BlueViolet\0" + "brown\0" + "brown1\0" + "brown2\0" + "brown3\0" + "brown4\0" + "burlywood\0" + "burlywood1\0" + "burlywood2\0" + "burlywood3\0" + "burlywood4\0" + "cadet blue\0" + "CadetBlue\0" + "CadetBlue1\0" + "CadetBlue2\0" + "CadetBlue3\0" + "CadetBlue4\0" + "chartreuse\0" + "chartreuse1\0" + "chartreuse2\0" + "chartreuse3\0" + "chartreuse4\0" + "chocolate\0" + "chocolate1\0" + "chocolate2\0" + "chocolate3\0" + "chocolate4\0" + "coral\0" + "coral1\0" + "coral2\0" + "coral3\0" + "coral4\0" + "cornflower blue\0" + "CornflowerBlue\0" + "cornsilk\0" + "cornsilk1\0" + "cornsilk2\0" + "cornsilk3\0" + "cornsilk4\0" + "cyan\0" + "cyan1\0" + "cyan2\0" + "cyan3\0" + "cyan4\0" + "dark blue\0" + "dark cyan\0" + "dark goldenrod\0" + "dark gray\0" + "dark green\0" + "dark grey\0" + "dark khaki\0" + "dark magenta\0" + "dark olive green\0" + "dark orange\0" + "dark orchid\0" + "dark red\0" + "dark salmon\0" + "dark sea green\0" + "dark slate blue\0" + "dark slate gray\0" + "dark slate grey\0" + "dark turquoise\0" + "dark violet\0" + "DarkBlue\0" + "DarkCyan\0" + "DarkGoldenrod\0" + "DarkGoldenrod1\0" + "DarkGoldenrod2\0" + "DarkGoldenrod3\0" + "DarkGoldenrod4\0" + "DarkGray\0" + "DarkGreen\0" + "DarkGrey\0" + "DarkKhaki\0" + "DarkMagenta\0" + "DarkOliveGreen\0" + "DarkOliveGreen1\0" + "DarkOliveGreen2\0" + "DarkOliveGreen3\0" + "DarkOliveGreen4\0" + "DarkOrange\0" + "DarkOrange1\0" + "DarkOrange2\0" + "DarkOrange3\0" + "DarkOrange4\0" + "DarkOrchid\0" + "DarkOrchid1\0" + "DarkOrchid2\0" + "DarkOrchid3\0" + "DarkOrchid4\0" + "DarkRed\0" + "DarkSalmon\0" + "DarkSeaGreen\0" + "DarkSeaGreen1\0" + "DarkSeaGreen2\0" + "DarkSeaGreen3\0" + "DarkSeaGreen4\0" + "DarkSlateBlue\0" + "DarkSlateGray\0" + "DarkSlateGray1\0" + "DarkSlateGray2\0" + "DarkSlateGray3\0" + "DarkSlateGray4\0" + "DarkSlateGrey\0" + "DarkTurquoise\0" + "DarkViolet\0" + "deep pink\0" + "deep sky blue\0" + "DeepPink\0" + "DeepPink1\0" + "DeepPink2\0" + "DeepPink3\0" + "DeepPink4\0" + "DeepSkyBlue\0" + "DeepSkyBlue1\0" + "DeepSkyBlue2\0" + "DeepSkyBlue3\0" + "DeepSkyBlue4\0" + "dim gray\0" + "dim grey\0" + "DimGray\0" + "DimGrey\0" + "dodger blue\0" + "DodgerBlue\0" + "DodgerBlue1\0" + "DodgerBlue2\0" + "DodgerBlue3\0" + "DodgerBlue4\0" + "firebrick\0" + "firebrick1\0" + "firebrick2\0" + "firebrick3\0" + "firebrick4\0" + "floral white\0" + "FloralWhite\0" + "forest green\0" + "ForestGreen\0" + "gainsboro\0" + "ghost white\0" + "GhostWhite\0" + "gold\0" + "gold1\0" + "gold2\0" + "gold3\0" + "gold4\0" + "goldenrod\0" + "goldenrod1\0" + "goldenrod2\0" + "goldenrod3\0" + "goldenrod4\0" + "gray\0" + "gray0\0" + "gray1\0" + "gray10\0" + "gray100\0" + "gray11\0" + "gray12\0" + "gray13\0" + "gray14\0" + "gray15\0" + "gray16\0" + "gray17\0" + "gray18\0" + "gray19\0" + "gray2\0" + "gray20\0" + "gray21\0" + "gray22\0" + "gray23\0" + "gray24\0" + "gray25\0" + "gray26\0" + "gray27\0" + "gray28\0" + "gray29\0" + "gray3\0" + "gray30\0" + "gray31\0" + "gray32\0" + "gray33\0" + "gray34\0" + "gray35\0" + "gray36\0" + "gray37\0" + "gray38\0" + "gray39\0" + "gray4\0" + "gray40\0" + "gray41\0" + "gray42\0" + "gray43\0" + "gray44\0" + "gray45\0" + "gray46\0" + "gray47\0" + "gray48\0" + "gray49\0" + "gray5\0" + "gray50\0" + "gray51\0" + "gray52\0" + "gray53\0" + "gray54\0" + "gray55\0" + "gray56\0" + "gray57\0" + "gray58\0" + "gray59\0" + "gray6\0" + "gray60\0" + "gray61\0" + "gray62\0" + "gray63\0" + "gray64\0" + "gray65\0" + "gray66\0" + "gray67\0" + "gray68\0" + "gray69\0" + "gray7\0" + "gray70\0" + "gray71\0" + "gray72\0" + "gray73\0" + "gray74\0" + "gray75\0" + "gray76\0" + "gray77\0" + "gray78\0" + "gray79\0" + "gray8\0" + "gray80\0" + "gray81\0" + "gray82\0" + "gray83\0" + "gray84\0" + "gray85\0" + "gray86\0" + "gray87\0" + "gray88\0" + "gray89\0" + "gray9\0" + "gray90\0" + "gray91\0" + "gray92\0" + "gray93\0" + "gray94\0" + "gray95\0" + "gray96\0" + "gray97\0" + "gray98\0" + "gray99\0" + "green\0" + "green yellow\0" + "green1\0" + "green2\0" + "green3\0" + "green4\0" + "GreenYellow\0" + "grey\0" + "grey0\0" + "grey1\0" + "grey10\0" + "grey100\0" + "grey11\0" + "grey12\0" + "grey13\0" + "grey14\0" + "grey15\0" + "grey16\0" + "grey17\0" + "grey18\0" + "grey19\0" + "grey2\0" + "grey20\0" + "grey21\0" + "grey22\0" + "grey23\0" + "grey24\0" + "grey25\0" + "grey26\0" + "grey27\0" + "grey28\0" + "grey29\0" + "grey3\0" + "grey30\0" + "grey31\0" + "grey32\0" + "grey33\0" + "grey34\0" + "grey35\0" + "grey36\0" + "grey37\0" + "grey38\0" + "grey39\0" + "grey4\0" + "grey40\0" + "grey41\0" + "grey42\0" + "grey43\0" + "grey44\0" + "grey45\0" + "grey46\0" + "grey47\0" + "grey48\0" + "grey49\0" + "grey5\0" + "grey50\0" + "grey51\0" + "grey52\0" + "grey53\0" + "grey54\0" + "grey55\0" + "grey56\0" + "grey57\0" + "grey58\0" + "grey59\0" + "grey6\0" + "grey60\0" + "grey61\0" + "grey62\0" + "grey63\0" + "grey64\0" + "grey65\0" + "grey66\0" + "grey67\0" + "grey68\0" + "grey69\0" + "grey7\0" + "grey70\0" + "grey71\0" + "grey72\0" + "grey73\0" + "grey74\0" + "grey75\0" + "grey76\0" + "grey77\0" + "grey78\0" + "grey79\0" + "grey8\0" + "grey80\0" + "grey81\0" + "grey82\0" + "grey83\0" + "grey84\0" + "grey85\0" + "grey86\0" + "grey87\0" + "grey88\0" + "grey89\0" + "grey9\0" + "grey90\0" + "grey91\0" + "grey92\0" + "grey93\0" + "grey94\0" + "grey95\0" + "grey96\0" + "grey97\0" + "grey98\0" + "grey99\0" + "honeydew\0" + "honeydew1\0" + "honeydew2\0" + "honeydew3\0" + "honeydew4\0" + "hot pink\0" + "HotPink\0" + "HotPink1\0" + "HotPink2\0" + "HotPink3\0" + "HotPink4\0" + "indian red\0" + "IndianRed\0" + "IndianRed1\0" + "IndianRed2\0" + "IndianRed3\0" + "IndianRed4\0" + "ivory\0" + "ivory1\0" + "ivory2\0" + "ivory3\0" + "ivory4\0" + "khaki\0" + "khaki1\0" + "khaki2\0" + "khaki3\0" + "khaki4\0" + "lavender\0" + "lavender blush\0" + "LavenderBlush\0" + "LavenderBlush1\0" + "LavenderBlush2\0" + "LavenderBlush3\0" + "LavenderBlush4\0" + "lawn green\0" + "LawnGreen\0" + "lemon chiffon\0" + "LemonChiffon\0" + "LemonChiffon1\0" + "LemonChiffon2\0" + "LemonChiffon3\0" + "LemonChiffon4\0" + "light blue\0" + "light coral\0" + "light cyan\0" + "light goldenrod\0" + "light goldenrod yellow\0" + "light gray\0" + "light green\0" + "light grey\0" + "light pink\0" + "light salmon\0" + "light sea green\0" + "light sky blue\0" + "light slate blue\0" + "light slate gray\0" + "light slate grey\0" + "light steel blue\0" + "light yellow\0" + "LightBlue\0" + "LightBlue1\0" + "LightBlue2\0" + "LightBlue3\0" + "LightBlue4\0" + "LightCoral\0" + "LightCyan\0" + "LightCyan1\0" + "LightCyan2\0" + "LightCyan3\0" + "LightCyan4\0" + "LightGoldenrod\0" + "LightGoldenrod1\0" + "LightGoldenrod2\0" + "LightGoldenrod3\0" + "LightGoldenrod4\0" + "LightGoldenrodYellow\0" + "LightGray\0" + "LightGreen\0" + "LightGrey\0" + "LightPink\0" + "LightPink1\0" + "LightPink2\0" + "LightPink3\0" + "LightPink4\0" + "LightSalmon\0" + "LightSalmon1\0" + "LightSalmon2\0" + "LightSalmon3\0" + "LightSalmon4\0" + "LightSeaGreen\0" + "LightSkyBlue\0" + "LightSkyBlue1\0" + "LightSkyBlue2\0" + "LightSkyBlue3\0" + "LightSkyBlue4\0" + "LightSlateBlue\0" + "LightSlateGray\0" + "LightSlateGrey\0" + "LightSteelBlue\0" + "LightSteelBlue1\0" + "LightSteelBlue2\0" + "LightSteelBlue3\0" + "LightSteelBlue4\0" + "LightYellow\0" + "LightYellow1\0" + "LightYellow2\0" + "LightYellow3\0" + "LightYellow4\0" + "lime green\0" + "LimeGreen\0" + "linen\0" + "magenta\0" + "magenta1\0" + "magenta2\0" + "magenta3\0" + "magenta4\0" + "maroon\0" + "maroon1\0" + "maroon2\0" + "maroon3\0" + "maroon4\0" + "medium aquamarine\0" + "medium blue\0" + "medium orchid\0" + "medium purple\0" + "medium sea green\0" + "medium slate blue\0" + "medium spring green\0" + "medium turquoise\0" + "medium violet red\0" + "MediumAquamarine\0" + "MediumBlue\0" + "MediumOrchid\0" + "MediumOrchid1\0" + "MediumOrchid2\0" + "MediumOrchid3\0" + "MediumOrchid4\0" + "MediumPurple\0" + "MediumPurple1\0" + "MediumPurple2\0" + "MediumPurple3\0" + "MediumPurple4\0" + "MediumSeaGreen\0" + "MediumSlateBlue\0" + "MediumSpringGreen\0" + "MediumTurquoise\0" + "MediumVioletRed\0" + "midnight blue\0" + "MidnightBlue\0" + "mint cream\0" + "MintCream\0" + "misty rose\0" + "MistyRose\0" + "MistyRose1\0" + "MistyRose2\0" + "MistyRose3\0" + "MistyRose4\0" + "moccasin\0" + "navajo white\0" + "NavajoWhite\0" + "NavajoWhite1\0" + "NavajoWhite2\0" + "NavajoWhite3\0" + "NavajoWhite4\0" + "navy\0" + "navy blue\0" + "NavyBlue\0" + "old lace\0" + "OldLace\0" + "olive drab\0" + "OliveDrab\0" + "OliveDrab1\0" + "OliveDrab2\0" + "OliveDrab3\0" + "OliveDrab4\0" + "orange\0" + "orange red\0" + "orange1\0" + "orange2\0" + "orange3\0" + "orange4\0" + "OrangeRed\0" + "OrangeRed1\0" + "OrangeRed2\0" + "OrangeRed3\0" + "OrangeRed4\0" + "orchid\0" + "orchid1\0" + "orchid2\0" + "orchid3\0" + "orchid4\0" + "pale goldenrod\0" + "pale green\0" + "pale turquoise\0" + "pale violet red\0" + "PaleGoldenrod\0" + "PaleGreen\0" + "PaleGreen1\0" + "PaleGreen2\0" + "PaleGreen3\0" + "PaleGreen4\0" + "PaleTurquoise\0" + "PaleTurquoise1\0" + "PaleTurquoise2\0" + "PaleTurquoise3\0" + "PaleTurquoise4\0" + "PaleVioletRed\0" + "PaleVioletRed1\0" + "PaleVioletRed2\0" + "PaleVioletRed3\0" + "PaleVioletRed4\0" + "papaya whip\0" + "PapayaWhip\0" + "peach puff\0" + "PeachPuff\0" + "PeachPuff1\0" + "PeachPuff2\0" + "PeachPuff3\0" + "PeachPuff4\0" + "peru\0" + "pink\0" + "pink1\0" + "pink2\0" + "pink3\0" + "pink4\0" + "plum\0" + "plum1\0" + "plum2\0" + "plum3\0" + "plum4\0" + "powder blue\0" + "PowderBlue\0" + "purple\0" + "purple1\0" + "purple2\0" + "purple3\0" + "purple4\0" + "red\0" + "red1\0" + "red2\0" + "red3\0" + "red4\0" + "rosy brown\0" + "RosyBrown\0" + "RosyBrown1\0" + "RosyBrown2\0" + "RosyBrown3\0" + "RosyBrown4\0" + "royal blue\0" + "RoyalBlue\0" + "RoyalBlue1\0" + "RoyalBlue2\0" + "RoyalBlue3\0" + "RoyalBlue4\0" + "saddle brown\0" + "SaddleBrown\0" + "salmon\0" + "salmon1\0" + "salmon2\0" + "salmon3\0" + "salmon4\0" + "sandy brown\0" + "SandyBrown\0" + "sea green\0" + "SeaGreen\0" + "SeaGreen1\0" + "SeaGreen2\0" + "SeaGreen3\0" + "SeaGreen4\0" + "seashell\0" + "seashell1\0" + "seashell2\0" + "seashell3\0" + "seashell4\0" + "sienna\0" + "sienna1\0" + "sienna2\0" + "sienna3\0" + "sienna4\0" + "sky blue\0" + "SkyBlue\0" + "SkyBlue1\0" + "SkyBlue2\0" + "SkyBlue3\0" + "SkyBlue4\0" + "slate blue\0" + "slate gray\0" + "slate grey\0" + "SlateBlue\0" + "SlateBlue1\0" + "SlateBlue2\0" + "SlateBlue3\0" + "SlateBlue4\0" + "SlateGray\0" + "SlateGray1\0" + "SlateGray2\0" + "SlateGray3\0" + "SlateGray4\0" + "SlateGrey\0" + "snow\0" + "snow1\0" + "snow2\0" + "snow3\0" + "snow4\0" + "spring green\0" + "SpringGreen\0" + "SpringGreen1\0" + "SpringGreen2\0" + "SpringGreen3\0" + "SpringGreen4\0" + "steel blue\0" + "SteelBlue\0" + "SteelBlue1\0" + "SteelBlue2\0" + "SteelBlue3\0" + "SteelBlue4\0" + "tan\0" + "tan1\0" + "tan2\0" + "tan3\0" + "tan4\0" + "thistle\0" + "thistle1\0" + "thistle2\0" + "thistle3\0" + "thistle4\0" + "tomato\0" + "tomato1\0" + "tomato2\0" + "tomato3\0" + "tomato4\0" + "turquoise\0" + "turquoise1\0" + "turquoise2\0" + "turquoise3\0" + "turquoise4\0" + "violet\0" + "violet red\0" + "VioletRed\0" + "VioletRed1\0" + "VioletRed2\0" + "VioletRed3\0" + "VioletRed4\0" + "wheat\0" + "wheat1\0" + "wheat2\0" + "wheat3\0" + "wheat4\0" + "white\0" + "white smoke\0" + "WhiteSmoke\0" + "yellow\0" + "yellow green\0" + "yellow1\0" + "yellow2\0" + "yellow3\0" + "yellow4\0" + "YellowGreen\0" +}; + +static const BuiltinColor BuiltinColors[] = { + { 240, 248, 255, 0 }, /* alice blue */ + { 240, 248, 255, 11 }, /* AliceBlue */ + { 250, 235, 215, 21 }, /* antique white */ + { 250, 235, 215, 35 }, /* AntiqueWhite */ + { 255, 239, 219, 48 }, /* AntiqueWhite1 */ + { 238, 223, 204, 62 }, /* AntiqueWhite2 */ + { 205, 192, 176, 76 }, /* AntiqueWhite3 */ + { 139, 131, 120, 90 }, /* AntiqueWhite4 */ + { 127, 255, 212, 104 }, /* aquamarine */ + { 127, 255, 212, 115 }, /* aquamarine1 */ + { 118, 238, 198, 127 }, /* aquamarine2 */ + { 102, 205, 170, 139 }, /* aquamarine3 */ + { 69, 139, 116, 151 }, /* aquamarine4 */ + { 240, 255, 255, 163 }, /* azure */ + { 240, 255, 255, 169 }, /* azure1 */ + { 224, 238, 238, 176 }, /* azure2 */ + { 193, 205, 205, 183 }, /* azure3 */ + { 131, 139, 139, 190 }, /* azure4 */ + { 245, 245, 220, 197 }, /* beige */ + { 255, 228, 196, 203 }, /* bisque */ + { 255, 228, 196, 210 }, /* bisque1 */ + { 238, 213, 183, 218 }, /* bisque2 */ + { 205, 183, 158, 226 }, /* bisque3 */ + { 139, 125, 107, 234 }, /* bisque4 */ + { 0, 0, 0, 242 }, /* black */ + { 255, 235, 205, 248 }, /* blanched almond */ + { 255, 235, 205, 264 }, /* BlanchedAlmond */ + { 0, 0, 255, 279 }, /* blue */ + { 138, 43, 226, 284 }, /* blue violet */ + { 0, 0, 255, 296 }, /* blue1 */ + { 0, 0, 238, 302 }, /* blue2 */ + { 0, 0, 205, 308 }, /* blue3 */ + { 0, 0, 139, 314 }, /* blue4 */ + { 138, 43, 226, 320 }, /* BlueViolet */ + { 165, 42, 42, 331 }, /* brown */ + { 255, 64, 64, 337 }, /* brown1 */ + { 238, 59, 59, 344 }, /* brown2 */ + { 205, 51, 51, 351 }, /* brown3 */ + { 139, 35, 35, 358 }, /* brown4 */ + { 222, 184, 135, 365 }, /* burlywood */ + { 255, 211, 155, 375 }, /* burlywood1 */ + { 238, 197, 145, 386 }, /* burlywood2 */ + { 205, 170, 125, 397 }, /* burlywood3 */ + { 139, 115, 85, 408 }, /* burlywood4 */ + { 95, 158, 160, 419 }, /* cadet blue */ + { 95, 158, 160, 430 }, /* CadetBlue */ + { 152, 245, 255, 440 }, /* CadetBlue1 */ + { 142, 229, 238, 451 }, /* CadetBlue2 */ + { 122, 197, 205, 462 }, /* CadetBlue3 */ + { 83, 134, 139, 473 }, /* CadetBlue4 */ + { 127, 255, 0, 484 }, /* chartreuse */ + { 127, 255, 0, 495 }, /* chartreuse1 */ + { 118, 238, 0, 507 }, /* chartreuse2 */ + { 102, 205, 0, 519 }, /* chartreuse3 */ + { 69, 139, 0, 531 }, /* chartreuse4 */ + { 210, 105, 30, 543 }, /* chocolate */ + { 255, 127, 36, 553 }, /* chocolate1 */ + { 238, 118, 33, 564 }, /* chocolate2 */ + { 205, 102, 29, 575 }, /* chocolate3 */ + { 139, 69, 19, 586 }, /* chocolate4 */ + { 255, 127, 80, 597 }, /* coral */ + { 255, 114, 86, 603 }, /* coral1 */ + { 238, 106, 80, 610 }, /* coral2 */ + { 205, 91, 69, 617 }, /* coral3 */ + { 139, 62, 47, 624 }, /* coral4 */ + { 100, 149, 237, 631 }, /* cornflower blue */ + { 100, 149, 237, 647 }, /* CornflowerBlue */ + { 255, 248, 220, 662 }, /* cornsilk */ + { 255, 248, 220, 671 }, /* cornsilk1 */ + { 238, 232, 205, 681 }, /* cornsilk2 */ + { 205, 200, 177, 691 }, /* cornsilk3 */ + { 139, 136, 120, 701 }, /* cornsilk4 */ + { 0, 255, 255, 711 }, /* cyan */ + { 0, 255, 255, 716 }, /* cyan1 */ + { 0, 238, 238, 722 }, /* cyan2 */ + { 0, 205, 205, 728 }, /* cyan3 */ + { 0, 139, 139, 734 }, /* cyan4 */ + { 0, 0, 139, 740 }, /* dark blue */ + { 0, 139, 139, 750 }, /* dark cyan */ + { 184, 134, 11, 760 }, /* dark goldenrod */ + { 169, 169, 169, 775 }, /* dark gray */ + { 0, 100, 0, 785 }, /* dark green */ + { 169, 169, 169, 796 }, /* dark grey */ + { 189, 183, 107, 806 }, /* dark khaki */ + { 139, 0, 139, 817 }, /* dark magenta */ + { 85, 107, 47, 830 }, /* dark olive green */ + { 255, 140, 0, 847 }, /* dark orange */ + { 153, 50, 204, 859 }, /* dark orchid */ + { 139, 0, 0, 871 }, /* dark red */ + { 233, 150, 122, 880 }, /* dark salmon */ + { 143, 188, 143, 892 }, /* dark sea green */ + { 72, 61, 139, 907 }, /* dark slate blue */ + { 47, 79, 79, 923 }, /* dark slate gray */ + { 47, 79, 79, 939 }, /* dark slate grey */ + { 0, 206, 209, 955 }, /* dark turquoise */ + { 148, 0, 211, 970 }, /* dark violet */ + { 0, 0, 139, 982 }, /* DarkBlue */ + { 0, 139, 139, 991 }, /* DarkCyan */ + { 184, 134, 11, 1000 }, /* DarkGoldenrod */ + { 255, 185, 15, 1014 }, /* DarkGoldenrod1 */ + { 238, 173, 14, 1029 }, /* DarkGoldenrod2 */ + { 205, 149, 12, 1044 }, /* DarkGoldenrod3 */ + { 139, 101, 8, 1059 }, /* DarkGoldenrod4 */ + { 169, 169, 169, 1074 }, /* DarkGray */ + { 0, 100, 0, 1083 }, /* DarkGreen */ + { 169, 169, 169, 1093 }, /* DarkGrey */ + { 189, 183, 107, 1102 }, /* DarkKhaki */ + { 139, 0, 139, 1112 }, /* DarkMagenta */ + { 85, 107, 47, 1124 }, /* DarkOliveGreen */ + { 202, 255, 112, 1139 }, /* DarkOliveGreen1 */ + { 188, 238, 104, 1155 }, /* DarkOliveGreen2 */ + { 162, 205, 90, 1171 }, /* DarkOliveGreen3 */ + { 110, 139, 61, 1187 }, /* DarkOliveGreen4 */ + { 255, 140, 0, 1203 }, /* DarkOrange */ + { 255, 127, 0, 1214 }, /* DarkOrange1 */ + { 238, 118, 0, 1226 }, /* DarkOrange2 */ + { 205, 102, 0, 1238 }, /* DarkOrange3 */ + { 139, 69, 0, 1250 }, /* DarkOrange4 */ + { 153, 50, 204, 1262 }, /* DarkOrchid */ + { 191, 62, 255, 1273 }, /* DarkOrchid1 */ + { 178, 58, 238, 1285 }, /* DarkOrchid2 */ + { 154, 50, 205, 1297 }, /* DarkOrchid3 */ + { 104, 34, 139, 1309 }, /* DarkOrchid4 */ + { 139, 0, 0, 1321 }, /* DarkRed */ + { 233, 150, 122, 1329 }, /* DarkSalmon */ + { 143, 188, 143, 1340 }, /* DarkSeaGreen */ + { 193, 255, 193, 1353 }, /* DarkSeaGreen1 */ + { 180, 238, 180, 1367 }, /* DarkSeaGreen2 */ + { 155, 205, 155, 1381 }, /* DarkSeaGreen3 */ + { 105, 139, 105, 1395 }, /* DarkSeaGreen4 */ + { 72, 61, 139, 1409 }, /* DarkSlateBlue */ + { 47, 79, 79, 1423 }, /* DarkSlateGray */ + { 151, 255, 255, 1437 }, /* DarkSlateGray1 */ + { 141, 238, 238, 1452 }, /* DarkSlateGray2 */ + { 121, 205, 205, 1467 }, /* DarkSlateGray3 */ + { 82, 139, 139, 1482 }, /* DarkSlateGray4 */ + { 47, 79, 79, 1497 }, /* DarkSlateGrey */ + { 0, 206, 209, 1511 }, /* DarkTurquoise */ + { 148, 0, 211, 1525 }, /* DarkViolet */ + { 255, 20, 147, 1536 }, /* deep pink */ + { 0, 191, 255, 1546 }, /* deep sky blue */ + { 255, 20, 147, 1560 }, /* DeepPink */ + { 255, 20, 147, 1569 }, /* DeepPink1 */ + { 238, 18, 137, 1579 }, /* DeepPink2 */ + { 205, 16, 118, 1589 }, /* DeepPink3 */ + { 139, 10, 80, 1599 }, /* DeepPink4 */ + { 0, 191, 255, 1609 }, /* DeepSkyBlue */ + { 0, 191, 255, 1621 }, /* DeepSkyBlue1 */ + { 0, 178, 238, 1634 }, /* DeepSkyBlue2 */ + { 0, 154, 205, 1647 }, /* DeepSkyBlue3 */ + { 0, 104, 139, 1660 }, /* DeepSkyBlue4 */ + { 105, 105, 105, 1673 }, /* dim gray */ + { 105, 105, 105, 1682 }, /* dim grey */ + { 105, 105, 105, 1691 }, /* DimGray */ + { 105, 105, 105, 1699 }, /* DimGrey */ + { 30, 144, 255, 1707 }, /* dodger blue */ + { 30, 144, 255, 1719 }, /* DodgerBlue */ + { 30, 144, 255, 1730 }, /* DodgerBlue1 */ + { 28, 134, 238, 1742 }, /* DodgerBlue2 */ + { 24, 116, 205, 1754 }, /* DodgerBlue3 */ + { 16, 78, 139, 1766 }, /* DodgerBlue4 */ + { 178, 34, 34, 1778 }, /* firebrick */ + { 255, 48, 48, 1788 }, /* firebrick1 */ + { 238, 44, 44, 1799 }, /* firebrick2 */ + { 205, 38, 38, 1810 }, /* firebrick3 */ + { 139, 26, 26, 1821 }, /* firebrick4 */ + { 255, 250, 240, 1832 }, /* floral white */ + { 255, 250, 240, 1845 }, /* FloralWhite */ + { 34, 139, 34, 1857 }, /* forest green */ + { 34, 139, 34, 1870 }, /* ForestGreen */ + { 220, 220, 220, 1882 }, /* gainsboro */ + { 248, 248, 255, 1892 }, /* ghost white */ + { 248, 248, 255, 1904 }, /* GhostWhite */ + { 255, 215, 0, 1915 }, /* gold */ + { 255, 215, 0, 1920 }, /* gold1 */ + { 238, 201, 0, 1926 }, /* gold2 */ + { 205, 173, 0, 1932 }, /* gold3 */ + { 139, 117, 0, 1938 }, /* gold4 */ + { 218, 165, 32, 1944 }, /* goldenrod */ + { 255, 193, 37, 1954 }, /* goldenrod1 */ + { 238, 180, 34, 1965 }, /* goldenrod2 */ + { 205, 155, 29, 1976 }, /* goldenrod3 */ + { 139, 105, 20, 1987 }, /* goldenrod4 */ + { 190, 190, 190, 1998 }, /* gray */ + { 0, 0, 0, 2003 }, /* gray0 */ + { 3, 3, 3, 2009 }, /* gray1 */ + { 26, 26, 26, 2015 }, /* gray10 */ + { 255, 255, 255, 2022 }, /* gray100 */ + { 28, 28, 28, 2030 }, /* gray11 */ + { 31, 31, 31, 2037 }, /* gray12 */ + { 33, 33, 33, 2044 }, /* gray13 */ + { 36, 36, 36, 2051 }, /* gray14 */ + { 38, 38, 38, 2058 }, /* gray15 */ + { 41, 41, 41, 2065 }, /* gray16 */ + { 43, 43, 43, 2072 }, /* gray17 */ + { 46, 46, 46, 2079 }, /* gray18 */ + { 48, 48, 48, 2086 }, /* gray19 */ + { 5, 5, 5, 2093 }, /* gray2 */ + { 51, 51, 51, 2099 }, /* gray20 */ + { 54, 54, 54, 2106 }, /* gray21 */ + { 56, 56, 56, 2113 }, /* gray22 */ + { 59, 59, 59, 2120 }, /* gray23 */ + { 61, 61, 61, 2127 }, /* gray24 */ + { 64, 64, 64, 2134 }, /* gray25 */ + { 66, 66, 66, 2141 }, /* gray26 */ + { 69, 69, 69, 2148 }, /* gray27 */ + { 71, 71, 71, 2155 }, /* gray28 */ + { 74, 74, 74, 2162 }, /* gray29 */ + { 8, 8, 8, 2169 }, /* gray3 */ + { 77, 77, 77, 2175 }, /* gray30 */ + { 79, 79, 79, 2182 }, /* gray31 */ + { 82, 82, 82, 2189 }, /* gray32 */ + { 84, 84, 84, 2196 }, /* gray33 */ + { 87, 87, 87, 2203 }, /* gray34 */ + { 89, 89, 89, 2210 }, /* gray35 */ + { 92, 92, 92, 2217 }, /* gray36 */ + { 94, 94, 94, 2224 }, /* gray37 */ + { 97, 97, 97, 2231 }, /* gray38 */ + { 99, 99, 99, 2238 }, /* gray39 */ + { 10, 10, 10, 2245 }, /* gray4 */ + { 102, 102, 102, 2251 }, /* gray40 */ + { 105, 105, 105, 2258 }, /* gray41 */ + { 107, 107, 107, 2265 }, /* gray42 */ + { 110, 110, 110, 2272 }, /* gray43 */ + { 112, 112, 112, 2279 }, /* gray44 */ + { 115, 115, 115, 2286 }, /* gray45 */ + { 117, 117, 117, 2293 }, /* gray46 */ + { 120, 120, 120, 2300 }, /* gray47 */ + { 122, 122, 122, 2307 }, /* gray48 */ + { 125, 125, 125, 2314 }, /* gray49 */ + { 13, 13, 13, 2321 }, /* gray5 */ + { 127, 127, 127, 2327 }, /* gray50 */ + { 130, 130, 130, 2334 }, /* gray51 */ + { 133, 133, 133, 2341 }, /* gray52 */ + { 135, 135, 135, 2348 }, /* gray53 */ + { 138, 138, 138, 2355 }, /* gray54 */ + { 140, 140, 140, 2362 }, /* gray55 */ + { 143, 143, 143, 2369 }, /* gray56 */ + { 145, 145, 145, 2376 }, /* gray57 */ + { 148, 148, 148, 2383 }, /* gray58 */ + { 150, 150, 150, 2390 }, /* gray59 */ + { 15, 15, 15, 2397 }, /* gray6 */ + { 153, 153, 153, 2403 }, /* gray60 */ + { 156, 156, 156, 2410 }, /* gray61 */ + { 158, 158, 158, 2417 }, /* gray62 */ + { 161, 161, 161, 2424 }, /* gray63 */ + { 163, 163, 163, 2431 }, /* gray64 */ + { 166, 166, 166, 2438 }, /* gray65 */ + { 168, 168, 168, 2445 }, /* gray66 */ + { 171, 171, 171, 2452 }, /* gray67 */ + { 173, 173, 173, 2459 }, /* gray68 */ + { 176, 176, 176, 2466 }, /* gray69 */ + { 18, 18, 18, 2473 }, /* gray7 */ + { 179, 179, 179, 2479 }, /* gray70 */ + { 181, 181, 181, 2486 }, /* gray71 */ + { 184, 184, 184, 2493 }, /* gray72 */ + { 186, 186, 186, 2500 }, /* gray73 */ + { 189, 189, 189, 2507 }, /* gray74 */ + { 191, 191, 191, 2514 }, /* gray75 */ + { 194, 194, 194, 2521 }, /* gray76 */ + { 196, 196, 196, 2528 }, /* gray77 */ + { 199, 199, 199, 2535 }, /* gray78 */ + { 201, 201, 201, 2542 }, /* gray79 */ + { 20, 20, 20, 2549 }, /* gray8 */ + { 204, 204, 204, 2555 }, /* gray80 */ + { 207, 207, 207, 2562 }, /* gray81 */ + { 209, 209, 209, 2569 }, /* gray82 */ + { 212, 212, 212, 2576 }, /* gray83 */ + { 214, 214, 214, 2583 }, /* gray84 */ + { 217, 217, 217, 2590 }, /* gray85 */ + { 219, 219, 219, 2597 }, /* gray86 */ + { 222, 222, 222, 2604 }, /* gray87 */ + { 224, 224, 224, 2611 }, /* gray88 */ + { 227, 227, 227, 2618 }, /* gray89 */ + { 23, 23, 23, 2625 }, /* gray9 */ + { 229, 229, 229, 2631 }, /* gray90 */ + { 232, 232, 232, 2638 }, /* gray91 */ + { 235, 235, 235, 2645 }, /* gray92 */ + { 237, 237, 237, 2652 }, /* gray93 */ + { 240, 240, 240, 2659 }, /* gray94 */ + { 242, 242, 242, 2666 }, /* gray95 */ + { 245, 245, 245, 2673 }, /* gray96 */ + { 247, 247, 247, 2680 }, /* gray97 */ + { 250, 250, 250, 2687 }, /* gray98 */ + { 252, 252, 252, 2694 }, /* gray99 */ + { 0, 255, 0, 2701 }, /* green */ + { 173, 255, 47, 2707 }, /* green yellow */ + { 0, 255, 0, 2720 }, /* green1 */ + { 0, 238, 0, 2727 }, /* green2 */ + { 0, 205, 0, 2734 }, /* green3 */ + { 0, 139, 0, 2741 }, /* green4 */ + { 173, 255, 47, 2748 }, /* GreenYellow */ + { 190, 190, 190, 2760 }, /* grey */ + { 0, 0, 0, 2765 }, /* grey0 */ + { 3, 3, 3, 2771 }, /* grey1 */ + { 26, 26, 26, 2777 }, /* grey10 */ + { 255, 255, 255, 2784 }, /* grey100 */ + { 28, 28, 28, 2792 }, /* grey11 */ + { 31, 31, 31, 2799 }, /* grey12 */ + { 33, 33, 33, 2806 }, /* grey13 */ + { 36, 36, 36, 2813 }, /* grey14 */ + { 38, 38, 38, 2820 }, /* grey15 */ + { 41, 41, 41, 2827 }, /* grey16 */ + { 43, 43, 43, 2834 }, /* grey17 */ + { 46, 46, 46, 2841 }, /* grey18 */ + { 48, 48, 48, 2848 }, /* grey19 */ + { 5, 5, 5, 2855 }, /* grey2 */ + { 51, 51, 51, 2861 }, /* grey20 */ + { 54, 54, 54, 2868 }, /* grey21 */ + { 56, 56, 56, 2875 }, /* grey22 */ + { 59, 59, 59, 2882 }, /* grey23 */ + { 61, 61, 61, 2889 }, /* grey24 */ + { 64, 64, 64, 2896 }, /* grey25 */ + { 66, 66, 66, 2903 }, /* grey26 */ + { 69, 69, 69, 2910 }, /* grey27 */ + { 71, 71, 71, 2917 }, /* grey28 */ + { 74, 74, 74, 2924 }, /* grey29 */ + { 8, 8, 8, 2931 }, /* grey3 */ + { 77, 77, 77, 2937 }, /* grey30 */ + { 79, 79, 79, 2944 }, /* grey31 */ + { 82, 82, 82, 2951 }, /* grey32 */ + { 84, 84, 84, 2958 }, /* grey33 */ + { 87, 87, 87, 2965 }, /* grey34 */ + { 89, 89, 89, 2972 }, /* grey35 */ + { 92, 92, 92, 2979 }, /* grey36 */ + { 94, 94, 94, 2986 }, /* grey37 */ + { 97, 97, 97, 2993 }, /* grey38 */ + { 99, 99, 99, 3000 }, /* grey39 */ + { 10, 10, 10, 3007 }, /* grey4 */ + { 102, 102, 102, 3013 }, /* grey40 */ + { 105, 105, 105, 3020 }, /* grey41 */ + { 107, 107, 107, 3027 }, /* grey42 */ + { 110, 110, 110, 3034 }, /* grey43 */ + { 112, 112, 112, 3041 }, /* grey44 */ + { 115, 115, 115, 3048 }, /* grey45 */ + { 117, 117, 117, 3055 }, /* grey46 */ + { 120, 120, 120, 3062 }, /* grey47 */ + { 122, 122, 122, 3069 }, /* grey48 */ + { 125, 125, 125, 3076 }, /* grey49 */ + { 13, 13, 13, 3083 }, /* grey5 */ + { 127, 127, 127, 3089 }, /* grey50 */ + { 130, 130, 130, 3096 }, /* grey51 */ + { 133, 133, 133, 3103 }, /* grey52 */ + { 135, 135, 135, 3110 }, /* grey53 */ + { 138, 138, 138, 3117 }, /* grey54 */ + { 140, 140, 140, 3124 }, /* grey55 */ + { 143, 143, 143, 3131 }, /* grey56 */ + { 145, 145, 145, 3138 }, /* grey57 */ + { 148, 148, 148, 3145 }, /* grey58 */ + { 150, 150, 150, 3152 }, /* grey59 */ + { 15, 15, 15, 3159 }, /* grey6 */ + { 153, 153, 153, 3165 }, /* grey60 */ + { 156, 156, 156, 3172 }, /* grey61 */ + { 158, 158, 158, 3179 }, /* grey62 */ + { 161, 161, 161, 3186 }, /* grey63 */ + { 163, 163, 163, 3193 }, /* grey64 */ + { 166, 166, 166, 3200 }, /* grey65 */ + { 168, 168, 168, 3207 }, /* grey66 */ + { 171, 171, 171, 3214 }, /* grey67 */ + { 173, 173, 173, 3221 }, /* grey68 */ + { 176, 176, 176, 3228 }, /* grey69 */ + { 18, 18, 18, 3235 }, /* grey7 */ + { 179, 179, 179, 3241 }, /* grey70 */ + { 181, 181, 181, 3248 }, /* grey71 */ + { 184, 184, 184, 3255 }, /* grey72 */ + { 186, 186, 186, 3262 }, /* grey73 */ + { 189, 189, 189, 3269 }, /* grey74 */ + { 191, 191, 191, 3276 }, /* grey75 */ + { 194, 194, 194, 3283 }, /* grey76 */ + { 196, 196, 196, 3290 }, /* grey77 */ + { 199, 199, 199, 3297 }, /* grey78 */ + { 201, 201, 201, 3304 }, /* grey79 */ + { 20, 20, 20, 3311 }, /* grey8 */ + { 204, 204, 204, 3317 }, /* grey80 */ + { 207, 207, 207, 3324 }, /* grey81 */ + { 209, 209, 209, 3331 }, /* grey82 */ + { 212, 212, 212, 3338 }, /* grey83 */ + { 214, 214, 214, 3345 }, /* grey84 */ + { 217, 217, 217, 3352 }, /* grey85 */ + { 219, 219, 219, 3359 }, /* grey86 */ + { 222, 222, 222, 3366 }, /* grey87 */ + { 224, 224, 224, 3373 }, /* grey88 */ + { 227, 227, 227, 3380 }, /* grey89 */ + { 23, 23, 23, 3387 }, /* grey9 */ + { 229, 229, 229, 3393 }, /* grey90 */ + { 232, 232, 232, 3400 }, /* grey91 */ + { 235, 235, 235, 3407 }, /* grey92 */ + { 237, 237, 237, 3414 }, /* grey93 */ + { 240, 240, 240, 3421 }, /* grey94 */ + { 242, 242, 242, 3428 }, /* grey95 */ + { 245, 245, 245, 3435 }, /* grey96 */ + { 247, 247, 247, 3442 }, /* grey97 */ + { 250, 250, 250, 3449 }, /* grey98 */ + { 252, 252, 252, 3456 }, /* grey99 */ + { 240, 255, 240, 3463 }, /* honeydew */ + { 240, 255, 240, 3472 }, /* honeydew1 */ + { 224, 238, 224, 3482 }, /* honeydew2 */ + { 193, 205, 193, 3492 }, /* honeydew3 */ + { 131, 139, 131, 3502 }, /* honeydew4 */ + { 255, 105, 180, 3512 }, /* hot pink */ + { 255, 105, 180, 3521 }, /* HotPink */ + { 255, 110, 180, 3529 }, /* HotPink1 */ + { 238, 106, 167, 3538 }, /* HotPink2 */ + { 205, 96, 144, 3547 }, /* HotPink3 */ + { 139, 58, 98, 3556 }, /* HotPink4 */ + { 205, 92, 92, 3565 }, /* indian red */ + { 205, 92, 92, 3576 }, /* IndianRed */ + { 255, 106, 106, 3586 }, /* IndianRed1 */ + { 238, 99, 99, 3597 }, /* IndianRed2 */ + { 205, 85, 85, 3608 }, /* IndianRed3 */ + { 139, 58, 58, 3619 }, /* IndianRed4 */ + { 255, 255, 240, 3630 }, /* ivory */ + { 255, 255, 240, 3636 }, /* ivory1 */ + { 238, 238, 224, 3643 }, /* ivory2 */ + { 205, 205, 193, 3650 }, /* ivory3 */ + { 139, 139, 131, 3657 }, /* ivory4 */ + { 240, 230, 140, 3664 }, /* khaki */ + { 255, 246, 143, 3670 }, /* khaki1 */ + { 238, 230, 133, 3677 }, /* khaki2 */ + { 205, 198, 115, 3684 }, /* khaki3 */ + { 139, 134, 78, 3691 }, /* khaki4 */ + { 230, 230, 250, 3698 }, /* lavender */ + { 255, 240, 245, 3707 }, /* lavender blush */ + { 255, 240, 245, 3722 }, /* LavenderBlush */ + { 255, 240, 245, 3736 }, /* LavenderBlush1 */ + { 238, 224, 229, 3751 }, /* LavenderBlush2 */ + { 205, 193, 197, 3766 }, /* LavenderBlush3 */ + { 139, 131, 134, 3781 }, /* LavenderBlush4 */ + { 124, 252, 0, 3796 }, /* lawn green */ + { 124, 252, 0, 3807 }, /* LawnGreen */ + { 255, 250, 205, 3817 }, /* lemon chiffon */ + { 255, 250, 205, 3831 }, /* LemonChiffon */ + { 255, 250, 205, 3844 }, /* LemonChiffon1 */ + { 238, 233, 191, 3858 }, /* LemonChiffon2 */ + { 205, 201, 165, 3872 }, /* LemonChiffon3 */ + { 139, 137, 112, 3886 }, /* LemonChiffon4 */ + { 173, 216, 230, 3900 }, /* light blue */ + { 240, 128, 128, 3911 }, /* light coral */ + { 224, 255, 255, 3923 }, /* light cyan */ + { 238, 221, 130, 3934 }, /* light goldenrod */ + { 250, 250, 210, 3950 }, /* light goldenrod yellow */ + { 211, 211, 211, 3973 }, /* light gray */ + { 144, 238, 144, 3984 }, /* light green */ + { 211, 211, 211, 3996 }, /* light grey */ + { 255, 182, 193, 4007 }, /* light pink */ + { 255, 160, 122, 4018 }, /* light salmon */ + { 32, 178, 170, 4031 }, /* light sea green */ + { 135, 206, 250, 4047 }, /* light sky blue */ + { 132, 112, 255, 4062 }, /* light slate blue */ + { 119, 136, 153, 4079 }, /* light slate gray */ + { 119, 136, 153, 4096 }, /* light slate grey */ + { 176, 196, 222, 4113 }, /* light steel blue */ + { 255, 255, 224, 4130 }, /* light yellow */ + { 173, 216, 230, 4143 }, /* LightBlue */ + { 191, 239, 255, 4153 }, /* LightBlue1 */ + { 178, 223, 238, 4164 }, /* LightBlue2 */ + { 154, 192, 205, 4175 }, /* LightBlue3 */ + { 104, 131, 139, 4186 }, /* LightBlue4 */ + { 240, 128, 128, 4197 }, /* LightCoral */ + { 224, 255, 255, 4208 }, /* LightCyan */ + { 224, 255, 255, 4218 }, /* LightCyan1 */ + { 209, 238, 238, 4229 }, /* LightCyan2 */ + { 180, 205, 205, 4240 }, /* LightCyan3 */ + { 122, 139, 139, 4251 }, /* LightCyan4 */ + { 238, 221, 130, 4262 }, /* LightGoldenrod */ + { 255, 236, 139, 4277 }, /* LightGoldenrod1 */ + { 238, 220, 130, 4293 }, /* LightGoldenrod2 */ + { 205, 190, 112, 4309 }, /* LightGoldenrod3 */ + { 139, 129, 76, 4325 }, /* LightGoldenrod4 */ + { 250, 250, 210, 4341 }, /* LightGoldenrodYellow */ + { 211, 211, 211, 4362 }, /* LightGray */ + { 144, 238, 144, 4372 }, /* LightGreen */ + { 211, 211, 211, 4383 }, /* LightGrey */ + { 255, 182, 193, 4393 }, /* LightPink */ + { 255, 174, 185, 4403 }, /* LightPink1 */ + { 238, 162, 173, 4414 }, /* LightPink2 */ + { 205, 140, 149, 4425 }, /* LightPink3 */ + { 139, 95, 101, 4436 }, /* LightPink4 */ + { 255, 160, 122, 4447 }, /* LightSalmon */ + { 255, 160, 122, 4459 }, /* LightSalmon1 */ + { 238, 149, 114, 4472 }, /* LightSalmon2 */ + { 205, 129, 98, 4485 }, /* LightSalmon3 */ + { 139, 87, 66, 4498 }, /* LightSalmon4 */ + { 32, 178, 170, 4511 }, /* LightSeaGreen */ + { 135, 206, 250, 4525 }, /* LightSkyBlue */ + { 176, 226, 255, 4538 }, /* LightSkyBlue1 */ + { 164, 211, 238, 4552 }, /* LightSkyBlue2 */ + { 141, 182, 205, 4566 }, /* LightSkyBlue3 */ + { 96, 123, 139, 4580 }, /* LightSkyBlue4 */ + { 132, 112, 255, 4594 }, /* LightSlateBlue */ + { 119, 136, 153, 4609 }, /* LightSlateGray */ + { 119, 136, 153, 4624 }, /* LightSlateGrey */ + { 176, 196, 222, 4639 }, /* LightSteelBlue */ + { 202, 225, 255, 4654 }, /* LightSteelBlue1 */ + { 188, 210, 238, 4670 }, /* LightSteelBlue2 */ + { 162, 181, 205, 4686 }, /* LightSteelBlue3 */ + { 110, 123, 139, 4702 }, /* LightSteelBlue4 */ + { 255, 255, 224, 4718 }, /* LightYellow */ + { 255, 255, 224, 4730 }, /* LightYellow1 */ + { 238, 238, 209, 4743 }, /* LightYellow2 */ + { 205, 205, 180, 4756 }, /* LightYellow3 */ + { 139, 139, 122, 4769 }, /* LightYellow4 */ + { 50, 205, 50, 4782 }, /* lime green */ + { 50, 205, 50, 4793 }, /* LimeGreen */ + { 250, 240, 230, 4803 }, /* linen */ + { 255, 0, 255, 4809 }, /* magenta */ + { 255, 0, 255, 4817 }, /* magenta1 */ + { 238, 0, 238, 4826 }, /* magenta2 */ + { 205, 0, 205, 4835 }, /* magenta3 */ + { 139, 0, 139, 4844 }, /* magenta4 */ + { 176, 48, 96, 4853 }, /* maroon */ + { 255, 52, 179, 4860 }, /* maroon1 */ + { 238, 48, 167, 4868 }, /* maroon2 */ + { 205, 41, 144, 4876 }, /* maroon3 */ + { 139, 28, 98, 4884 }, /* maroon4 */ + { 102, 205, 170, 4892 }, /* medium aquamarine */ + { 0, 0, 205, 4910 }, /* medium blue */ + { 186, 85, 211, 4922 }, /* medium orchid */ + { 147, 112, 219, 4936 }, /* medium purple */ + { 60, 179, 113, 4950 }, /* medium sea green */ + { 123, 104, 238, 4967 }, /* medium slate blue */ + { 0, 250, 154, 4985 }, /* medium spring green */ + { 72, 209, 204, 5005 }, /* medium turquoise */ + { 199, 21, 133, 5022 }, /* medium violet red */ + { 102, 205, 170, 5040 }, /* MediumAquamarine */ + { 0, 0, 205, 5057 }, /* MediumBlue */ + { 186, 85, 211, 5068 }, /* MediumOrchid */ + { 224, 102, 255, 5081 }, /* MediumOrchid1 */ + { 209, 95, 238, 5095 }, /* MediumOrchid2 */ + { 180, 82, 205, 5109 }, /* MediumOrchid3 */ + { 122, 55, 139, 5123 }, /* MediumOrchid4 */ + { 147, 112, 219, 5137 }, /* MediumPurple */ + { 171, 130, 255, 5150 }, /* MediumPurple1 */ + { 159, 121, 238, 5164 }, /* MediumPurple2 */ + { 137, 104, 205, 5178 }, /* MediumPurple3 */ + { 93, 71, 139, 5192 }, /* MediumPurple4 */ + { 60, 179, 113, 5206 }, /* MediumSeaGreen */ + { 123, 104, 238, 5221 }, /* MediumSlateBlue */ + { 0, 250, 154, 5237 }, /* MediumSpringGreen */ + { 72, 209, 204, 5255 }, /* MediumTurquoise */ + { 199, 21, 133, 5271 }, /* MediumVioletRed */ + { 25, 25, 112, 5287 }, /* midnight blue */ + { 25, 25, 112, 5301 }, /* MidnightBlue */ + { 245, 255, 250, 5314 }, /* mint cream */ + { 245, 255, 250, 5325 }, /* MintCream */ + { 255, 228, 225, 5335 }, /* misty rose */ + { 255, 228, 225, 5346 }, /* MistyRose */ + { 255, 228, 225, 5356 }, /* MistyRose1 */ + { 238, 213, 210, 5367 }, /* MistyRose2 */ + { 205, 183, 181, 5378 }, /* MistyRose3 */ + { 139, 125, 123, 5389 }, /* MistyRose4 */ + { 255, 228, 181, 5400 }, /* moccasin */ + { 255, 222, 173, 5409 }, /* navajo white */ + { 255, 222, 173, 5422 }, /* NavajoWhite */ + { 255, 222, 173, 5434 }, /* NavajoWhite1 */ + { 238, 207, 161, 5447 }, /* NavajoWhite2 */ + { 205, 179, 139, 5460 }, /* NavajoWhite3 */ + { 139, 121, 94, 5473 }, /* NavajoWhite4 */ + { 0, 0, 128, 5486 }, /* navy */ + { 0, 0, 128, 5491 }, /* navy blue */ + { 0, 0, 128, 5501 }, /* NavyBlue */ + { 253, 245, 230, 5510 }, /* old lace */ + { 253, 245, 230, 5519 }, /* OldLace */ + { 107, 142, 35, 5527 }, /* olive drab */ + { 107, 142, 35, 5538 }, /* OliveDrab */ + { 192, 255, 62, 5548 }, /* OliveDrab1 */ + { 179, 238, 58, 5559 }, /* OliveDrab2 */ + { 154, 205, 50, 5570 }, /* OliveDrab3 */ + { 105, 139, 34, 5581 }, /* OliveDrab4 */ + { 255, 165, 0, 5592 }, /* orange */ + { 255, 69, 0, 5599 }, /* orange red */ + { 255, 165, 0, 5610 }, /* orange1 */ + { 238, 154, 0, 5618 }, /* orange2 */ + { 205, 133, 0, 5626 }, /* orange3 */ + { 139, 90, 0, 5634 }, /* orange4 */ + { 255, 69, 0, 5642 }, /* OrangeRed */ + { 255, 69, 0, 5652 }, /* OrangeRed1 */ + { 238, 64, 0, 5663 }, /* OrangeRed2 */ + { 205, 55, 0, 5674 }, /* OrangeRed3 */ + { 139, 37, 0, 5685 }, /* OrangeRed4 */ + { 218, 112, 214, 5696 }, /* orchid */ + { 255, 131, 250, 5703 }, /* orchid1 */ + { 238, 122, 233, 5711 }, /* orchid2 */ + { 205, 105, 201, 5719 }, /* orchid3 */ + { 139, 71, 137, 5727 }, /* orchid4 */ + { 238, 232, 170, 5735 }, /* pale goldenrod */ + { 152, 251, 152, 5750 }, /* pale green */ + { 175, 238, 238, 5761 }, /* pale turquoise */ + { 219, 112, 147, 5776 }, /* pale violet red */ + { 238, 232, 170, 5792 }, /* PaleGoldenrod */ + { 152, 251, 152, 5806 }, /* PaleGreen */ + { 154, 255, 154, 5816 }, /* PaleGreen1 */ + { 144, 238, 144, 5827 }, /* PaleGreen2 */ + { 124, 205, 124, 5838 }, /* PaleGreen3 */ + { 84, 139, 84, 5849 }, /* PaleGreen4 */ + { 175, 238, 238, 5860 }, /* PaleTurquoise */ + { 187, 255, 255, 5874 }, /* PaleTurquoise1 */ + { 174, 238, 238, 5889 }, /* PaleTurquoise2 */ + { 150, 205, 205, 5904 }, /* PaleTurquoise3 */ + { 102, 139, 139, 5919 }, /* PaleTurquoise4 */ + { 219, 112, 147, 5934 }, /* PaleVioletRed */ + { 255, 130, 171, 5948 }, /* PaleVioletRed1 */ + { 238, 121, 159, 5963 }, /* PaleVioletRed2 */ + { 205, 104, 137, 5978 }, /* PaleVioletRed3 */ + { 139, 71, 93, 5993 }, /* PaleVioletRed4 */ + { 255, 239, 213, 6008 }, /* papaya whip */ + { 255, 239, 213, 6020 }, /* PapayaWhip */ + { 255, 218, 185, 6031 }, /* peach puff */ + { 255, 218, 185, 6042 }, /* PeachPuff */ + { 255, 218, 185, 6052 }, /* PeachPuff1 */ + { 238, 203, 173, 6063 }, /* PeachPuff2 */ + { 205, 175, 149, 6074 }, /* PeachPuff3 */ + { 139, 119, 101, 6085 }, /* PeachPuff4 */ + { 205, 133, 63, 6096 }, /* peru */ + { 255, 192, 203, 6101 }, /* pink */ + { 255, 181, 197, 6106 }, /* pink1 */ + { 238, 169, 184, 6112 }, /* pink2 */ + { 205, 145, 158, 6118 }, /* pink3 */ + { 139, 99, 108, 6124 }, /* pink4 */ + { 221, 160, 221, 6130 }, /* plum */ + { 255, 187, 255, 6135 }, /* plum1 */ + { 238, 174, 238, 6141 }, /* plum2 */ + { 205, 150, 205, 6147 }, /* plum3 */ + { 139, 102, 139, 6153 }, /* plum4 */ + { 176, 224, 230, 6159 }, /* powder blue */ + { 176, 224, 230, 6171 }, /* PowderBlue */ + { 160, 32, 240, 6182 }, /* purple */ + { 155, 48, 255, 6189 }, /* purple1 */ + { 145, 44, 238, 6197 }, /* purple2 */ + { 125, 38, 205, 6205 }, /* purple3 */ + { 85, 26, 139, 6213 }, /* purple4 */ + { 255, 0, 0, 6221 }, /* red */ + { 255, 0, 0, 6225 }, /* red1 */ + { 238, 0, 0, 6230 }, /* red2 */ + { 205, 0, 0, 6235 }, /* red3 */ + { 139, 0, 0, 6240 }, /* red4 */ + { 188, 143, 143, 6245 }, /* rosy brown */ + { 188, 143, 143, 6256 }, /* RosyBrown */ + { 255, 193, 193, 6266 }, /* RosyBrown1 */ + { 238, 180, 180, 6277 }, /* RosyBrown2 */ + { 205, 155, 155, 6288 }, /* RosyBrown3 */ + { 139, 105, 105, 6299 }, /* RosyBrown4 */ + { 65, 105, 225, 6310 }, /* royal blue */ + { 65, 105, 225, 6321 }, /* RoyalBlue */ + { 72, 118, 255, 6331 }, /* RoyalBlue1 */ + { 67, 110, 238, 6342 }, /* RoyalBlue2 */ + { 58, 95, 205, 6353 }, /* RoyalBlue3 */ + { 39, 64, 139, 6364 }, /* RoyalBlue4 */ + { 139, 69, 19, 6375 }, /* saddle brown */ + { 139, 69, 19, 6388 }, /* SaddleBrown */ + { 250, 128, 114, 6400 }, /* salmon */ + { 255, 140, 105, 6407 }, /* salmon1 */ + { 238, 130, 98, 6415 }, /* salmon2 */ + { 205, 112, 84, 6423 }, /* salmon3 */ + { 139, 76, 57, 6431 }, /* salmon4 */ + { 244, 164, 96, 6439 }, /* sandy brown */ + { 244, 164, 96, 6451 }, /* SandyBrown */ + { 46, 139, 87, 6462 }, /* sea green */ + { 46, 139, 87, 6472 }, /* SeaGreen */ + { 84, 255, 159, 6481 }, /* SeaGreen1 */ + { 78, 238, 148, 6491 }, /* SeaGreen2 */ + { 67, 205, 128, 6501 }, /* SeaGreen3 */ + { 46, 139, 87, 6511 }, /* SeaGreen4 */ + { 255, 245, 238, 6521 }, /* seashell */ + { 255, 245, 238, 6530 }, /* seashell1 */ + { 238, 229, 222, 6540 }, /* seashell2 */ + { 205, 197, 191, 6550 }, /* seashell3 */ + { 139, 134, 130, 6560 }, /* seashell4 */ + { 160, 82, 45, 6570 }, /* sienna */ + { 255, 130, 71, 6577 }, /* sienna1 */ + { 238, 121, 66, 6585 }, /* sienna2 */ + { 205, 104, 57, 6593 }, /* sienna3 */ + { 139, 71, 38, 6601 }, /* sienna4 */ + { 135, 206, 235, 6609 }, /* sky blue */ + { 135, 206, 235, 6618 }, /* SkyBlue */ + { 135, 206, 255, 6626 }, /* SkyBlue1 */ + { 126, 192, 238, 6635 }, /* SkyBlue2 */ + { 108, 166, 205, 6644 }, /* SkyBlue3 */ + { 74, 112, 139, 6653 }, /* SkyBlue4 */ + { 106, 90, 205, 6662 }, /* slate blue */ + { 112, 128, 144, 6673 }, /* slate gray */ + { 112, 128, 144, 6684 }, /* slate grey */ + { 106, 90, 205, 6695 }, /* SlateBlue */ + { 131, 111, 255, 6705 }, /* SlateBlue1 */ + { 122, 103, 238, 6716 }, /* SlateBlue2 */ + { 105, 89, 205, 6727 }, /* SlateBlue3 */ + { 71, 60, 139, 6738 }, /* SlateBlue4 */ + { 112, 128, 144, 6749 }, /* SlateGray */ + { 198, 226, 255, 6759 }, /* SlateGray1 */ + { 185, 211, 238, 6770 }, /* SlateGray2 */ + { 159, 182, 205, 6781 }, /* SlateGray3 */ + { 108, 123, 139, 6792 }, /* SlateGray4 */ + { 112, 128, 144, 6803 }, /* SlateGrey */ + { 255, 250, 250, 6813 }, /* snow */ + { 255, 250, 250, 6818 }, /* snow1 */ + { 238, 233, 233, 6824 }, /* snow2 */ + { 205, 201, 201, 6830 }, /* snow3 */ + { 139, 137, 137, 6836 }, /* snow4 */ + { 0, 255, 127, 6842 }, /* spring green */ + { 0, 255, 127, 6855 }, /* SpringGreen */ + { 0, 255, 127, 6867 }, /* SpringGreen1 */ + { 0, 238, 118, 6880 }, /* SpringGreen2 */ + { 0, 205, 102, 6893 }, /* SpringGreen3 */ + { 0, 139, 69, 6906 }, /* SpringGreen4 */ + { 70, 130, 180, 6919 }, /* steel blue */ + { 70, 130, 180, 6930 }, /* SteelBlue */ + { 99, 184, 255, 6940 }, /* SteelBlue1 */ + { 92, 172, 238, 6951 }, /* SteelBlue2 */ + { 79, 148, 205, 6962 }, /* SteelBlue3 */ + { 54, 100, 139, 6973 }, /* SteelBlue4 */ + { 210, 180, 140, 6984 }, /* tan */ + { 255, 165, 79, 6988 }, /* tan1 */ + { 238, 154, 73, 6993 }, /* tan2 */ + { 205, 133, 63, 6998 }, /* tan3 */ + { 139, 90, 43, 7003 }, /* tan4 */ + { 216, 191, 216, 7008 }, /* thistle */ + { 255, 225, 255, 7016 }, /* thistle1 */ + { 238, 210, 238, 7025 }, /* thistle2 */ + { 205, 181, 205, 7034 }, /* thistle3 */ + { 139, 123, 139, 7043 }, /* thistle4 */ + { 255, 99, 71, 7052 }, /* tomato */ + { 255, 99, 71, 7059 }, /* tomato1 */ + { 238, 92, 66, 7067 }, /* tomato2 */ + { 205, 79, 57, 7075 }, /* tomato3 */ + { 139, 54, 38, 7083 }, /* tomato4 */ + { 64, 224, 208, 7091 }, /* turquoise */ + { 0, 245, 255, 7101 }, /* turquoise1 */ + { 0, 229, 238, 7112 }, /* turquoise2 */ + { 0, 197, 205, 7123 }, /* turquoise3 */ + { 0, 134, 139, 7134 }, /* turquoise4 */ + { 238, 130, 238, 7145 }, /* violet */ + { 208, 32, 144, 7152 }, /* violet red */ + { 208, 32, 144, 7163 }, /* VioletRed */ + { 255, 62, 150, 7173 }, /* VioletRed1 */ + { 238, 58, 140, 7184 }, /* VioletRed2 */ + { 205, 50, 120, 7195 }, /* VioletRed3 */ + { 139, 34, 82, 7206 }, /* VioletRed4 */ + { 245, 222, 179, 7217 }, /* wheat */ + { 255, 231, 186, 7223 }, /* wheat1 */ + { 238, 216, 174, 7230 }, /* wheat2 */ + { 205, 186, 150, 7237 }, /* wheat3 */ + { 139, 126, 102, 7244 }, /* wheat4 */ + { 255, 255, 255, 7251 }, /* white */ + { 245, 245, 245, 7257 }, /* white smoke */ + { 245, 245, 245, 7269 }, /* WhiteSmoke */ + { 255, 255, 0, 7280 }, /* yellow */ + { 154, 205, 50, 7287 }, /* yellow green */ + { 255, 255, 0, 7300 }, /* yellow1 */ + { 238, 238, 0, 7308 }, /* yellow2 */ + { 205, 205, 0, 7316 }, /* yellow3 */ + { 139, 139, 0, 7324 }, /* yellow4 */ + { 154, 205, 50, 7332 }, /* YellowGreen */ +}; + +#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) +{ + const BuiltinColor *c; + int low, mid, high; + int r; + + (void)screen; + + low = 0; + high = NUM_BUILTIN_COLORS - 1; + while (high >= low) + { + mid = (low + high) / 2; + c = &BuiltinColors[mid]; + r = strncasecmp (&BuiltinColorNames[c->name], name, len); + if (r == 0 && len == strlen (&BuiltinColorNames[c->name])) + { + *pred = c->red; + *pgreen = c->green; + *pblue = c->blue; + return 1; + } + if (r < 0) + low = mid + 1; + else + high = mid - 1; + } + return 0; +} diff --git a/src/x11-color.h b/src/x11-color.h new file mode 100644 index 00000000..cfaa0849 --- /dev/null +++ b/src/x11-color.h @@ -0,0 +1,5 @@ +/* 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); diff --git a/src/x11.cc b/src/x11.cc index b8cd4cbb..2b088fcc 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -41,7 +41,7 @@ #include #include #include -#include "x11.h" +#include "gui.h" #ifdef BUILD_IMLIB2 #include "imlib2.h" #endif /* BUILD_IMLIB2 */ @@ -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,37 +91,10 @@ 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 - if (!out_to_x.get(l)) { return false; } + if (!out_to_x.get(l) || !display || !window.window) { return false; } int major, minor; @@ -210,128 +171,11 @@ 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 <> -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: 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,29 +183,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( - "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_XDBE priv::use_xdbe_setting use_xdbe; @@ -405,8 +231,14 @@ static void init_X11() { ? dispstr.c_str() : nullptr; if ((display = XOpenDisplay(disp)) == nullptr) { - throw std::runtime_error(std::string("can't open display: ") + - XDisplayName(disp)); + std::string err = std::string("can't open display: ") + + XDisplayName(disp); +#ifdef BUILD_WAYLAND + fprintf(stderr, "%s\n", err.c_str()); + return; +#else + throw std::runtime_error(err); +#endif } } @@ -494,6 +326,8 @@ static Window find_desktop_window(Window *p_root, Window *p_desktop) { int format, i; unsigned long nitems, bytes; unsigned int n; + if (!display) + return 0; Window root = RootWindow(display, screen); Window win; Window troot, parent, *children; @@ -636,10 +470,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; @@ -969,6 +803,10 @@ static void init_window(lua::state &l __attribute__((unused)), bool own) { if (window.window == 0u) { window.window = find_desktop_window(&window.root, &window.desktop); } + if (window.window == 0u) { + return; + } + window.visual = DefaultVisual(display, screen); window.colourmap = DefaultColormap(display, screen); 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