Merge pull request #152 from bendardenne/32bit-drawables

Use 4-byte -c option to allow compositors to use translucency as an alternate blurring method, thus speeding up blurring and allowing for dynamic background. Somewhat addresses #129.
This commit is contained in:
Raymond Li 2020-04-17 14:41:27 -04:00 committed by GitHub
commit b386a984e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 105 deletions

View File

@ -37,9 +37,9 @@ screen (you can configure the color/an image). You can return to your screen by
entering your password.
.SH IMPROVEMENTS
.IP \[bu] 2
i3lock forks, so you can combine it with an alias to suspend to RAM (run "i3lock && echo mem > /sys/power/state" to get a locked screen after waking up your computer from suspend to RAM)
i3lock forks, so you can combine it with an alias to suspend to RAM
(run "i3lock && echo mem > /sys/power/state" to get a locked screen after waking up your computer from suspend to RAM)
.IP \[bu]
You can specify either a background color or a PNG image which will be displayed while your screen is locked.
.IP \[bu]
@ -47,7 +47,6 @@ You can specify whether i3lock should bell upon a wrong password.
.IP \[bu]
i3lock uses PAM and therefore is compatible with LDAP, etc.
.SH OPTIONS
.TP
.B \-v, \-\-version
@ -87,7 +86,6 @@ the remaining bits, in that order.
.Vb 6
\& --raw=1920x1080:rgb
.Ve
You can use ImageMagicks
.IR convert(1)
program to feed raw images into i3lock:
@ -95,22 +93,21 @@ program to feed raw images into i3lock:
.Vb 6
\& convert wallpaper.jpg RGB:- | i3lock --raw 3840x2160:rgb --image /dev/stdin
.Ve
This allows you to load a variety of image formats without i3lock having to
support each one explicitly.
You can also use it to resize images to the screen ratio:
.Vb 6
\& convert wallpaper.jpg -resize $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/') RGB:- | i3lock --raw $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/'):rgb --image /dev/stdin
.Ve
Note that $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/') gets you the current screen dimensions in the wxh (e.g. 1920x1080) format.
Note that $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/')
gets you the current screen dimensions in the wxh (e.g. 1920x1080) format.
.TP
.BI \-c\ rrggbb \fR,\ \fB\-\-color= rrggbb
Turn the screen into the given color instead of white. Color must be given in 3-byte
format: rrggbb (i.e. ff0000 is red).
.BI \-c\ rrggbbaa \fR,\ \fB\-\-color= rrggbbaa
Turn the screen into the given color instead of white. Color must be given in 4-byte
format: rrggbbaa (i.e. ff0000ff is opaque red).
Use the last byte for alpha. Setting this below FF (i.e. ff000088) will allow your screen to be shown translucently if you use a compositor (e.g. compton, xcompmgr).
.TP
.B \-t, \-\-tiling
@ -154,6 +151,8 @@ Note that this number is zero indexed. The ordering is dependent on libxinerama.
.B \-B=sigma, \-\-blur=sigma
Captures the screen and blurs it using the given sigma (radius).
Images may still be overlaid over the blurred screenshot.
As an alternative to this option, you could specify a translucent background color
(-c option) with a fully transparent or translucent color, and use a compositor to perform blurring (e.g. compton, picom).
.TP
.B \-\-indicator
@ -164,23 +163,21 @@ Forces the indicator to always be visible, instead of only showing on activity.
Displays the keylayout. Positionable similar to date, time, and indicator. Modes are as follows:
.RS
.RS
0 - Displays the full string returned by the query, i.e. "English (US)"
1 - Displays up until the first parenthesis, i.e. "English"
2 - Displays just the contents of the parenthesis, i.e. "US"
.RE
.RE
.TP
.B \-k, \-\-clock, \-\-force\-clock
Displays the clock. \-\-force\-clock also displays the clock when there's indicator text (useful for when the clock is not positioned with the indicator).
Displays the clock. \-\-force\-clock also displays the clock when there's indicator text
(useful for when the clock is not positioned with the indicator).
.TP
.B \-\-composite
Some compositors have problems with i3lock trying to render over them, so this argument is disabled by default. However, some will work properly with it, so it's been left enabled.
Some compositors have problems with i3lock trying to render over them, so this argument is disabled by default.
However, some will work properly with it, so it's been left enabled.
.TP
.B \-\-pass\-media\-keys
@ -260,19 +257,13 @@ Sets the color of the keyboard layout text.
.TP
.B \-\-indpos="x position:y position"
Sets the position for the unlock indicator. Valid variables include:
.RS
.RS
x - x position of the current display. Corresponds to the leftmost row of pixels on that display.
y - y position of the current display. Corresponds to the topmost row of pixels on that display.
w - width of the current display.
h - height of the current display.
r - the unlock indicator radius.
.RE
.RE
@ -287,28 +278,21 @@ Sets the format used for generating the time string. See strftime(3) for a full
.TP
.B \-\-timepos="x position:y position"
Sets the position for the time string. All the variables from \-\-indpos may be used, in addition to:
.RS
.RS
ix - the x value of the indicator on the current display.
iy - the y value of the indicator on the current display.
.RE
.RE
.TP
.B \-\-time\-align, \-\-date\-align, \-\-layout\-align, \-\-verif\-align, \-\-wrong\-align, \-\-modif\-align, \-\-greeter\-align
Sets the text alignment of the time, date, keylayout, verification text, wrong text, modifier text and greeter text.
.RS
.RS
0 - centered (default)
1 - left aligned
2 - right aligned
.RE
.RE
@ -331,13 +315,10 @@ Sets the font size used to render various strings.
.TP
.B \-\-datepos="x position:y position"
Sets the position for the date string. All the variables from \-\-indpos and \-\-timepos may be used, in addition to:
.RS
.RS
tx - the computed x value of the timestring, for the current display.
ty - the computed y value of the timestring, for the current display.
.RE
.RE
@ -355,7 +336,8 @@ Sets the position for the date string. All the variables from \-\-indpos and \-\
.TP
.B \-\-refresh\-rate=seconds\-as\-double
The refresh rate of the indicator, given in seconds. This should automatically align itself, but is somewhat buggy currently. Values less than one will work, but may result in poor system performance.
The refresh rate of the indicator, given in seconds. This should automatically align itself, but is somewhat buggy currently.
Values less than one will work, but may result in poor system performance.
.TP
.B \-\-veriftext="text"
@ -391,7 +373,8 @@ Replaces the usual ring indicator with a bar indicator, with a variety of option
.TP
.B \-\-redraw\-thread
Starts a separate thread for redrawing the screen. Potentially worse for security, but makes the bar indicator still do its usual periodic redraws when PAM is authenticating.
Starts a separate thread for redrawing the screen. Potentially worse for security, but makes the bar indicator still do
its usual periodic redraws when PAM is authenticating.
.TP
.B \-\-bar\-direction={0, 1, 2}
@ -407,15 +390,18 @@ Sets whether the bar is vertically or horizontally oriented. Defaults to horizon
.TP
.B \-\-bar\-step
Sets the step that each bar decreases by when a key is pressed. A random bar is set to its max height, and then each neighbor is set to (height - step*distance).
Sets the step that each bar decreases by when a key is pressed. A random bar is set to its max height,
and then each neighbor is set to (height - step*distance).
.TP
.B \-\-bar\-max\-height
The maximum height a bar can get to. When a key is pressed, a random bar is set to this value, and then its neighbors are set to its height, minus the step value.
The maximum height a bar can get to. When a key is pressed, a random bar is set to this value,
and then its neighbors are set to its height, minus the step value.
.TP
.B \-\-bar\-base\-width
The thickness of the "base" bar that all the bars originate from. This bar also takes on the ring verif and wrong colors to give authentication feedback.
The thickness of the "base" bar that all the bars originate from.
This bar also takes on the ring verif and wrong colors to give authentication feedback.
.TP
.B \-\-bar\-color
@ -427,24 +413,21 @@ The value by which the bars decrease each time the screen is redrawn.
.TP
.B \-\-bar\-position
Works similarly to the time/date/indicator expressions. If the bar is horizontal, this sets the vertical offset from the top edge. If it's vertically oriented, this sets the horizontal offset from the left edge.
Works similarly to the time/date/indicator expressions. If the bar is horizontal, this sets the vertical offset from the top edge.
If it's vertically oriented, this sets the horizontal offset from the left edge.
.TP
.B \-\-no\-verify
Do not verify the password entered by the user and unlock immediately. Use only for quickly testing new configurations and remember to remove to actually lock your screen!
Do not verify the password entered by the user and unlock immediately.
.B Use only for quickly testing new configurations and remember to remove to actually lock your screen!
.SH DPMS
The \-d (\-\-dpms) option was removed from i3lock in version 2.8. There were
plenty of use-cases that were not properly addressed, and plenty of bugs
surrounding that feature. While features are not normally removed from i3 and
its tools, we felt the need to make an exception in this case.
Users who wish to explicitly enable DPMS only when their screen is locked can
use a wrapper script around i3lock like the following:
.Vb 6
\& #!/bin/sh
\& revert() {
@ -455,7 +438,6 @@ use a wrapper script around i3lock like the following:
\& i3lock -n
\& revert
.Ve
The \-I (\-\-inactivity\-timeout=seconds) was removed because it only makes sense with DPMS.
.SH SEE ALSO

View File

@ -70,7 +70,7 @@
typedef void (*ev_callback_t)(EV_P_ ev_timer *w, int revents);
static void input_done(void);
char color[7] = "ffffff";
char color[9] = "ffffffff";
/* options for unlock indicator colors */
char insidevercolor[9] = "006effbf";
@ -1497,6 +1497,19 @@ int main(int argc, char *argv[]) {
char *optstring = "hvnbdc:p:ui:teI:frsS:kB:m";
char *arg = NULL;
int opt = 0;
#define parse_color(acolor)\
arg = optarg;\
if (arg[0] == '#') arg++;\
if (strlen(arg) == 6) {\
/* If 6 digits given, assume RGB and pad 0xff for alpha */\
char padded[9] = "ffffffff"; \
strncpy( padded, arg, 6 );\
arg = padded;\
}\
if (strlen(arg) != 8 || sscanf(arg, "%08[0-9a-fA-F]", acolor) != 1)\
errx(1, #acolor " is invalid, color must be given in 3 or 4-byte format: rrggbb[aa]\n");
while ((o = getopt_long(argc, argv, optstring, longopts, &longoptind)) != -1) {
switch (o) {
case 'v':
@ -1514,18 +1527,6 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Inactivity timeout only makes sense with DPMS, which was removed. Please see the manpage i3lock(1).\n");
break;
}
case 'c': {
arg = optarg;
/* Skip # if present */
if (arg[0] == '#')
arg++;
if (strlen(arg) != 6 || sscanf(arg, "%06[0-9a-fA-F]", color) != 1)
errx(EXIT_FAILURE, "color is invalid, it must be given in 3-byte hexadecimal format: rrggbb");
break;
}
case 'u':
unlock_indicator = false;
break;
@ -1575,11 +1576,9 @@ int main(int argc, char *argv[]) {
break;
// Begin colors
#define parse_color(color)\
arg = optarg;\
if (arg[0] == '#') arg++;\
if (strlen(arg) != 8 || sscanf(arg, "%08[0-9a-fA-F]", color) != 1)\
errx(1, #color " is invalid, color must be given in 4-byte format: rrggbbaa\n");
case 'c':
parse_color(color);
break;
case 300:
parse_color(insidevercolor);
break;
@ -2206,14 +2205,16 @@ int main(int argc, char *argv[]) {
cairo_surface_destroy(xcb_img);
}
/* Pixmap on which the image is rendered to (if any) */
xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
xcb_window_t stolen_focus = find_focused_window(conn, screen->root);
/* Open the fullscreen window, already with the correct pixmap in place */
win = open_fullscreen_window(conn, screen, color, bg_pixmap);
xcb_free_pixmap(conn, bg_pixmap);
win = open_fullscreen_window(conn, screen, color);
xcb_pixmap_t pixmap = create_bg_pixmap(conn, win, last_resolution, color);
draw_image(last_resolution, pixmap);
xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap});
xcb_free_pixmap(conn, pixmap);
if (blur_pixmap) {
xcb_free_pixmap(conn, *blur_pixmap);
free(blur_pixmap);

View File

@ -71,7 +71,7 @@ unsigned long lastCheck;
/* Whether the image should be tiled. */
extern bool tile;
/* The background color to use (in hex). */
extern char color[7];
extern char color[9];
/* indicator color options */
extern char insidevercolor[9];
extern char insidewrongcolor[9];
@ -675,16 +675,14 @@ static void draw_elements(cairo_t *const ctx, DrawData const *const draw_data) {
* resolution and returns it.
*
*/
xcb_pixmap_t draw_image(uint32_t *resolution) {
void draw_image(uint32_t *resolution, xcb_drawable_t drawable) {
const double scaling_factor = get_dpi_value() / 96.0;
xcb_pixmap_t bg_pixmap = XCB_NONE;
int button_diameter_physical = ceil(scaling_factor * BUTTON_DIAMETER);
DEBUG("scaling_factor is %.f, physical diameter is %d px\n",
scaling_factor, button_diameter_physical);
if (!vistype)
vistype = get_root_visual_type(screen);
bg_pixmap = create_bg_pixmap(conn, screen, resolution, color);
vistype = get_visualtype_by_depth(32, screen);
/* 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.
@ -696,7 +694,7 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
// cairo_set_font_face(ctx, get_font_face(0));
cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]);
cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, drawable, vistype, resolution[0], resolution[1]);
cairo_t *xcb_ctx = cairo_create(xcb_output);
/*update image according to the slideshow_interval*/
@ -1064,7 +1062,6 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
cairo_surface_destroy(output);
cairo_destroy(ctx);
cairo_destroy(xcb_ctx);
return bg_pixmap;
}
/*
@ -1073,12 +1070,11 @@ xcb_pixmap_t draw_image(uint32_t *resolution) {
*/
void redraw_screen(void) {
DEBUG("redraw_screen(unlock_state = %d, auth_state = %d) @ [%lu]\n", unlock_state, auth_state, (unsigned long)time(NULL));
xcb_pixmap_t bg_pixmap = draw_image(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_pixmap_t pixmap = create_bg_pixmap(conn, win, last_resolution, color);
draw_image(last_resolution, pixmap);
xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){pixmap});
xcb_clear_area(conn, 0, win, 0, 0, last_resolution[0], last_resolution[1]);
xcb_free_pixmap(conn, bg_pixmap);
xcb_free_pixmap(conn, pixmap);
xcb_flush(conn);
}

View File

@ -38,7 +38,7 @@ typedef struct {
double bar_offset;
} DrawData;
xcb_pixmap_t draw_image(uint32_t* resolution);
void draw_image(uint32_t* resolution, xcb_drawable_t drawable);
void init_colors_once(void);
void redraw_screen(void);
void clear_indicator(void);

68
xcb.c
View File

@ -82,16 +82,37 @@ static unsigned char mask_windows_bits[] = {
0x80, 0x01};
static uint32_t get_colorpixel(char *hex) {
char strgroups[3][3] = {{hex[0], hex[1], '\0'},
char strgroups[4][3] = {{hex[0], hex[1], '\0'},
{hex[2], hex[3], '\0'},
{hex[4], hex[5], '\0'}};
uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)),
{hex[4], hex[5], '\0'},
{hex[6], hex[4], '\0'}};
uint32_t rgb16[4] = {(strtol(strgroups[0], NULL, 16)),
(strtol(strgroups[1], NULL, 16)),
(strtol(strgroups[2], NULL, 16))};
(strtol(strgroups[2], NULL, 16)),
(strtol(strgroups[3], NULL, 16))};
return (rgb16[0] << 16) + (rgb16[1] << 8) + rgb16[2];
return (rgb16[3] << 24) + (rgb16[0] << 16) + (rgb16[1] << 8) + rgb16[2];
}
xcb_visualtype_t *get_visualtype_by_depth(uint16_t depth, xcb_screen_t *root_screen) {
xcb_depth_iterator_t depth_iter;
depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
if (depth_iter.data->depth != depth)
continue;
xcb_visualtype_iterator_t visual_iter;
visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
if (!visual_iter.rem)
continue;
return visual_iter.data;
}
return NULL;
}
xcb_visualtype_t *get_root_visual_type(xcb_screen_t *screen) {
xcb_visualtype_t *visual_type = NULL;
xcb_depth_iterator_t depth_iter;
@ -114,10 +135,9 @@ xcb_visualtype_t *get_root_visual_type(xcb_screen_t *screen) {
return NULL;
}
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t *resolution, char *color) {
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_drawable_t win, u_int32_t *resolution, char *color) {
xcb_pixmap_t bg_pixmap = xcb_generate_id(conn);
xcb_create_pixmap(conn, scr->root_depth, bg_pixmap, scr->root,
resolution[0], resolution[1]);
xcb_create_pixmap(conn, 32, bg_pixmap, win, resolution[0], resolution[1]);
/* Generate a Graphics Context and fill the pixmap with background color
* (for images that are smaller than your screen) */
@ -131,9 +151,9 @@ xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32
return bg_pixmap;
}
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap) {
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color) {
uint32_t mask = 0;
uint32_t values[3];
uint32_t values[5];
xcb_window_t win = xcb_generate_id(conn);
xcb_window_t parent_win = scr->root;
@ -161,26 +181,32 @@ xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, c
}
}
if (pixmap == XCB_NONE) {
mask |= XCB_CW_BACK_PIXEL;
values[0] = get_colorpixel(color);
} else {
mask |= XCB_CW_BACK_PIXMAP;
values[0] = pixmap;
}
xcb_visualid_t visual = get_visualtype_by_depth(32, scr)->visual_id;
xcb_colormap_t win_colormap = xcb_generate_id(conn);
xcb_create_colormap(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, scr->root, visual);
mask |= XCB_CW_BACK_PIXEL;
values[0] = get_colorpixel(color);
mask |= XCB_CW_BORDER_PIXEL;
values[1] = 0x00000000;
mask |= XCB_CW_OVERRIDE_REDIRECT;
values[1] = 1;
values[2] = 1;
mask |= XCB_CW_EVENT_MASK;
values[2] = XCB_EVENT_MASK_EXPOSURE |
values[3] = XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_VISIBILITY_CHANGE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY;
mask |= XCB_CW_COLORMAP;
values[4] = win_colormap;
xcb_create_window(conn,
XCB_COPY_FROM_PARENT,
32,
win, /* the window id */
parent_win,
0, 0,
@ -188,7 +214,7 @@ xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, c
scr->height_in_pixels, /* dimensions */
0, /* border = 0, we draw our own */
XCB_WINDOW_CLASS_INPUT_OUTPUT,
XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
visual, /* copy visual from parent */
mask,
values);

5
xcb.h
View File

@ -24,8 +24,9 @@ extern xcb_connection_t *conn;
extern xcb_screen_t *screen;
xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s);
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t *resolution, char *color);
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap);
xcb_visualtype_t* get_visualtype_by_depth(uint16_t depth, xcb_screen_t* root_screen);
xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_drawable_t drawable, u_int32_t *resolution, char *color);
xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color);
bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor, int tries);
xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice);
xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t root);