Feature for #1078: Configurable swaylock colors

Colors are configured through the command line so that swaylock conforms
to the i3lock fork 'github.com/chrjguill/i3lock-color'. Differences from
it are that one letter options '-r' and '-s' are not implimentend because
'-s' is already used by '--scaling' in swaylock.
This commit also fixed whitespace in 'include/swaylock/swaylock.h' and
changed `parse_color` in 'common/util.h' so that it can accept colors
that do not start with a hash. This was done to keep compatability with
the i3lock fork.
This commit is contained in:
Calvin Lee 2017-02-21 12:49:22 -07:00
parent 4930451e32
commit 84335e3cee
2 changed files with 211 additions and 37 deletions

211
main.c
View File

@ -18,9 +18,11 @@
#include "swaylock/swaylock.h" #include "swaylock/swaylock.h"
#include "ipc-client.h" #include "ipc-client.h"
#include "log.h" #include "log.h"
#include "util.h"
struct registry *registry; struct registry *registry;
struct render_data render_data; struct render_data render_data;
struct lock_config *config;
bool show_indicator = true; bool show_indicator = true;
void wl_dispatch_events() { void wl_dispatch_events() {
@ -35,7 +37,7 @@ void sigalarm_handler(int sig) {
signal(SIGALRM, SIG_IGN); signal(SIGALRM, SIG_IGN);
// Hide typing indicator // Hide typing indicator
render_data.auth_state = AUTH_STATE_IDLE; render_data.auth_state = AUTH_STATE_IDLE;
render(&render_data); render(&render_data, config);
wl_display_flush(registry->display); wl_display_flush(registry->display);
signal(SIGALRM, sigalarm_handler); signal(SIGALRM, sigalarm_handler);
} }
@ -55,6 +57,36 @@ void sway_terminate(int exit_code) {
char *password; char *password;
int password_size; int password_size;
int line_source = 0;
struct lock_config *init_config() {
struct lock_config *config = calloc(1, sizeof(struct lock_config));
config->font = strdup("sans-serif");
config->colors.text = 0x000000FF;
config->colors.line = 0x000000FF;
config->colors.separator = 0x000000FF;
config->colors.input_cursor = 0x33DB00FF;
config->colors.backspace_cursor = 0xDB3300FF;
config->colors.normal.inner_ring = 0x000000BF;
config->colors.normal.outer_ring = 0x337D00FF;
config->colors.validating.inner_ring = 0x0072FFBF;
config->colors.validating.outer_ring = 0x3300FAFF;
config->colors.invalid.inner_ring = 0xFA0000BF;
config->colors.invalid.outer_ring = 0x7D3300FF;
return config;
}
void free_config(struct lock_config *config) {
free(config->font);
free(config);
}
int function_conversation(int num_msg, const struct pam_message **msg, int function_conversation(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr) { struct pam_response **resp, void *appdata_ptr) {
@ -123,7 +155,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
case XKB_KEY_Return: case XKB_KEY_Return:
render_data.auth_state = AUTH_STATE_VALIDATING; render_data.auth_state = AUTH_STATE_VALIDATING;
render(&render_data); render(&render_data, config);
// Make sure our render call will actually be displayed on the screen // Make sure our render call will actually be displayed on the screen
wl_dispatch_events(); wl_dispatch_events();
@ -207,7 +239,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
} }
} }
if (redraw_screen) { if (redraw_screen) {
render(&render_data); render(&render_data, config);
wl_dispatch_events(); wl_dispatch_events();
// Hide the indicator after a couple of seconds // Hide the indicator after a couple of seconds
alarm(5); alarm(5);
@ -315,6 +347,7 @@ int main(int argc, char **argv) {
const char *scaling_mode_str = "fit", *socket_path = NULL; const char *scaling_mode_str = "fit", *socket_path = NULL;
int i; int i;
void *images = NULL; void *images = NULL;
config = init_config();
render_data.num_images = 0; render_data.num_images = 0;
render_data.color_set = 0; render_data.color_set = 0;
@ -335,21 +368,47 @@ int main(int argc, char **argv) {
{"socket", required_argument, NULL, 'p'}, {"socket", required_argument, NULL, 'p'},
{"no-unlock-indicator", no_argument, NULL, 'u'}, {"no-unlock-indicator", no_argument, NULL, 'u'},
{"daemonize", no_argument, NULL, 'f'}, {"daemonize", no_argument, NULL, 'f'},
{"font", required_argument, NULL, 0},
{"line-uses-ring", no_argument, NULL, 0},
{"line-uses-inside", no_argument, NULL, 0},
{"textcolor", required_argument, NULL, 0},
{"insidevercolor", required_argument, NULL, 0},
{"insidewrongcolor", required_argument, NULL, 0},
{"insidecolor", required_argument, NULL, 0},
{"ringvercolor", required_argument, NULL, 0},
{"ringwrongcolor", required_argument, NULL, 0},
{"ringcolor", required_argument, NULL, 0},
{"linecolor", required_argument, NULL, 0},
{"separatorcolor", required_argument, NULL, 0},
{"keyhlcolor", required_argument, NULL, 0},
{"bshlcolor", required_argument, NULL, 0},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
const char *usage = const char *usage =
"Usage: swaylock [options...]\n" "Usage: swaylock [options...]\n"
"\n" "\n"
" -h, --help Show help message and quit.\n" " -h, --help Show help message and quit.\n"
" -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n"
" -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n"
" -t, --tiling Same as --scaling=tile.\n" " -t, --tiling Same as --scaling=tile.\n"
" -v, --version Show the version number and quit.\n" " -v, --version Show the version number and quit.\n"
" -i, --image [<output>:]<path> Display the given image.\n" " -i, --image [<output>:]<path> Display the given image.\n"
" -u, --no-unlock-indicator Disable the unlock indicator.\n" " -u, --no-unlock-indicator Disable the unlock indicator.\n"
" -f, --daemonize Detach from the controlling terminal.\n" " -f, --daemonize Detach from the controlling terminal.\n"
" --socket <socket> Use the specified socket.\n"; " --socket <socket> Use the specified socket.\n"
" --font <font> Use the specified font instead of sans-serif.\n"
" --textcolor <rrggbb[aa]> Sets the color of the text.\n"
" --insidevercolor <rrggbb[aa]> Sets the color of the verifying indicator circle.\n"
" --insidewrongcolor <rrggbb[aa]> Sets the color of the invalid indicator circle.\n"
" --insidecolor <rrggbb[aa]> Sets the color of the typing or idle indicator circle.\n"
" --ringvercolor <rrggbb[aa]> Sets the color of the verifying indicator ring.\n"
" --ringwrongcolor <rrggbb[aa]> Sets the color of the invalid indicator ring.\n"
" --ringcolor <rrggbb[aa]> Sets the color of the typing or idle indicator ring.\n"
" --linecolor <rrggbb[aa]> Sets the color of the line that separates the indicator.\n"
" --separatorcolor <rrggbb[aa]> Sets the color of the line that separates highlight segments.\n"
" --keyhlcolor <rrggbb[aa]> Sets the color of keypress highlight segments.\n"
" --bshlcolor <rrggbb[aa]> Sets the color of keypress highlight segments.\n";
registry = registry_poll(); registry = registry_poll();
@ -364,18 +423,8 @@ int main(int argc, char **argv) {
switch (c) { switch (c) {
case 'c': case 'c':
{ {
int colorlen = strlen(optarg); render_data.color = parse_color(optarg);
if (colorlen < 6 || colorlen == 7 || colorlen > 8) {
sway_log(L_ERROR, "color must be specified in 3 or 4 byte format, i.e. rrggbb or rrggbbaa");
exit(EXIT_FAILURE);
}
render_data.color = strtol(optarg, NULL, 16);
render_data.color_set = 1; render_data.color_set = 1;
if (colorlen == 6) {
render_data.color <<= 8;
render_data.color |= 0xFF;
}
break; break;
} }
case 'i': case 'i':
@ -431,6 +480,59 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
break; break;
case 0:
if (strcmp(long_options[option_index].name, "font") == 0) {
free(config->font);
config->font = strdup(optarg);
}
else if (strcmp(long_options[option_index].name, "line-uses-ring") == 0) {
if (line_source != 0) {
sway_log(L_ERROR, "Line source options conflict");
exit(EXIT_FAILURE);
}
line_source = 1;
}
else if (strcmp(long_options[option_index].name, "line-uses-inside") == 0) {
if (line_source != 0) {
sway_log(L_ERROR, "Line source options conflict");
exit(EXIT_FAILURE);
}
line_source = 2;
}
else if (strcmp(long_options[option_index].name, "textcolor") == 0) {
config->colors.text = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "insidevercolor") == 0) {
config->colors.validating.inner_ring = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "insidewrongcolor") == 0) {
config->colors.invalid.inner_ring = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "insidecolor") == 0) {
config->colors.normal.inner_ring = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "ringvercolor") == 0) {
config->colors.validating.outer_ring = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "ringwrongcolor") == 0) {
config->colors.invalid.outer_ring = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "ringcolor") == 0) {
config->colors.normal.outer_ring = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "linecolor") == 0) {
config->colors.line = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "separatorcolor") == 0) {
config->colors.separator = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "keyhlcolor") == 0) {
config->colors.input_cursor = parse_color(optarg);
}
else if (strcmp(long_options[option_index].name, "bshlcolor") == 0) {
config->colors.backspace_cursor = parse_color(optarg);
}
break;
default: default:
fprintf(stderr, "%s", usage); fprintf(stderr, "%s", usage);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -524,7 +626,7 @@ int main(int argc, char **argv) {
free(displays_paths); free(displays_paths);
} }
render(&render_data); render(&render_data, config);
bool locked = false; bool locked = false;
while (wl_display_dispatch(registry->display) != -1) { while (wl_display_dispatch(registry->display) != -1) {
if (!locked) { if (!locked) {
@ -556,10 +658,12 @@ int main(int argc, char **argv) {
list_free(render_data.surfaces); list_free(render_data.surfaces);
registry_teardown(registry); registry_teardown(registry);
free_config(config);
return 0; return 0;
} }
void render(struct render_data *render_data) { void render(struct render_data *render_data, struct lock_config *config) {
int i; int i;
for (i = 0; i < render_data->surfaces->length; ++i) { for (i = 0; i < render_data->surfaces->length; ++i) {
sway_log(L_DEBUG, "Render surface %d of %d", i, render_data->surfaces->length); sway_log(L_DEBUG, "Render surface %d of %d", i, render_data->surfaces->length);
@ -609,21 +713,21 @@ void render(struct render_data *render_data) {
switch (render_data->auth_state) { switch (render_data->auth_state) {
case AUTH_STATE_INPUT: case AUTH_STATE_INPUT:
case AUTH_STATE_BACKSPACE: { case AUTH_STATE_BACKSPACE: {
cairo_set_source_rgba(window->cairo, 0, 0, 0, 0.75); cairo_set_source_u32(window->cairo, config->colors.normal.inner_ring);
cairo_fill_preserve(window->cairo); cairo_fill_preserve(window->cairo);
cairo_set_source_rgb(window->cairo, 51.0 / 255, 125.0 / 255, 0); cairo_set_source_u32(window->cairo, config->colors.normal.outer_ring);
cairo_stroke(window->cairo); cairo_stroke(window->cairo);
} break; } break;
case AUTH_STATE_VALIDATING: { case AUTH_STATE_VALIDATING: {
cairo_set_source_rgba(window->cairo, 0, 114.0 / 255, 255.0 / 255, 0.75); cairo_set_source_u32(window->cairo, config->colors.validating.inner_ring);
cairo_fill_preserve(window->cairo); cairo_fill_preserve(window->cairo);
cairo_set_source_rgb(window->cairo, 51.0 / 255, 0, 250.0 / 255); cairo_set_source_u32(window->cairo, config->colors.validating.outer_ring);
cairo_stroke(window->cairo); cairo_stroke(window->cairo);
} break; } break;
case AUTH_STATE_INVALID: { case AUTH_STATE_INVALID: {
cairo_set_source_rgba(window->cairo, 250.0 / 255, 0, 0, 0.75); cairo_set_source_u32(window->cairo, config->colors.invalid.inner_ring);
cairo_fill_preserve(window->cairo); cairo_fill_preserve(window->cairo);
cairo_set_source_rgb(window->cairo, 125.0 / 255, 51.0 / 255, 0); cairo_set_source_u32(window->cairo, config->colors.invalid.outer_ring);
cairo_stroke(window->cairo); cairo_stroke(window->cairo);
} break; } break;
default: break; default: break;
@ -631,8 +735,8 @@ void render(struct render_data *render_data) {
// Draw a message // Draw a message
char *text = NULL; char *text = NULL;
cairo_set_source_rgb(window->cairo, 0, 0, 0); cairo_set_source_u32(window->cairo, config->colors.text);
cairo_select_font_face(window->cairo, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_select_font_face(window->cairo, config->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(window->cairo, ARC_RADIUS/3.0f); cairo_set_font_size(window->cairo, ARC_RADIUS/3.0f);
switch (render_data->auth_state) { switch (render_data->auth_state) {
case AUTH_STATE_VALIDATING: case AUTH_STATE_VALIDATING:
@ -664,14 +768,14 @@ void render(struct render_data *render_data) {
highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5;
cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_RANGE);
if (render_data->auth_state == AUTH_STATE_INPUT) { if (render_data->auth_state == AUTH_STATE_INPUT) {
cairo_set_source_rgb(window->cairo, 51.0 / 255, 219.0 / 255, 0); cairo_set_source_u32(window->cairo, config->colors.input_cursor);
} else { } else {
cairo_set_source_rgb(window->cairo, 219.0 / 255, 51.0 / 255, 0); cairo_set_source_u32(window->cairo, config->colors.backspace_cursor);
} }
cairo_stroke(window->cairo); cairo_stroke(window->cairo);
// Draw borders // Draw borders
cairo_set_source_rgb(window->cairo, 0, 0, 0); cairo_set_source_u32(window->cairo, config->colors.separator);
cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS);
cairo_stroke(window->cairo); cairo_stroke(window->cairo);
@ -679,8 +783,41 @@ void render(struct render_data *render_data) {
cairo_stroke(window->cairo); cairo_stroke(window->cairo);
} }
if (line_source == 1) {
switch(render_data->auth_state) {
case AUTH_STATE_VALIDATING: {
cairo_set_source_u32(window->cairo, config->colors.validating.outer_ring);
break;
}
case AUTH_STATE_INVALID: {
cairo_set_source_u32(window->cairo, config->colors.invalid.outer_ring);
break;
}
default: {
cairo_set_source_u32(window->cairo, config->colors.normal.outer_ring);
}
}
}
else if (line_source == 2) {
switch(render_data->auth_state) {
case AUTH_STATE_VALIDATING: {
cairo_set_source_u32(window->cairo, config->colors.validating.inner_ring);
break;
}
case AUTH_STATE_INVALID: {
cairo_set_source_u32(window->cairo, config->colors.invalid.inner_ring);
break;
}
default: {
cairo_set_source_u32(window->cairo, config->colors.normal.inner_ring);
break;
}
}
}
else {
cairo_set_source_u32(window->cairo, config->colors.line);
}
// Draw inner + outer border of the circle // Draw inner + outer border of the circle
cairo_set_source_rgb(window->cairo, 0, 0, 0);
cairo_set_line_width(window->cairo, 2.0); cairo_set_line_width(window->cairo, 2.0);
cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS - ARC_THICKNESS/2, 0, 2*M_PI); cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS - ARC_THICKNESS/2, 0, 2*M_PI);
cairo_stroke(window->cairo); cairo_stroke(window->cairo);

View File

@ -45,6 +45,43 @@ Options
Use the specified socket path. Otherwise, swaymsg will ask sway where the Use the specified socket path. Otherwise, swaymsg will ask sway where the
socket is (which is the value of $SWAYSOCK, then of $I3SOCK). socket is (which is the value of $SWAYSOCK, then of $I3SOCK).
*--font* <font>::
Sets the font of the text inside the indicator.
*--textcolor* <rrggbb[aa]>::
Sets the color of the text inside the indicator.
*--insidevercolor* <rrggbb[aa]>::
Sets the color of the inside of the indicator when verifying.
*--insidewrongcolor* <rrggbb[aa]>::
Sets the color of the inside of the indicator when invalid.
*--insidecolor* <rrggbb[aa]>::
Sets the color of the inside of the indicator when typing or idle.
*--ringvercolor* <rrggbb[aa]>::
Sets the color of the outside of the indicator when verifying.
*--ringwrongcolor* <rrggbb[aa]>::
Sets the color of the outside of the indicator when invalid.
*--ringcolor* <rrggbb[aa]>::
Sets the color of the outside of the indicator when typing or idle.
*--linecolor* <rrggbb[aa]>::
Sets the color of the lines that separate the inside and outside of the
indicator.
*--separatorcolor* <rrggbb[aa]>::
Sets the color of the lines that seperate highlight segments.
*--keyhlcolor* <rrggbb[aa]>::
Sets the color of keypress highlight segments.
*--bshlcolor* <rrggbb[aa]>::
Sets the color of backspace highlight segments.
Authors Authors
------- -------