diff --git a/CMakeLists.txt b/CMakeLists.txt index 80842fe..f4163d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable(${APP_NAME} ${SOURCE_DIR}/backend/x11/window.c ${SOURCE_DIR}/bar/bar.c + ${SOURCE_DIR}/bar/binding.c ${SOURCE_DIR}/bar/cell.c ${SOURCE_DIR}/bar/text.c ${SOURCE_DIR}/bar/workspaces.c diff --git a/include/zdwm/bar.h b/include/zdwm/bar.h index 704f988..051985b 100644 --- a/include/zdwm/bar.h +++ b/include/zdwm/bar.h @@ -33,8 +33,12 @@ typedef struct zdwm_bar_config_t { const char *layout_bg; const char *layout_fg; + + bool binding_show_default; + uint32_t binding_padding_x; const char *binding_mode_bg; const char *binding_mode_fg; + const char *window_bg; const char *window_fg; const char *window_focused_bg; diff --git a/src/bar/bar.c b/src/bar/bar.c index 5e624ca..a4b05d4 100644 --- a/src/bar/bar.c +++ b/src/bar/bar.c @@ -8,6 +8,7 @@ #include #include +#include "bar/binding.h" #include "bar/cell.h" #include "bar/text.h" #include "bar/types.h" @@ -78,6 +79,28 @@ void bar_output_add_workspace( bar_workspace_add_listeners(listeners, item->state); } +static void bar_output_add_binding( + bar_output_t *bar_output, + zdwm_bar_config_t *config, + listeners_t *listeners +) { + bar_binding_config_t binding_config = { + .show_default = config->binding_show_default, + .cell_padding = VALUE(config->binding_padding_x, config->padding_x), + .bg = VALUE(config->binding_mode_bg, config->bg), + .fg = VALUE(config->binding_mode_fg, config->fg), + }; + auto item = bar_add_item( + bar_output->output_id, + &bar_output->left, + bar_binding, + &binding_config + ); + item->cell_padding = binding_config.cell_padding; + + bar_binding_add_listeners(listeners, item->state); +} + void bar_init(bar_t *bar, listeners_t *listeners) { auto c = &bar->config; bar->ctx = text_context_create(c->font_family, c->font_size, c->dpi); @@ -87,6 +110,7 @@ void bar_init(bar_t *bar, listeners_t *listeners) { bar_output->height = bar->config.height; bar_output_add_workspace(bar_output, &bar->config, listeners); + bar_output_add_binding(bar_output, &bar->config, listeners); } bar->timerfd = time_create_monotonic_timerfd_by_fps(bar->config.fps); diff --git a/src/bar/binding.c b/src/bar/binding.c new file mode 100644 index 0000000..78e93e6 --- /dev/null +++ b/src/bar/binding.c @@ -0,0 +1,104 @@ +#include "bar/binding.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "base/memory.h" +#include "core/listeners.h" + +typedef struct bar_binding_state_t { + zdwm_binding_mode_notify_t mode; + + bar_binding_config_t config; + + bool inited; + bool dirty; +} bar_binding_state_t; + +static void * +bar_binding_create_state(zdwm_output_id_t output_id, void *config) { + const bar_binding_config_t *bar_config = config; + assert(bar_config); + + auto state = p_new(bar_binding_state_t, 1); + state->config = *bar_config; + + return state; +} + +static void bar_binding_update( + zdwm_bar_item_t *item, + const zdwm_bar_cell_api_t *cells, + void *state +) { + auto data = (bar_binding_state_t *)state; + if (!data->inited || !data->dirty) return; + + auto config = &data->config; + auto mode = &data->mode; + + if (!config->show_default && mode->is_default_mode) { + cells->set_cell_count(item, 0); + } else { + constexpr auto index = 0; + cells->set_cell_count(item, 1); + cells->cell_set_text(item, index, mode->name); + cells->cell_set_bg(item, index, config->bg); + cells->cell_set_fg(item, index, config->fg); + } + + data->dirty = false; +} + +static zdwm_action_t bar_binding_on_click( + zdwm_bar_item_t *item, + size_t cell_index, + int32_t x, + void *state +) { + return (zdwm_action_t){ + .type = ZDWM_ACTION_BINDING_MODE_CYCLE, + .as.binding_mode_cycle = {.delta = 1}, + }; +} + +static void bar_binding_destroy_state(void *state) { + if (!state) return; + + auto data = (bar_binding_state_t *)state; + p_delete(&data); +} + +zdwm_bar_item_type_t bar_binding = { + .create_state = bar_binding_create_state, + .update = bar_binding_update, + .on_click = bar_binding_on_click, + .destroy_state = bar_binding_destroy_state, + .update_interval_ms = 0, +}; + +static void +bar_binding_mode_notify(zdwm_binding_mode_notify_t mode, void *user_data) { + auto state = (bar_binding_state_t *)user_data; + if (!state->inited) { + state->mode = mode; + + state->inited = true; + state->dirty = true; + return; + } + + if (state->mode.id == mode.id) return; + state->mode = mode; + + state->dirty = true; +} + +void bar_binding_add_listeners(listeners_t *listeners, void *state) { + listeners_add_binding_mode_notify(listeners, bar_binding_mode_notify, state); +} diff --git a/src/bar/binding.h b/src/bar/binding.h new file mode 100644 index 0000000..2c37f0f --- /dev/null +++ b/src/bar/binding.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#include "core/listeners.h" + +typedef struct bar_binding_config_t { + bool show_default; + uint32_t cell_padding; + const char *bg; + const char *fg; +} bar_binding_config_t; + +extern zdwm_bar_item_type_t bar_binding; + +void bar_binding_add_listeners(listeners_t *listeners, void *state); diff --git a/src/config/defaults.c b/src/config/defaults.c index 2e35436..9cb435a 100644 --- a/src/config/defaults.c +++ b/src/config/defaults.c @@ -189,6 +189,11 @@ bool config_defaults_build( .tag_urgent_fg = "#ff0000", .layout_bg = "#222222", .layout_fg = "#bbbbbb", + + .binding_show_default = true, + .binding_padding_x = 2, + .binding_mode_bg = "#900000", + .binding_mode_fg = "#ffffff", }; api->set_bar_config(builder, bar_config);