From 12a06184e733554bafc76e643b49067fcd758fc0 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Tue, 6 Oct 2020 14:33:05 +0200 Subject: Merge the upstream changes from i3lock --- .clang-format | 1 + .travis.yml | 6 +----- configure.ac | 1 + i3lock.c | 14 +++++++------ i3lock.h | 9 ++++---- travis/Dockerfile | 4 ++-- unlock_indicator.c | 61 ++++++++++++++++++++++++++++++++++-------------------- unlock_indicator.h | 5 ++++- 8 files changed, 61 insertions(+), 40 deletions(-) diff --git a/.clang-format b/.clang-format index 1d84013..6e49d83 100644 --- a/.clang-format +++ b/.clang-format @@ -8,3 +8,4 @@ IndentWidth: 4 PointerBindsToType: false ColumnLimit: 0 SpaceBeforeParens: ControlStatements +SortIncludes: false diff --git a/.travis.yml b/.travis.yml index 15ad1e4..6e929e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,11 +7,7 @@ language: c compiler: - gcc - clang -addons: - apt: - packages: - - clang-format-3.5 script: - - clang-format-3.5 -i *.[ch] && git diff --exit-code || (echo 'Code was not formatted using clang-format!'; false) - docker build --pull --no-cache --rm -t=i3lock -f travis/Dockerfile . + - docker run -e CC=$CC -v $PWD:/usr/src:rw i3lock /bin/sh -c 'clang-format-9 -i *.[ch] && git diff --exit-code || (echo "Code was not formatted using clang-format!"; false)' - docker run -e CC=$CC -v $PWD:/usr/src:rw i3lock /bin/sh -c 'autoreconf -fi && mkdir -p build && cd build && (../configure || (cat config.log; false)) && make -j V=1 CFLAGS="-Wformat -Wformat-security -Wextra -Wno-unused-parameter -Werror"' diff --git a/configure.ac b/configure.ac index 79f23a9..699e5a6 100644 --- a/configure.ac +++ b/configure.ac @@ -66,6 +66,7 @@ AC_FUNC_FORK AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK AC_FUNC_STRNLEN AC_CHECK_FUNCS([atexit dup2 ftruncate getcwd gettimeofday localtime_r memchr memset mkdir rmdir setlocale socket strcasecmp strchr strdup strerror strncasecmp strndup strrchr strspn strstr strtol strtoul], , [AC_MSG_FAILURE([cannot find the $ac_func function, which i3lock requires])]) +AC_CHECK_FUNCS([explicit_bzero]) # Checks for libraries. diff --git a/i3lock.c b/i3lock.c index 4ef0f73..f7c5bdc 100644 --- a/i3lock.c +++ b/i3lock.c @@ -46,7 +46,6 @@ #include #endif #include -#include #include #include #include @@ -54,7 +53,7 @@ #include #include #include -#ifdef __OpenBSD__ +#ifdef HAVE_EXPLICIT_BZERO #include /* explicit_bzero(3) */ #endif #include @@ -153,7 +152,7 @@ bool skip_repeated_empty_password = false; * Decrements i to point to the previous unicode glyph * */ -void u8_dec(char *s, int *i) { +static void u8_dec(char *s, int *i) { (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || isutf(s[--(*i)]) || --(*i)); } @@ -223,7 +222,7 @@ static bool load_compose_table(const char *locale) { * */ static void clear_password_memory(void) { -#ifdef __OpenBSD__ +#ifdef HAVE_EXPLICIT_BZERO /* Use explicit_bzero(3) which was explicitly designed not to be * optimized out by the compiler. */ explicit_bzero(password, strlen(password)); @@ -664,7 +663,7 @@ static void process_xkb_event(xcb_generic_event_t *gevent) { * and also redraw the image, if any. * */ -void handle_screen_resize(void) { +static void handle_screen_resize(void) { xcb_get_geometry_cookie_t geomc; xcb_get_geometry_reply_t *geom; geomc = xcb_get_geometry(conn, screen->root); @@ -1119,6 +1118,8 @@ int main(int argc, char *argv[]) { err(EXIT_FAILURE, "getpwuid() failed"); if ((username = pw->pw_name) == NULL) errx(EXIT_FAILURE, "pw->pw_name is NULL."); + if (getenv("WAYLAND_DISPLAY") != NULL) + errx(EXIT_FAILURE, "i3lock is a program for X11 and does not work on Wayland. Try https://github.com/swaywm/swaylock instead"); #ifdef EXTRAS char *optstring = "hvnbDdELc:B:G:F:J:O:R:r:S:T:W:X:x:Y:y:Z:p:ui:teI:f"; @@ -1497,7 +1498,8 @@ int main(int argc, char *argv[]) { free(image_raw_format); /* Pixmap on which the image is rendered to (if any) */ - xcb_pixmap_t bg_pixmap = draw_image(last_resolution); + xcb_pixmap_t bg_pixmap = create_bg_pixmap(conn, screen, last_resolution, color); + draw_image(bg_pixmap, last_resolution); xcb_window_t stolen_focus = find_focused_window(conn, screen->root); diff --git a/i3lock.h b/i3lock.h index 57190e5..6cf7694 100644 --- a/i3lock.h +++ b/i3lock.h @@ -5,10 +5,11 @@ * This is important because xautolock (for example) closes stdout/stderr by * default, so just printing something to stdout will lead to the data ending * up on the X11 socket (!). */ -#define DEBUG(fmt, ...) \ - do { \ - if (debug_mode) \ - printf("[i3lock-debug] " fmt, ##__VA_ARGS__); \ +#define DEBUG(fmt, ...) \ + do { \ + if (debug_mode) { \ + fprintf(stderr, "[i3lock-extended-debug] " fmt, ##__VA_ARGS__); \ + } \ } while (0) #endif diff --git a/travis/Dockerfile b/travis/Dockerfile index 5381276..cc2dd7d 100644 --- a/travis/Dockerfile +++ b/travis/Dockerfile @@ -11,7 +11,7 @@ RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry # (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now. # Install mk-build-deps (for installing the i3 build dependencies), -# clang and clang-format-3.8 (for checking formatting and building with clang), +# clang and clang-format-9 (for checking formatting and building with clang), # lintian (for checking spelling errors), # test suite dependencies (for running tests) RUN apt-get update && \ @@ -19,7 +19,7 @@ RUN apt-get update && \ build-essential clang git autoconf automake libxcb-randr0-dev pkg-config libpam0g-dev \ libcairo2-dev libxcb1-dev libxcb-dpms0-dev libxcb-image0-dev libxcb-util0-dev \ libxcb-xrm-dev libev-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev \ - libxkbcommon-x11-dev && \ + libxkbcommon-x11-dev clang-format-9 && \ rm -rf /var/lib/apt/lists/* WORKDIR /usr/src diff --git a/unlock_indicator.c b/unlock_indicator.c index 3d98a5f..73320cb 100644 --- a/unlock_indicator.c +++ b/unlock_indicator.c @@ -50,9 +50,9 @@ #define BUTTON_CENTER (BUTTON_RADIUS + 5) #define BUTTON_DIAMETER (2 * BUTTON_SPACE) -/****************************************************************************** +/******************************************************************************* * Variables defined in i3lock.c. - *****************************************************************************/ + ******************************************************************************/ extern bool debug_mode; @@ -100,16 +100,16 @@ extern bool show_failed_attempts; /* Number of failed unlock attempts. */ extern int failed_attempts; -/****************************************************************************** +/******************************************************************************* * Variables defined in xcb.c. - *****************************************************************************/ + ******************************************************************************/ /* The root screen, to determine the DPI. */ extern xcb_screen_t *screen; -/****************************************************************************** +/******************************************************************************* * Local variables. - *****************************************************************************/ + ******************************************************************************/ /* Cache the screen’s visual, necessary for creating a Cairo context. */ static xcb_visualtype_t *vistype; @@ -124,8 +124,7 @@ auth_state_t auth_state; * resolution and returns it. * */ -xcb_pixmap_t draw_image(uint32_t *resolution) { - xcb_pixmap_t bg_pixmap = XCB_NONE; +void draw_image(xcb_pixmap_t bg_pixmap, uint32_t *resolution) { const double scaling_factor = get_dpi_value() / 96.0; int button_diameter_physical = ceil(scaling_factor * BUTTON_DIAMETER); DEBUG("scaling_factor is %.f, physical diameter is %d px\n", @@ -133,7 +132,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { if (!vistype) vistype = get_root_visual_type(screen); - bg_pixmap = create_bg_pixmap(conn, screen, resolution, color); + /* Initialize cairo: Create one in-memory surface to render the unlock * indicator on, create one XCB surface to actually draw (one or more, * depending on the amount of screens) unlock indicators on. */ @@ -143,6 +142,19 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); cairo_t *xcb_ctx = cairo_create(xcb_output); + /* After the first iteration, the pixmap will still contain the previous + * contents. Explicitly clear the entire pixmap with the background color + * first to get back into a defined state: */ + char strgroups[3][3] = {{color[0], color[1], '\0'}, + {color[2], color[3], '\0'}, + {color[4], color[5], '\0'}}; + uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), + (strtol(strgroups[1], NULL, 16)), + (strtol(strgroups[2], NULL, 16))}; + cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0); + cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); + cairo_fill(xcb_ctx); + if (img) { if (!tile) { cairo_set_source_surface(xcb_ctx, img, 0, 0); @@ -157,16 +169,6 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_fill(xcb_ctx); cairo_pattern_destroy(pattern); } - } else { - char strgroups[3][3] = {{color[0], color[1], '\0'}, - {color[2], color[3], '\0'}, - {color[4], color[5], '\0'}}; - uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), - (strtol(strgroups[1], NULL, 16)), - (strtol(strgroups[2], NULL, 16))}; - cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0); - cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); - cairo_fill(xcb_ctx); } if (unlock_indicator && @@ -394,7 +396,18 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { cairo_surface_destroy(output); cairo_destroy(ctx); cairo_destroy(xcb_ctx); - return bg_pixmap; +} + +static xcb_pixmap_t bg_pixmap = XCB_NONE; + +/* + * Releases the current background pixmap so that the next redraw_screen() call + * will allocate a new one with the updated resolution. + * + */ +void free_bg_pixmap(void) { + xcb_free_pixmap(conn, bg_pixmap); + bg_pixmap = XCB_NONE; } /* @@ -403,12 +416,16 @@ xcb_pixmap_t draw_image(uint32_t *resolution) { */ void redraw_screen(void) { DEBUG("redraw_screen(unlock_state = %d, auth_state = %d)\n", unlock_state, auth_state); - xcb_pixmap_t bg_pixmap = draw_image(last_resolution); + if (bg_pixmap == XCB_NONE) { + DEBUG("allocating pixmap for %d x %d px\n", last_resolution[0], last_resolution[1]); + bg_pixmap = create_bg_pixmap(conn, screen, last_resolution, color); + } + + draw_image(bg_pixmap, last_resolution); xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){bg_pixmap}); /* XXX: Possible optimization: Only update the area in the middle of the * screen instead of the whole screen. */ xcb_clear_area(conn, 0, win, 0, 0, last_resolution[0], last_resolution[1]); - xcb_free_pixmap(conn, bg_pixmap); xcb_flush(conn); } diff --git a/unlock_indicator.h b/unlock_indicator.h index 93c1de8..581d028 100644 --- a/unlock_indicator.h +++ b/unlock_indicator.h @@ -1,6 +1,8 @@ #ifndef _UNLOCK_INDICATOR_H #define _UNLOCK_INDICATOR_H +#include + typedef enum { STATE_STARTED = 0, /* default state */ STATE_KEY_PRESSED = 1, /* key was pressed, show unlock indicator */ @@ -19,7 +21,8 @@ typedef enum { STATE_I3LOCK_LOCK_FAILED = 4, /* i3lock failed to load */ } auth_state_t; -xcb_pixmap_t draw_image(uint32_t* resolution); +void free_bg_pixmap(void); +void draw_image(xcb_pixmap_t bg_pixmap, uint32_t* resolution); void redraw_screen(void); void clear_indicator(void); -- cgit v1.3