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
|
||||
..
|
||||
|
||||
.TH i3lock-color 1 "JUN 2021" Linux "User Manuals"
|
||||
.TH i3lock-color 1 "JAN 2022" Linux "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
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
|
||||
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
|
||||
.B \-\-time\-str="%H:%M:%S"
|
||||
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!"
|
||||
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
|
||||
.B \-\-noinput\-text="no input"
|
||||
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
|
||||
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
|
||||
.IR xautolock(1)
|
||||
\- use i3lock as your screen saver
|
||||
|
@ -491,7 +514,14 @@ Randomize the order of the images.
|
|||
.IR convert(1)
|
||||
\- 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>
|
||||
|
||||
Jan-Erik Rediger <badboy at archlinux.us>
|
||||
|
|
|
@ -256,6 +256,14 @@ static cairo_font_face_t *font_faces[6] = {
|
|||
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) {
|
||||
if (font_faces[which]) {
|
||||
return font_faces[which];
|
||||
|
@ -314,6 +322,94 @@ static cairo_font_face_t *get_font_face(int which) {
|
|||
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
|
||||
*/
|
||||
|
@ -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_move_to(ctx, x, text.y);
|
||||
|
||||
cairo_text_path(ctx, text.str);
|
||||
draw_text_with_cc(ctx, text, x);
|
||||
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);
|
||||
|
|
|
@ -47,6 +47,22 @@ typedef enum {
|
|||
MAX,
|
||||
} 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 draw_image(uint32_t* resolution, cairo_surface_t* img, cairo_t* xcb_ctx);
|
||||
void init_colors_once(void);
|
||||
|
|
Loading…
Reference in a new issue