From dd3db16c108d77837ce660b62ff53f0943e6f51c Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 18 Jul 2022 22:17:37 +0200 Subject: [PATCH] Adding key_indicator that shows the status of 'Caps Lock', 'Num Lock' and 'Scroll Lock' in i3status output. --- .gitignore | 2 ++ i3status.c | 24 ++++++++++++++++++++ include/i3status.h | 8 +++++++ meson.build | 6 ++++- src/print_key_indicator.c | 46 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/print_key_indicator.c diff --git a/.gitignore b/.gitignore index 36cd436..0f6f57e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ man/i3status.1 # it is up to you to arrange for it to be ignored by git, # e.g. by listing your directory in .git/info/exclude. /build + +.vscode diff --git a/i3status.c b/i3status.c index 3922bf2..8141f95 100644 --- a/i3status.c +++ b/i3status.c @@ -443,6 +443,18 @@ int main(int argc, char *argv[]) { CFG_CUSTOM_SEP_BLOCK_WIDTH_OPT, CFG_END()}; + cfg_opt_t key_indicator_opts[] = { + CFG_STR("format", "%content", CFGF_NONE), + CFG_STR("format_bad", "%title - %errno: %error", CFGF_NONE), + CFG_STR("path", NULL, CFGF_NONE), + CFG_INT("max_characters", 255, CFGF_NONE), + CFG_CUSTOM_ALIGN_OPT, + CFG_CUSTOM_COLOR_OPTS, + CFG_CUSTOM_MIN_WIDTH_OPT, + CFG_CUSTOM_SEPARATOR_OPT, + CFG_CUSTOM_SEP_BLOCK_WIDTH_OPT, + CFG_END()}; + cfg_opt_t read_opts[] = { CFG_STR("format", "%content", CFGF_NONE), CFG_STR("format_bad", "%title - %errno: %error", CFGF_NONE), @@ -473,6 +485,7 @@ int main(int argc, char *argv[]) { CFG_SEC("load", load_opts, CFGF_NONE), CFG_SEC("memory", memory_opts, CFGF_NONE), CFG_SEC("cpu_usage", usage_opts, CFGF_NONE), + CFG_SEC("key_indicator", key_indicator_opts, CFGF_NONE), CFG_SEC("read_file", read_opts, CFGF_TITLE | CFGF_MULTI), CFG_END()}; @@ -932,6 +945,17 @@ int main(int argc, char *argv[]) { SEC_CLOSE_MAP; } + CASE_SEC("key_indicator") { + SEC_OPEN_MAP("key_indicator"); + key_indicator_ctx_t ctx = { + .json_gen = json_gen, + .buf = buffer, + .buflen = sizeof(buffer), + }; + print_key_indicator(&ctx); + SEC_CLOSE_MAP; + } + CASE_SEC_TITLE("read_file") { SEC_OPEN_MAP("read_file"); file_contents_ctx_t ctx = { diff --git a/include/i3status.h b/include/i3status.h index ad05055..be3d1f2 100644 --- a/include/i3status.h +++ b/include/i3status.h @@ -424,6 +424,14 @@ typedef struct { void print_volume(volume_ctx_t *ctx); +typedef struct { + yajl_gen json_gen; + char *buf; + const size_t buflen; +} key_indicator_ctx_t; + +void print_key_indicator(key_indicator_ctx_t *ctx); + bool process_runs(const char *path); int volume_pulseaudio(uint32_t sink_idx, const char *sink_name); bool description_pulseaudio(uint32_t sink_idx, const char *sink_name, char buffer[MAX_SINK_DESCRIPTION_LEN]); diff --git a/meson.build b/meson.build index 327d8a9..728de7b 100644 --- a/meson.build +++ b/meson.build @@ -144,6 +144,7 @@ add_project_arguments('-D_GNU_SOURCE', language: 'c') # https://mesonbuild.com/howtox.html#add-math-library-lm-portably m_dep = cc.find_library('m', required: false) rt_dep = cc.find_library('rt', required: false) +x_dep = cc.find_library('X11', required: true) confuse_dep = dependency('libconfuse', method: 'pkg-config') yajl_dep = dependency('yajl', method: 'pkg-config') @@ -170,8 +171,10 @@ i3status_srcs = [ 'src/print_time.c', 'src/print_volume.c', 'src/print_wireless_info.c', + 'src/print_key_indicator.c', 'src/print_file_contents.c', 'src/process_runs.c', + 'src/print_key_indicator.c', ] thread_dep = dependency('threads') @@ -180,6 +183,7 @@ i3status_deps = [ thread_dep, m_dep, rt_dep, + x_dep, confuse_dep, yajl_dep, config_h, @@ -202,7 +206,7 @@ if host_os == 'netbsd' i3status_deps += [prop_dep] endif -inc = include_directories('include') +inc = include_directories('include', '/usr/include/') executable( 'i3status', diff --git a/src/print_key_indicator.c b/src/print_key_indicator.c new file mode 100644 index 0000000..b11b4f5 --- /dev/null +++ b/src/print_key_indicator.c @@ -0,0 +1,46 @@ + +#include + +#include +#include + +#include +#include + +#include "i3status.h" + +#define NUM_INDS 3 +#define STRING_SIZE 6 + +void print_key_indicator(key_indicator_ctx_t *ctx) { + + char *outwalk = ctx->buf; + char *ind_names[NUM_INDS] = {"Num Lock", "Caps Lock", "Scroll Lock"}; + char indicator_string[STRING_SIZE]; + char indicator_chars[3]; + int i; + int ndx = 0; + + Atom iatoms[NUM_INDS] = {0}; + Bool state[NUM_INDS] = {0}; + + Display *dpy = XOpenDisplay(NULL); + + for (i = 0; i < NUM_INDS; i++) { + iatoms[i] = XInternAtom(dpy, ind_names[i], 0); + } + + for (i = 0; i < NUM_INDS; i++) { + XkbGetNamedIndicator(dpy, iatoms[i], &ndx, &state[i], NULL, NULL); + } + + indicator_chars[0] = state[0] ? 'N' : 'n'; + indicator_chars[1] = state[1] ? 'C' : 'c'; + indicator_chars[2] = state[2] ? 'S' : 's'; + + snprintf(indicator_string, STRING_SIZE, "%c %c %c", indicator_chars[0], indicator_chars[1], indicator_chars[2]); + + OUTPUT_FULL_TEXT(indicator_string); + + XCloseDisplay(dpy); +} \ No newline at end of file