mirror of
https://github.com/Raymo111/i3lock-color.git
synced 2024-12-02 14:05:43 -05:00
feat(control char): add basic control char support (#238)
* feat(control char): add basic control char support * feat(control char): fix wrong x when \n after \b * feat(control char): add `\t` support, same behavior as `\t` in c printf * Gonna go with 4 spaces per tab to be safer * fix(control chars): leading control chars run into 'out of bounds memory acessing', and render at wrong position * doc(control chars): describe the control chars behavior and declare the influenced options and bump date to SEP 2021. * update to NOV * Bump years * Redo manpage Co-authored-by: Raymond Li <hi@raymond.li>
This commit is contained in:
parent
fbf109178c
commit
1e284b9488
3 changed files with 158 additions and 17 deletions
60
i3lock.1
60
i3lock.1
|
@ -8,7 +8,7 @@
|
||||||
.fi
|
.fi
|
||||||
..
|
..
|
||||||
|
|
||||||
.TH i3lock-color 1 "JUN 2021" Linux "User Manuals"
|
.TH i3lock-color 1 "JAN 2022" Linux "User Manuals"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
i3lock-color \- improved screen locker
|
i3lock-color \- improved screen locker
|
||||||
|
@ -240,6 +240,23 @@ Sets the color of the status text while verifying and when password is wrong.
|
||||||
.B \-\-{layout, time, date, greeter}\-color=rrggbbaa
|
.B \-\-{layout, time, date, greeter}\-color=rrggbbaa
|
||||||
Sets text colors.
|
Sets text colors.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-\-keylayout mode
|
||||||
|
Displays the keylayout. Positionable similar to date, time, and indicator.
|
||||||
|
Modes are as follows:
|
||||||
|
.RS
|
||||||
|
.IP \[bu] 2
|
||||||
|
0 - Displays the full string returned by the query, i.e. "English (US)"
|
||||||
|
.IP \[bu]
|
||||||
|
1 - Displays up until the first parenthesis, i.e. "English"
|
||||||
|
.IP \[bu]
|
||||||
|
2 - Displays just the contents of the parenthesis, i.e. "US"
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B For all following -str or -text options, some control characters
|
||||||
|
.B (i.e. \\\\n, \\\\t) are supported. See \fBCONTROL CHARACTERS\fR
|
||||||
|
.B for more details.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-time\-str="%H:%M:%S"
|
.B \-\-time\-str="%H:%M:%S"
|
||||||
Sets the format used for generating the time string.
|
Sets the format used for generating the time string.
|
||||||
|
@ -257,19 +274,6 @@ Sets the string to be shown while verifying the password/input/key/etc.
|
||||||
.B \-\-wrong\-text="wrong!"
|
.B \-\-wrong\-text="wrong!"
|
||||||
Sets the string to be shown upon entering an incorrect password.
|
Sets the string to be shown upon entering an incorrect password.
|
||||||
|
|
||||||
.TP
|
|
||||||
.B \-\-keylayout mode
|
|
||||||
Displays the keylayout. Positionable similar to date, time, and indicator.
|
|
||||||
Modes are as follows:
|
|
||||||
.RS
|
|
||||||
.IP \[bu] 2
|
|
||||||
0 - Displays the full string returned by the query, i.e. "English (US)"
|
|
||||||
.IP \[bu]
|
|
||||||
1 - Displays up until the first parenthesis, i.e. "English"
|
|
||||||
.IP \[bu]
|
|
||||||
2 - Displays just the contents of the parenthesis, i.e. "US"
|
|
||||||
.RE
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-noinput\-text="no input"
|
.B \-\-noinput\-text="no input"
|
||||||
Sets the string to be shown upon pressing backspace without anything to delete.
|
Sets the string to be shown upon pressing backspace without anything to delete.
|
||||||
|
@ -484,6 +488,25 @@ The interval to wait until switching to the next image.
|
||||||
.B \-\-slideshow\-random\-selection
|
.B \-\-slideshow\-random\-selection
|
||||||
Randomize the order of the images.
|
Randomize the order of the images.
|
||||||
|
|
||||||
|
.SH CONTROL CHARACTERS
|
||||||
|
Control characters (\\r \\n \\b \\t) are supported in text OPTIONS. Their behavior
|
||||||
|
are almost as same as anywhere else.
|
||||||
|
.TP
|
||||||
|
.B Carriage Return(\\\\r)
|
||||||
|
Move to the start of line (left edge).
|
||||||
|
Notes: The rendered characters would still live there.
|
||||||
|
.TP
|
||||||
|
.B Line Feed(\\\\n)
|
||||||
|
Move to start of next line (left edge).
|
||||||
|
.TP
|
||||||
|
.B Backspace(\\\\b)
|
||||||
|
Overwrite last one char if exists.
|
||||||
|
Notes: The rendered character would still live there.
|
||||||
|
.TP
|
||||||
|
.B Tab(\\\\t)
|
||||||
|
Move to next tab stop position.The width of one character for moving is as same as character 'a'.
|
||||||
|
Note: The width may be strange if the font is not mono-spaced.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.IR xautolock(1)
|
.IR xautolock(1)
|
||||||
\- use i3lock as your screen saver
|
\- use i3lock as your screen saver
|
||||||
|
@ -491,7 +514,14 @@ Randomize the order of the images.
|
||||||
.IR convert(1)
|
.IR convert(1)
|
||||||
\- feed a wide variety of image formats to i3lock
|
\- feed a wide variety of image formats to i3lock
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH HOMEPAGE
|
||||||
|
https://github.com/Raymo111/i3lock-color
|
||||||
|
|
||||||
|
Please report bugs and submit pull-requests as follows:
|
||||||
|
For i3lock (upstream): https://github.com/i3/i3lock
|
||||||
|
For i3lock-color (enhancements on top of i3lock): https://github.com/Raymo111/i3lock-color
|
||||||
|
|
||||||
|
.SH AUTHORS
|
||||||
Michael Stapelberg <michael+i3lock at stapelberg dot de>
|
Michael Stapelberg <michael+i3lock at stapelberg dot de>
|
||||||
|
|
||||||
Jan-Erik Rediger <badboy at archlinux.us>
|
Jan-Erik Rediger <badboy at archlinux.us>
|
||||||
|
|
|
@ -256,6 +256,14 @@ static cairo_font_face_t *font_faces[6] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static control_char_config_t control_characters[] = {
|
||||||
|
{'\n', CC_POS_RESET, 0, CC_POS_CHANGE, 1},
|
||||||
|
{'\b', CC_POS_CHANGE, -1, CC_POS_KEEP, 0},
|
||||||
|
{'\r', CC_POS_RESET, 0, CC_POS_KEEP, 0},
|
||||||
|
{'\t', CC_POS_TAB, 4, CC_POS_KEEP, 0},
|
||||||
|
};
|
||||||
|
size_t control_char_count = sizeof control_characters / sizeof(control_char_config_t);
|
||||||
|
|
||||||
static cairo_font_face_t *get_font_face(int which) {
|
static cairo_font_face_t *get_font_face(int which) {
|
||||||
if (font_faces[which]) {
|
if (font_faces[which]) {
|
||||||
return font_faces[which];
|
return font_faces[which];
|
||||||
|
@ -314,6 +322,94 @@ static cairo_font_face_t *get_font_face(int which) {
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Splits the given text by "control chars",
|
||||||
|
* And then draws the given text onto the cairo context.
|
||||||
|
*/
|
||||||
|
static void draw_text_with_cc(cairo_t *ctx, text_t text, double start_x) {
|
||||||
|
// get scaled_font
|
||||||
|
cairo_scaled_font_t *sft;
|
||||||
|
cairo_matrix_t fm, ctm;
|
||||||
|
cairo_matrix_init_scale(&fm, text.size, text.size);
|
||||||
|
cairo_get_matrix(ctx, &ctm);
|
||||||
|
cairo_font_options_t *opts;
|
||||||
|
opts = cairo_font_options_create();
|
||||||
|
sft = cairo_scaled_font_create(text.font, &fm, &ctm, opts);
|
||||||
|
cairo_font_options_destroy(opts);
|
||||||
|
/* use `a` to represent common character width, using in `\t` */
|
||||||
|
cairo_text_extents_t te;
|
||||||
|
cairo_text_extents(ctx, "a", &te);
|
||||||
|
|
||||||
|
// convert text to glyphs.
|
||||||
|
cairo_status_t status;
|
||||||
|
cairo_glyph_t* glyphs;
|
||||||
|
int nglyphs = 0,
|
||||||
|
len = 0,
|
||||||
|
start = 0,
|
||||||
|
lineno = 0,
|
||||||
|
x = start_x,
|
||||||
|
y = text.y;
|
||||||
|
size_t cur_cc;
|
||||||
|
|
||||||
|
while (text.str[start + len] != '\0') {
|
||||||
|
char is_cc = 0;
|
||||||
|
do {
|
||||||
|
for (cur_cc = 0; cur_cc < control_char_count; cur_cc++) {
|
||||||
|
if (text.str[start+len] == control_characters[cur_cc].character) {
|
||||||
|
is_cc = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (text.str[start+(len++)] != '\0' && !is_cc);
|
||||||
|
if (len > is_cc) {
|
||||||
|
status = cairo_scaled_font_text_to_glyphs(
|
||||||
|
sft, x, y, text.str + start, is_cc ? len - 1: len,
|
||||||
|
&glyphs, &nglyphs,
|
||||||
|
NULL, NULL, NULL
|
||||||
|
);
|
||||||
|
if (status == CAIRO_STATUS_SUCCESS) {
|
||||||
|
cairo_glyph_path(ctx, glyphs, nglyphs);
|
||||||
|
} else {
|
||||||
|
DEBUG("draw %c failed\n", text.str[start]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_cc && (cur_cc < control_char_count)) {
|
||||||
|
if (control_characters[cur_cc].x_behavior == CC_POS_CHANGE) {
|
||||||
|
char x_offset = control_characters[cur_cc].x_behavior_arg;
|
||||||
|
if (x_offset < 0 && x_offset > -nglyphs) {
|
||||||
|
x = glyphs[nglyphs+x_offset].x;
|
||||||
|
} else if (x_offset > 0) {
|
||||||
|
if (nglyphs >= 1) { // the case is some leading control chars.(although there is none now)
|
||||||
|
x = glyphs[nglyphs - 1].x + x_offset * te.x_advance;
|
||||||
|
} else { // deal the leading control chars.
|
||||||
|
x += x_offset * te.x_advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (control_characters[cur_cc].x_behavior == CC_POS_RESET) {
|
||||||
|
x = start_x;
|
||||||
|
} else if (control_characters[cur_cc].x_behavior == CC_POS_TAB) {
|
||||||
|
if (nglyphs > 0) { // there may be leading tab, such as '\t\t' or '\n\t'
|
||||||
|
int advance = control_characters[cur_cc].x_behavior_arg - ((nglyphs - 1) % control_characters[cur_cc].x_behavior_arg);
|
||||||
|
x = glyphs[nglyphs - 1].x + advance * te.x_advance;
|
||||||
|
} else { // deal the leading tab.
|
||||||
|
x += control_characters[cur_cc].x_behavior_arg * te.x_advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (control_characters[cur_cc].y_behavior == CC_POS_CHANGE) {
|
||||||
|
lineno += control_characters[cur_cc].y_behavior_arg;
|
||||||
|
} // CC_POS_KEEP is default for y
|
||||||
|
}
|
||||||
|
y = text.y + text.size * lineno;
|
||||||
|
if (len > is_cc) {
|
||||||
|
cairo_glyph_free(glyphs);
|
||||||
|
}
|
||||||
|
nglyphs = 0;
|
||||||
|
start += len;
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
cairo_scaled_font_destroy(sft);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Draws the given text onto the cairo context
|
* Draws the given text onto the cairo context
|
||||||
*/
|
*/
|
||||||
|
@ -342,9 +438,8 @@ static void draw_text(cairo_t *ctx, text_t text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_set_source_rgba(ctx, text.color.red, text.color.green, text.color.blue, text.color.alpha);
|
cairo_set_source_rgba(ctx, text.color.red, text.color.green, text.color.blue, text.color.alpha);
|
||||||
cairo_move_to(ctx, x, text.y);
|
|
||||||
|
|
||||||
cairo_text_path(ctx, text.str);
|
draw_text_with_cc(ctx, text, x);
|
||||||
cairo_fill_preserve(ctx);
|
cairo_fill_preserve(ctx);
|
||||||
|
|
||||||
cairo_set_source_rgba(ctx, text.outline_color.red, text.outline_color.green, text.outline_color.blue, text.outline_color.alpha);
|
cairo_set_source_rgba(ctx, text.outline_color.red, text.outline_color.green, text.outline_color.blue, text.outline_color.alpha);
|
||||||
|
|
|
@ -47,6 +47,22 @@ typedef enum {
|
||||||
MAX,
|
MAX,
|
||||||
} background_type_t;
|
} background_type_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CC_POS_RESET,
|
||||||
|
CC_POS_CHANGE,
|
||||||
|
CC_POS_KEEP,
|
||||||
|
CC_POS_TAB
|
||||||
|
} control_char_pos_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char character;
|
||||||
|
control_char_pos_t x_behavior;
|
||||||
|
int x_behavior_arg;
|
||||||
|
control_char_pos_t y_behavior;
|
||||||
|
int y_behavior_arg;
|
||||||
|
} control_char_config_t;
|
||||||
|
|
||||||
void render_lock(uint32_t* resolution, xcb_drawable_t drawable);
|
void render_lock(uint32_t* resolution, xcb_drawable_t drawable);
|
||||||
void draw_image(uint32_t* resolution, cairo_surface_t* img, cairo_t* xcb_ctx);
|
void draw_image(uint32_t* resolution, cairo_surface_t* img, cairo_t* xcb_ctx);
|
||||||
void init_colors_once(void);
|
void init_colors_once(void);
|
||||||
|
|
Loading…
Reference in a new issue