Compare commits

..

No commits in common. "master" and "releases/1.11" have entirely different histories.

54 changed files with 215 additions and 1477 deletions

View file

@ -12,7 +12,7 @@ steps:
- python3 -m venv codespell-venv
- source codespell-venv/bin/activate
- pip install codespell
- codespell README.md CHANGELOG.md *.c *.h doc/*.scd bar decorations modules particles examples
- codespell README.md CHANGELOG.md *.c *.h doc/*.scd
- deactivate
- name: subprojects

View file

@ -1,6 +1,5 @@
# Changelog
* [Unreleased](#unreleased)
* [1.11.0](#1-11-0)
* [1.10.0](#1-10-0)
* [1.9.0](#1-9-0)
@ -12,60 +11,6 @@
* [1.5.0](#1-5-0)
## Unreleased
### Added
* environment variable substitution in config files ([#96][96]).
* Log output now respects the [`NO_COLOR`](http://no-color.org/)
environment variable.
* network: `type` tag ([#380][380]).
* network: `type` and `kind` tags ([#380][380]).
* tags: `/<N>` tag formatter: divides the tag's decimal value with `N`
([#392][392]).
* i3/sway: `output` tag, reflecting the output (monitor) a workspace
is on.
* Added "string like" `~~` operator to Map particle. Allows glob-style
matching on strings using `*` and `?` characters ([#400][400]).
* Added "single" mode flag to the `mpd` module ([#428][428]).
* niri: add a new module for niri-workspaces and niri-language
([#404][404]).
[96]: https://codeberg.org/dnkl/yambar/issues/96
[380]: https://codeberg.org/dnkl/yambar/issues/380
[392]: https://codeberg.org/dnkl/yambar/issues/392
[400]: https://codeberg.org/dnkl/yambar/pulls/400
[428]: https://codeberg.org/dnkl/yambar/pulls/428
[404]: https://codeberg.org/dnkl/yambar/issues/404
### Changed
* `river`: expand to an empty list of particles when river is not
running ([#384][384]).
[384]: https://codeberg.org/dnkl/yambar/issues/384
### Deprecated
### Removed
### Fixed
* network: fix missing break in switch statement ([#377][377]).
* i3/sway: crash when output is turned off an on ([#300][300]).
* mpd: yambar never attempting to reconnect after MPD closed the
connection (for example, when MPD is restarted).
* Bar positioning on multi-monitor setups, when `location=bottom`.
* pipewire: Improve handling of node switching ([#424][424]).
[377]: https://codeberg.org/dnkl/yambar/issues/377
[300]: https://codeberg.org/dnkl/yambar/issues/300
[424]: https://codeberg.org/dnkl/yambar/pulls/424
### Security
### Contributors
## 1.11.0
### Added

View file

@ -2,7 +2,7 @@
# Yambar
[![Packaging status](https://repology.org/badge/vertical-allrepos/yambar.svg?columns=4)](https://repology.org/project/yambar/versions)
[![Packaging status](https://repology.org/badge/vertical-allrepos/yambar.svg)](https://repology.org/project/yambar/versions)
## Index

View file

@ -28,7 +28,7 @@
#define max(x, y) ((x) > (y) ? (x) : (y))
/*
* Calculate total width of left/center/right groups.
* Calculate total width of left/center/rigth groups.
* Note: begin_expose() must have been called
*/
static void

View file

@ -699,7 +699,6 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
tll_foreach(backend->monitors, it)
{
struct monitor *mon = &it->item;
/*
if (mon->wl_name == name) {
LOG_INFO("%s disconnected/disabled", mon->name);
@ -712,7 +711,6 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
tll_remove(backend->monitors, it);
return;
}
*/
}
LOG_WARN("unknown global removed: 0x%08x", name);

View file

@ -101,7 +101,7 @@ setup(struct bar *_bar)
backend->x = mon->x;
backend->y = mon->y;
bar->width = mon->width;
backend->y += bar->location == BAR_TOP ? 0 : mon->height - bar->height_with_border;
backend->y += bar->location == BAR_TOP ? 0 : screen->height_in_pixels - bar->height_with_border;
found_monitor = true;
@ -369,7 +369,7 @@ refresh(const struct bar *_bar)
/* Send an event to handle refresh from main thread */
/* Note: docs say that all X11 events are 32 bytes, regardless of
/* Note: docs say that all X11 events are 32 bytes, reglardless of
* the size of the event structure */
xcb_expose_event_t *evt = calloc(32, 1);

View file

@ -44,12 +44,6 @@ endif
if plugin_network_enabled
plugin_pages += ['yambar-modules-network.5.scd']
endif
if plugin_niri_language_enabled
plugin_pages += ['yambar-modules-niri-language.5.scd']
endif
if plugin_niri_workspaces_enabled
plugin_pages += ['yambar-modules-niri-workspaces.5.scd']
endif
if plugin_pipewire_enabled
plugin_pages += ['yambar-modules-pipewire.5.scd']
endif

View file

@ -137,7 +137,7 @@ content:
# STACK
This particle combines multiple decorations.
This particles combines multiple decorations.
## CONFIGURATION

View file

@ -17,8 +17,8 @@ currently present in the machine.
for the machine
| is_disk
: boolean
: whether or not the device is a disk (e.g., sda, sdb) or a partition
(e.g., sda1, sda2, ...). "Total" is advertised as a disk.
: whether or not the device is a disk (e.g. sda, sdb) or a partition
(e.g. sda1, sda2, ...). "Total" is advertised as a disk.
| read_speed
: int
: bytes read, in bytes/s

View file

@ -26,9 +26,6 @@ with the _application_ and _title_ tags to replace the X11-only
| name
: string
: The workspace name
| output
: string
: The output (monitor) the workspace is on
| visible
: bool
: True if the workspace is currently visible (on any output)

View file

@ -20,9 +20,6 @@ mpd - This module provides MPD status such as currently playing artist/album/son
| consume
: bool
: True if the *consume* flag is set
| single
: bool
: True if the *single* flag is set
| volume
: range
: Volume of MPD in percentage

View file

@ -21,16 +21,6 @@ address per network interface.
| name
: string
: Network interface name
| type
: string
: Interface type (*ether*, *wlan*, *loopback*, or *ARPHRD_NNN*, where
*N* is a number).
| kind
: string
: Interface kind. Empty for non-virtual interfaces. For virtual
interfaces, this value is taken from the _IFLA\_INFO\_KIND_ netlink
attribute. Examples of valid values are *bond*, *bridge*, *gre*, *tun*
and *veth*.
| index
: int
: Network interface index
@ -101,23 +91,17 @@ address per network interface.
# EXAMPLES
Display all Ethernet (including WLAN) devices. This excludes loopback,
bridges etc.
```
bar:
left:
- network:
content:
map:
default:
string: {text: "{name}: {state} ({ipv4})"}
conditions:
type == ether || type == wlan:
map:
default:
string: {text: "{name}: {state} ({ipv4})"}
conditions:
ipv4 == "":
string: {text: "{name}: {state}"}
ipv4 == "":
string: {text: "{name}: {state}"}
```
# SEE ALSO

View file

@ -1,34 +0,0 @@
yambar-modules-niri-language(5)
# NAME
niri-language - This module provides information about niri's currently
selected language.
# TAGS
[[ *Name*
:[ *Type*
:< *Description*
| language
: string
: The currently selected language.
# CONFIGURATION
No additional attributes supported, only the generic ones (see
*GENERIC CONFIGURATION* in *yambar-modules*(5))
# EXAMPLES
```
bar:
left:
- niri-language:
content:
string: {text: "{language}"}
```
# SEE ALSO
*yambar-modules*(5), *yambar-particles*(5), *yambar-tags*(5), *yambar-decorations*(5)

View file

@ -1,60 +0,0 @@
yambar-modules-niri-workspaces(5)
# NAME
niri-workspaces - This module provides information about niri workspaces.
# DESCRIPTION
This module provides a map of each workspace present in niri.
Each workspace has its _id_, _name_, and its status (_focused_,
_active_, _empty_). The workspaces are sorted by their ids.
This module will *only* track the monitor where yambar was launched.
If you have a multi monitor setup, please launch yambar on each
individual monitor to track its workspaces.
# TAGS
[[ *Name*
:[ *Type*
:< *Description*
| id
: int
: The workspace id.
| name
: string
: The name of the workspace.
| active
: bool
: True if the workspace is currently visible on the current output.
| focused
: bool
: True if the workspace is currently focused.
| empty
: bool
: True if the workspace contains no window.
# CONFIGURATION
No additional attributes supported, only the generic ones (see
*GENERIC CONFIGURATION* in *yambar-modules*(5))
# EXAMPLES
```
bar:
left:
- niri-workspaces:
content:
map:
default: {string: {text: "| {id}"}}
conditions:
active: {string: {text: "-> {id}"}}
~empty: {string: {text: "@ {id}"}}
```
# SEE ALSO
*yambar-modules*(5), *yambar-particles*(5), *yambar-tags*(5), *yambar-decorations*(5)

View file

@ -19,10 +19,10 @@ pipewire - Monitors pipewire for volume, mute/unmute, device change
: Current device description
| form_factor
: string
: Current device form factor (headset, speaker, mic, etc.)
: Current device form factor (headset, speaker, mic, etc)
| bus
: string
: Current device bus (bluetooth, alsa, etc.)
: Current device bus (bluetooth, alsa, etc)
| icon
: string
: Current device icon name

View file

@ -16,7 +16,7 @@ configurable amount of time.
In continuous mode, the script is executed once. It will typically run
in a loop, sending an updated tag set whenever it needs, or wants
to. The last tag set is used (displayed) by yambar until a new tag set
is received. This mode is intended to be used by scripts that depend
is received. This mode is intended to be used by scripts that depends
on non-polling methods to update their state.
Tag sets, or _transactions_, are separated by an empty line

View file

@ -174,10 +174,6 @@ Available modules have their own pages:
*yambar-modules-sway*(5)
*yambar-modules-niri-language*(5)
*yambar-modules-niri-workspaces*(5)
*yambar-modules-xkb*(5)
*yambar-modules-xwindow*(5)

View file

@ -155,7 +155,7 @@ content:
This particle is a list (or sequence, if you like) of other
particles. It can be used to render e.g. _string_ particles with
different font and/or color formatting. Or any other particle
different font and/or color formatting. Or ay other particle
combinations.
But note that this means you *cannot* set any attributes on the _list_
@ -214,11 +214,6 @@ content:
- string: ...
```
Note that the short form has a hard-coded *right-spacing* of 2. This
cannot be changed. If you want a different spacing, you must use an
explicit list particle (i.e. the long form).
# MAP
This particle maps the values of a specific tag to different
@ -265,26 +260,6 @@ To match for empty strings, use ' "" ':
<tag> == ""
```
String glob matching
To perform string matching using globbing with "\*" & "?" characters:
\* Match any zero or more characters. ? Match exactly any one
character.
```
<tag> ~~ "hello*"
```
Will match any string starting with "hello", including "hello",
"hello1", "hello123", etc.
```
<tag> ~~ "hello?"
```
Will match any string starting with "hello" followed by any single
character, including "hello1", "hello-", but not "hello".
Furthermore, you may use the boolean operators:
[- &&
@ -476,7 +451,7 @@ itself when needed.
```
content:
progress-bar:
progres-bar:
tag: tag_name
length: 20
start: {string: {text: ├}}

View file

@ -86,15 +86,11 @@ be used.
: format
: Range tags
: Renders a range tag's value as a percentage value
| /N
: format
: All tag types
: Renders a tag's value (in decimal) divided by N
| kb, mb, gb
: format
: All tag types
: Renders a tag's value (in decimal) divided by 1000, 1000^2 or
1000^3. Note: no unit suffix is appended
1000^3. Note: no unit suffix is appended)
| kib, mib, gib
: format
: All tag types

View file

@ -25,7 +25,7 @@ yambar - modular status panel for X11 and Wayland
*-p*,*--print-pid*=_FILE_|_FD_
Print PID to this file, or FD, when successfully started. The file
(or FD) is closed immediately after writing the PID. When a _FILE_
as been specified, the file is unlinked upon exiting.
as been specified, the file is unlinked exit.
*-d*,*--log-level*={*info*,*warning*,*error*,*none*}
Log level, used both for log output on stderr as well as

View file

@ -23,11 +23,6 @@ types that are frequently used:
- 000000ff: black, no transparency
- 00ff00ff: green, no transparency
- ff000099: red, semi-transparent
- *environment reference*: a string that contains format ${VAR}. This will be
replaced by the value of the environment variable VAR. Example:
- ${HOME}
- ${HOME}/.config/yambar
- ENV is ${ENV}, ENV2 is ${ENV2}
# FORMAT
[[ *Name*

View file

@ -1,69 +0,0 @@
bg_default: &bg_default {stack: [{background: {color: 81A1C1ff}}, {underline: {size: 4, color: D8DEE9ff}}]}
bar:
height: 32
location: top
background: 000000ff
font: NotoSans:pixelsize=16
right:
- clock:
content:
- string: {text: , font: "Font Awesome 6 Free:style=solid:size=12"}
- string: {text: "{date}", right-margin: 5}
- string: {text: , font: "Font Awesome 6 Free:style=solid:size=12"}
- string: {text: "{time} "}
left:
- river:
anchors:
- base: &river_base
left-margin: 10
right-margin: 13
default: {string: {text: }}
conditions:
id == 1: {string: {text: 1}}
id == 2: {string: {text: 2}}
id == 3: {string: {text: 3}}
id == 4: {string: {text: 4}}
id == 5: {string: {text: 5}}
content:
map:
on-click:
left: sh -c "riverctl set-focused-tags $((1 << ({id} - 1)))"
right: sh -c "riverctl toggle-focused-tags $((1 << ({id} -1)))"
middle: sh -c "riverctl toggle-view-tags $((1 << ({id} -1)))"
conditions:
state == urgent:
map:
<<: *river_base
deco: {background: {color: D08770ff}}
state == focused:
map:
<<: *river_base
deco: *bg_default
state == visible && ~occupied:
map:
<<: *river_base
state == visible && occupied:
map:
<<: *river_base
deco: *bg_default
state == unfocused:
map:
<<: *river_base
state == invisible && ~occupied: {empty: {}}
state == invisible && occupied:
map:
<<: *river_base
deco: {underline: {size: 3, color: ea6962ff}}
center:
- foreign-toplevel:
content:
map:
conditions:
~activated: {empty: {}}
activated:
- string: {text: " {app-id}", foreground: ffa0a0ff}
- string: {text: ": {title}"}

View file

@ -19,7 +19,7 @@
#
# Now the fun part
#
# Example configuration:
# Exemple configuration:
#
# - script:
# path: /absolute/path/to/dwl-tags.sh

View file

@ -12,7 +12,7 @@
# {aur} int number of aur packages
# {pkg} int sum of both
#
# Examples configuration:
# Exemples configuration:
# - script:
# path: /absolute/path/to/pacman.sh
# args: []

12
log.c
View file

@ -39,15 +39,9 @@ log_init(enum log_colorize _colorize, bool _do_syslog, enum log_facility syslog_
[LOG_FACILITY_DAEMON] = LOG_DAEMON,
};
/* Don't use colors if NO_COLOR is defined and not empty */
const char *no_color_str = getenv("NO_COLOR");
const bool no_color = no_color_str != NULL && no_color_str[0] != '\0';
colorize = _colorize == LOG_COLORIZE_NEVER
? false
: _colorize == LOG_COLORIZE_ALWAYS
? true
: !no_color && isatty(STDERR_FILENO);
colorize = _colorize == LOG_COLORIZE_NEVER ? false
: _colorize == LOG_COLORIZE_ALWAYS ? true
: isatty(STDERR_FILENO);
do_syslog = _do_syslog;
log_level = _log_level;

2
main.c
View file

@ -87,7 +87,7 @@ get_config_path(void)
static struct bar *
load_bar(const char *config_path, enum bar_backend backend)
{
FILE *conf_file = fopen(config_path, "re");
FILE *conf_file = fopen(config_path, "r");
if (conf_file == NULL) {
LOG_ERRNO("%s: failed to open", config_path);
return NULL;

View file

@ -12,9 +12,7 @@ plugs_as_libs = get_option('core-plugins-as-shared-libraries')
cc = meson.get_compiler('c')
if cc.has_function('memfd_create',
args: ['-D_GNU_SOURCE=200809L'],
prefix: '#include <sys/mman.h>')
if cc.has_function('memfd_create')
add_project_arguments('-DMEMFD_CREATE', language: 'c')
endif
@ -189,8 +187,6 @@ summary(
'River': plugin_river_enabled,
'Script': plugin_script_enabled,
'Sway XKB keyboard': plugin_sway_xkb_enabled,
'Niri language': plugin_niri_language_enabled,
'Niri workspaces': plugin_niri_workspaces_enabled,
'XKB keyboard (for X11)': plugin_xkb_enabled,
'XWindow (window tracking for X11)': plugin_xwindow_enabled,
},

View file

@ -44,10 +44,6 @@ option('plugin-script', type: 'feature', value: 'auto',
description: 'Script support')
option('plugin-sway-xkb', type: 'feature', value: 'auto',
description: 'keyboard support for Sway')
option('plugin-niri-language', type: 'feature', value: 'auto',
description: 'language support for Niri')
option('plugin-niri-workspaces', type: 'feature', value: 'auto',
description: 'workspaces support for Niri')
option('plugin-xkb', type: 'feature', value: 'auto',
description: 'keyboard support for X11')
option('plugin-xwindow', type: 'feature', value: 'auto',

View file

@ -112,13 +112,13 @@ readint_from_fd(int fd)
static int
initialize(struct private *m)
{
int backlight_fd = open("/sys/class/backlight", O_RDONLY | O_CLOEXEC);
int backlight_fd = open("/sys/class/backlight", O_RDONLY);
if (backlight_fd == -1) {
LOG_ERRNO("/sys/class/backlight");
return -1;
}
int base_dir_fd = openat(backlight_fd, m->device, O_RDONLY | O_CLOEXEC);
int base_dir_fd = openat(backlight_fd, m->device, O_RDONLY);
close(backlight_fd);
if (base_dir_fd == -1) {
@ -126,7 +126,7 @@ initialize(struct private *m)
return -1;
}
int max_fd = openat(base_dir_fd, "max_brightness", O_RDONLY | O_CLOEXEC);
int max_fd = openat(base_dir_fd, "max_brightness", O_RDONLY);
if (max_fd == -1) {
LOG_ERRNO("/sys/class/backlight/%s/max_brightness", m->device);
close(base_dir_fd);
@ -136,7 +136,7 @@ initialize(struct private *m)
m->max_brightness = readint_from_fd(max_fd);
close(max_fd);
int current_fd = openat(base_dir_fd, "brightness", O_RDONLY | O_CLOEXEC);
int current_fd = openat(base_dir_fd, "brightness", O_RDONLY);
close(base_dir_fd);
if (current_fd == -1) {

View file

@ -259,13 +259,13 @@ initialize(struct private *m)
{
char line_buf[512];
int pw_fd = open("/sys/class/power_supply", O_RDONLY | O_CLOEXEC);
int pw_fd = open("/sys/class/power_supply", O_RDONLY);
if (pw_fd < 0) {
LOG_ERRNO("/sys/class/power_supply");
return false;
}
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY | O_CLOEXEC);
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY);
close(pw_fd);
if (base_dir_fd < 0) {
@ -274,7 +274,7 @@ initialize(struct private *m)
}
{
int fd = openat(base_dir_fd, "manufacturer", O_RDONLY | O_CLOEXEC);
int fd = openat(base_dir_fd, "manufacturer", O_RDONLY);
if (fd == -1) {
LOG_WARN("/sys/class/power_supply/%s/manufacturer: %s", m->battery, strerror(errno));
m->manufacturer = NULL;
@ -285,7 +285,7 @@ initialize(struct private *m)
}
{
int fd = openat(base_dir_fd, "model_name", O_RDONLY | O_CLOEXEC);
int fd = openat(base_dir_fd, "model_name", O_RDONLY);
if (fd == -1) {
LOG_WARN("/sys/class/power_supply/%s/model_name: %s", m->battery, strerror(errno));
m->model = NULL;
@ -298,7 +298,7 @@ initialize(struct private *m)
if (faccessat(base_dir_fd, "energy_full_design", O_RDONLY, 0) == 0
&& faccessat(base_dir_fd, "energy_full", O_RDONLY, 0) == 0) {
{
int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY | O_CLOEXEC);
int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY);
if (fd == -1) {
LOG_ERRNO("/sys/class/power_supply/%s/energy_full_design", m->battery);
goto err;
@ -309,7 +309,7 @@ initialize(struct private *m)
}
{
int fd = openat(base_dir_fd, "energy_full", O_RDONLY | O_CLOEXEC);
int fd = openat(base_dir_fd, "energy_full", O_RDONLY);
if (fd == -1) {
LOG_ERRNO("/sys/class/power_supply/%s/energy_full", m->battery);
goto err;
@ -325,7 +325,7 @@ initialize(struct private *m)
if (faccessat(base_dir_fd, "charge_full_design", O_RDONLY, 0) == 0
&& faccessat(base_dir_fd, "charge_full", O_RDONLY, 0) == 0) {
{
int fd = openat(base_dir_fd, "charge_full_design", O_RDONLY | O_CLOEXEC);
int fd = openat(base_dir_fd, "charge_full_design", O_RDONLY);
if (fd == -1) {
LOG_ERRNO("/sys/class/power_supply/%s/charge_full_design", m->battery);
goto err;
@ -336,7 +336,7 @@ initialize(struct private *m)
}
{
int fd = openat(base_dir_fd, "charge_full", O_RDONLY | O_CLOEXEC);
int fd = openat(base_dir_fd, "charge_full", O_RDONLY);
if (fd == -1) {
LOG_ERRNO("/sys/class/power_supply/%s/charge_full", m->battery);
goto err;
@ -362,13 +362,13 @@ update_status(struct module *mod)
{
struct private *m = mod->private;
int pw_fd = open("/sys/class/power_supply", O_RDONLY | O_CLOEXEC);
int pw_fd = open("/sys/class/power_supply", O_RDONLY);
if (pw_fd < 0) {
LOG_ERRNO("/sys/class/power_supply");
return false;
}
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY | O_CLOEXEC);
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY);
close(pw_fd);
if (base_dir_fd < 0) {
@ -376,14 +376,14 @@ update_status(struct module *mod)
return false;
}
int status_fd = openat(base_dir_fd, "status", O_RDONLY | O_CLOEXEC);
int status_fd = openat(base_dir_fd, "status", O_RDONLY);
if (status_fd < 0) {
LOG_ERRNO("/sys/class/power_supply/%s/status", m->battery);
close(base_dir_fd);
return false;
}
int capacity_fd = openat(base_dir_fd, "capacity", O_RDONLY | O_CLOEXEC);
int capacity_fd = openat(base_dir_fd, "capacity", O_RDONLY);
if (capacity_fd < 0) {
LOG_ERRNO("/sys/class/power_supply/%s/capacity", m->battery);
close(status_fd);
@ -391,12 +391,12 @@ update_status(struct module *mod)
return false;
}
int energy_fd = openat(base_dir_fd, "energy_now", O_RDONLY | O_CLOEXEC);
int power_fd = openat(base_dir_fd, "power_now", O_RDONLY | O_CLOEXEC);
int charge_fd = openat(base_dir_fd, "charge_now", O_RDONLY | O_CLOEXEC);
int current_fd = openat(base_dir_fd, "current_now", O_RDONLY | O_CLOEXEC);
int time_to_empty_fd = openat(base_dir_fd, "time_to_empty_now", O_RDONLY | O_CLOEXEC);
int time_to_full_fd = openat(base_dir_fd, "time_to_full_now", O_RDONLY | O_CLOEXEC);
int energy_fd = openat(base_dir_fd, "energy_now", O_RDONLY);
int power_fd = openat(base_dir_fd, "power_now", O_RDONLY);
int charge_fd = openat(base_dir_fd, "charge_now", O_RDONLY);
int current_fd = openat(base_dir_fd, "current_now", O_RDONLY);
int time_to_empty_fd = openat(base_dir_fd, "time_to_empty_now", O_RDONLY);
int time_to_full_fd = openat(base_dir_fd, "time_to_full_now", O_RDONLY);
long capacity = readint_from_fd(capacity_fd);
long energy = energy_fd >= 0 ? readint_from_fd(energy_fd) : -1;

View file

@ -124,7 +124,7 @@ refresh_cpu_stats(struct cpu_stats *cpu_stats, size_t core_count)
size_t len = 0;
ssize_t read;
fp = fopen("/proc/stat", "re");
fp = fopen("/proc/stat", "r");
if (NULL == fp) {
LOG_ERRNO("unable to open /proc/stat");
return;

View file

@ -105,7 +105,7 @@ refresh_device_stats(struct private *m)
size_t len = 0;
ssize_t read;
fp = fopen("/proc/diskstats", "re");
fp = fopen("/proc/diskstats", "r");
if (NULL == fp) {
LOG_ERRNO("unable to open /proc/diskstats");
return;
@ -129,7 +129,7 @@ refresh_device_stats(struct private *m)
while ((read = getline(&line, &len, fp)) != -1) {
/*
* For an explanation of the fields below, see
* For an explanation of the fields bellow, see
* https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
*/
uint8_t major_number = 0;

View file

@ -231,7 +231,7 @@ process_line(char *line, struct module *module)
/* No need to check error IMHO */
*target = strtoul(string, NULL, 10);
/* Populate information */
/* Populate informations */
if (index == 6) {
for (size_t id = 1; id <= private->number_of_tags; ++id) {
uint32_t mask = 1 << (id - 1);
@ -330,7 +330,7 @@ run_init(int *inotify_fd, int *inotify_wd, FILE **file, char *dwl_info_filename)
return 1;
}
*file = fopen(dwl_info_filename, "re");
*file = fopen(dwl_info_filename, "r");
if (*file == NULL) {
inotify_rm_watch(*inotify_fd, *inotify_wd);
close(*inotify_fd);

View file

@ -514,6 +514,7 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void
else if (is_move) {
struct workspace *w = workspace_lookup(m, current_id);
assert(w != NULL);
struct json_object *_current_output;
if (!json_object_object_get_ex(current, "output", &_current_output)) {
@ -521,22 +522,16 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void
mtx_unlock(&mod->lock);
return false;
}
const char *current_output_string = json_object_get_string(_current_output);
/* Ignore fallback_output ("For when there's no connected outputs") */
if (strcmp(current_output_string, "FALLBACK") != 0) {
free(w->output);
w->output = strdup(json_object_get_string(_current_output));
assert(w != NULL);
free(w->output);
w->output = strdup(current_output_string);
/*
* If the moved workspace was focused, schedule a full update because
* visibility for other workspaces may have changed.
*/
if (w->focused) {
i3_send_pkg(sock, I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
}
/*
* If the moved workspace was focused, schedule a full update because
* visibility for other workspaces may have changed.
*/
if (w->focused) {
i3_send_pkg(sock, I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL);
}
}
@ -664,7 +659,7 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m
char path[64];
snprintf(path, sizeof(path), "/proc/%u/comm", ws->window.pid);
int fd = open(path, O_RDONLY | O_CLOEXEC);
int fd = open(path, O_RDONLY);
if (fd == -1) {
/* Application may simply have terminated */
free(ws->window.application);
@ -876,7 +871,6 @@ content(struct module *mod)
struct tag_set tags = {
.tags = (struct tag *[]){
tag_new_string(mod, "name", name),
tag_new_string(mod, "output", ws->output),
tag_new_bool(mod, "visible", ws->visible),
tag_new_bool(mod, "focused", ws->focused),
tag_new_bool(mod, "urgent", ws->urgent),
@ -888,7 +882,7 @@ content(struct module *mod)
tag_new_string(mod, "mode", m->mode),
},
.count = 10,
.count = 9,
};
if (ws->focused) {

View file

@ -54,7 +54,7 @@ get_mem_stats(uint64_t *mem_free, uint64_t *mem_total)
size_t len = 0;
ssize_t read = 0;
fp = fopen("/proc/meminfo", "re");
fp = fopen("/proc/meminfo", "r");
if (NULL == fp) {
LOG_ERRNO("unable to open /proc/meminfo");
return false;

View file

@ -45,12 +45,6 @@ plugin_script_enabled = get_option('plugin-script').allowed()
json_sway_xkb = dependency('json-c', required: get_option('plugin-sway-xkb'))
plugin_sway_xkb_enabled = json_sway_xkb.found()
json_niri_language = dependency('json-c', required: get_option('plugin-niri-language'))
plugin_niri_language_enabled = json_niri_language.found()
json_niri_workspaces = dependency('json-c', required: get_option('plugin-niri-workspaces'))
plugin_niri_workspaces_enabled = json_niri_workspaces.found()
xcb_xkb = dependency('xcb-xkb', required: get_option('plugin-xkb'))
plugin_xkb_enabled = backend_x11 and xcb_xkb.found()
@ -127,14 +121,6 @@ if plugin_sway_xkb_enabled
mod_data += {'sway-xkb': [['i3-common.c', 'i3-common.h'], [dynlist, json_sway_xkb]]}
endif
if plugin_niri_language_enabled
mod_data += {'niri-language': [['niri-common.c', 'niri-common.h'], [dynlist, json_niri_language]]}
endif
if plugin_niri_workspaces_enabled
mod_data += {'niri-workspaces': [['niri-common.c', 'niri-common.h'], [dynlist, json_niri_workspaces]]}
endif
if plugin_xkb_enabled
mod_data += {'xkb': [[], [xcb_stuff, xcb_xkb]]}
endif

View file

@ -39,7 +39,6 @@ struct private
bool repeat;
bool random;
bool consume;
bool single;
int volume;
char *album;
char *artist;
@ -177,7 +176,6 @@ content(struct module *mod)
tag_new_bool(mod, "repeat", m->repeat),
tag_new_bool(mod, "random", m->random),
tag_new_bool(mod, "consume", m->consume),
tag_new_bool(mod, "single", m->single),
tag_new_int_range(mod, "volume", m->volume, 0, 100),
tag_new_string(mod, "album", m->album),
tag_new_string(mod, "artist", m->artist),
@ -189,7 +187,7 @@ content(struct module *mod)
tag_new_int_realtime(
mod, "elapsed", elapsed, 0, m->duration, realtime),
},
.count = 14,
.count = 13,
};
mtx_unlock(&mod->lock);
@ -338,7 +336,6 @@ update_status(struct module *mod)
m->repeat = mpd_status_get_repeat(status);
m->random = mpd_status_get_random(status);
m->consume = mpd_status_get_consume(status);
m->single = mpd_status_get_single_state(status) == MPD_SINGLE_ONESHOT;
m->volume = mpd_status_get_volume(status);
m->duration = mpd_status_get_total_time(status) * 1000;
m->elapsed.value = mpd_status_get_elapsed_ms(status);
@ -440,7 +437,7 @@ run(struct module *mod)
*/
while (!aborted) {
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}};
int res = poll(fds, sizeof(fds) / sizeof(fds[0]), 2 * 1000);
int res = poll(fds, sizeof(fds) / sizeof(fds[0]), 10 * 1000);
if (res < 0) {
if (errno == EINTR)
@ -451,16 +448,10 @@ run(struct module *mod)
break;
}
if (res == 0) {
ret = 0;
break;
}
else if (res == 1) {
if (res == 1) {
assert(fds[0].revents & POLLIN);
aborted = true;
}
}
}

View file

@ -17,7 +17,6 @@
#include <arpa/inet.h>
#include <linux/genetlink.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/nl80211.h>
#include <linux/rtnetlink.h>
@ -25,7 +24,7 @@
#include <tllist.h>
#define LOG_MODULE "network"
#define LOG_ENABLE_DBG 1
#define LOG_ENABLE_DBG 0
#include "../bar/bar.h"
#include "../config-verify.h"
#include "../config.h"
@ -53,8 +52,6 @@ struct af_addr {
struct iface {
char *name;
char *type; /* ARPHRD_NNN */
char *kind; /* IFLA_LINKINFO::IFLA_INFO_KIND */
uint32_t get_stats_seq_nr;
@ -107,8 +104,6 @@ free_iface(struct iface iface)
{
tll_free(iface.addrs);
free(iface.ssid);
free(iface.kind);
free(iface.type);
free(iface.name);
}
@ -124,10 +119,7 @@ destroy(struct module *mod)
if (m->urandom_fd >= 0)
close(m->urandom_fd);
tll_foreach(m->ifaces, it) {
free_iface(it->item);
tll_remove(m->ifaces, it);
}
tll_foreach(m->ifaces, it) free_iface(it->item);
free(m);
module_default_destroy(mod);
@ -212,8 +204,6 @@ content(struct module *mod)
struct tag_set tags = {
.tags = (struct tag *[]){
tag_new_string(mod, "name", iface->name),
tag_new_string(mod, "type", iface->type),
tag_new_string(mod, "kind", iface->kind),
tag_new_int(mod, "index", iface->index),
tag_new_bool(mod, "carrier", iface->carrier),
tag_new_string(mod, "state", state),
@ -228,7 +218,7 @@ content(struct module *mod)
tag_new_float(mod, "dl-speed", iface->dl_speed),
tag_new_float(mod, "ul-speed", iface->ul_speed),
},
.count = 16,
.count = 14,
};
exposables[idx++] = m->label->instantiate(m->label, &tags);
tag_set_destroy(&tags);
@ -556,79 +546,6 @@ send_nl80211_get_scan(struct private *m)
return true;
}
static bool
foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr *genl, size_t len,
bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
size_t len, void *ctx),
void *ctx)
{
const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN;
const uint8_t *end = (const uint8_t *)genl + len;
for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end;
raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) {
uint16_t type = attr->nla_type & NLA_TYPE_MASK;
bool nested = (attr->nla_type & NLA_F_NESTED) != 0;
;
const void *payload = raw + NLA_HDRLEN;
if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx))
return false;
}
return true;
}
static bool
foreach_nlattr_nested(struct module *mod, struct iface *iface, const void *parent_payload, size_t len,
bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested,
const void *payload, size_t len, void *ctx),
void *ctx)
{
const uint8_t *raw = parent_payload;
const uint8_t *end = parent_payload + len;
for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end;
raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) {
uint16_t type = attr->nla_type & NLA_TYPE_MASK;
bool nested = (attr->nla_type & NLA_F_NESTED) != 0;
const void *payload = raw + NLA_HDRLEN;
if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx))
return false;
}
return true;
}
static bool
parse_linkinfo(struct module *mod, struct iface *iface, uint16_t type,
bool nested, const void *payload, size_t len, void *_void)
{
switch (type) {
case IFLA_INFO_KIND: {
const char *kind = payload;
free(iface->kind);
iface->kind = strndup(kind, len);
LOG_DBG("%s: IFLA_INFO_KIND: %s", iface->name, iface->kind);
break;
}
case IFLA_INFO_DATA:
//LOG_DBG("%s: IFLA_INFO_DATA", iface->name);
break;
default:
LOG_WARN("unrecognized IFLA_LINKINFO attribute: "
"type=%hu, nested=%d, len=%zu",
type, nested, len);
break;
}
return true;
}
static void
handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size_t len)
{
@ -661,31 +578,9 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size
}
if (iface == NULL) {
char *type = NULL;
switch (msg->ifi_type) {
case ARPHRD_ETHER:
type = strdup("ether");
break;
case ARPHRD_LOOPBACK:
type = strdup("loopback");
break;
case ARPHRD_IEEE80211:
type = strdup("wlan");
break;
default:
if (asprintf(&type, "ARPHRD_%hu", msg->ifi_type) < 0)
type = strdup("unknown");
break;
}
mtx_lock(&mod->lock);
tll_push_back(m->ifaces, ((struct iface){
.index = msg->ifi_index,
.type = type,
.state = IF_OPER_DOWN,
.addrs = tll_init(),
}));
@ -698,10 +593,8 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size
case IFLA_IFNAME:
mtx_lock(&mod->lock);
iface->name = strdup((const char *)RTA_DATA(attr));
LOG_DBG("%s: index=%d, type=%s", iface->name, iface->index, iface->type);
LOG_DBG("%s: index=%d", iface->name, iface->index);
mtx_unlock(&mod->lock);
break;
case IFLA_OPERSTATE: {
uint8_t operstate = *(const uint8_t *)RTA_DATA(attr);
if (iface->state == operstate)
@ -736,8 +629,7 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size
if (memcmp(iface->mac, mac, sizeof(iface->mac)) == 0)
break;
LOG_DBG("%s: IFLA_ADDRESS: %02x:%02x:%02x:%02x:%02x:%02x",
iface->name, mac[0], mac[1], mac[2], mac[3],
LOG_DBG("%s: IFLA_ADDRESS: %02x:%02x:%02x:%02x:%02x:%02x", iface->name, mac[0], mac[1], mac[2], mac[3],
mac[4], mac[5]);
mtx_lock(&mod->lock);
@ -745,13 +637,6 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size
mtx_unlock(&mod->lock);
break;
}
case IFLA_LINKINFO: {
foreach_nlattr_nested(
mod, iface, RTA_DATA(attr), RTA_PAYLOAD(attr),
&parse_linkinfo, NULL);
break;
}
}
}
@ -784,7 +669,7 @@ handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, s
}
if (iface == NULL) {
LOG_ERR("failed to find network interface with index %d. Probably a yambar bug", msg->ifa_index);
LOG_ERR("failed to find network interface with index %d. Probaly a yambar bug", msg->ifa_index);
return;
}
@ -834,6 +719,51 @@ handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, s
mod->bar->refresh(mod->bar);
}
static bool
foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr *genl, size_t len,
bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
size_t len, void *ctx),
void *ctx)
{
const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN;
const uint8_t *end = (const uint8_t *)genl + len;
for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end;
raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) {
uint16_t type = attr->nla_type & NLA_TYPE_MASK;
bool nested = (attr->nla_type & NLA_F_NESTED) != 0;
;
const void *payload = raw + NLA_HDRLEN;
if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx))
return false;
}
return true;
}
static bool
foreach_nlattr_nested(struct module *mod, struct iface *iface, const void *parent_payload, size_t len,
bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested,
const void *payload, size_t len, void *ctx),
void *ctx)
{
const uint8_t *raw = parent_payload;
const uint8_t *end = parent_payload + len;
for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end;
raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) {
uint16_t type = attr->nla_type & NLA_TYPE_MASK;
bool nested = (attr->nla_type & NLA_F_NESTED) != 0;
const void *payload = raw + NLA_HDRLEN;
if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx))
return false;
}
return true;
}
struct mcast_group {
uint32_t id;
const char *name;
@ -1370,8 +1300,6 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
continue;
LOG_DBG("%s: got interface information", iface->name);
free(iface->type);
iface->type = strdup("wlan");
foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_new_interface, NULL);
break;
@ -1576,7 +1504,7 @@ out:
static struct module *
network_new(struct particle *label, int poll_interval, int left_spacing, int right_spacing)
{
int urandom_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
int urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd < 0) {
LOG_ERRNO("failed to open /dev/urandom");
return NULL;

View file

@ -1,377 +0,0 @@
#include <errno.h>
#include <json-c/json.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <threads.h>
#include <unistd.h>
#include "../log.h"
#include "niri-common.h"
#define LOG_MODULE "niri:common"
#define LOG_ENABLE_DBG 0
static struct niri_socket instance = {
.fd = -1,
.abort_fd = -1,
};
static void
workspace_free(struct niri_workspace *workspace)
{
free(workspace->name);
free(workspace);
}
static void
parser(char *response)
{
enum json_tokener_error error = json_tokener_success;
struct json_object *json = json_tokener_parse_verbose(response, &error);
if (error != json_tokener_success) {
LOG_WARN("failed to parse niri socket's response");
return;
}
enum niri_event events = 0;
struct json_object_iterator it = json_object_iter_begin(json);
struct json_object_iterator end = json_object_iter_end(json);
while (!json_object_iter_equal(&it, &end)) {
char const *key = json_object_iter_peek_name(&it);
// "WorkspacesChanged": {
// "workspaces": [
// {
// "id": 3,
// "idx": 1,
// "name": null,
// "output": "DP-4",
// "is_active": true,
// "is_focused": true,
// "active_window_id": 24
// },
// ...
// ]
// }
if (strcmp(key, "WorkspacesChanged") == 0) {
mtx_lock(&instance.mtx);
tll_foreach(instance.workspaces, it) { tll_remove_and_free(instance.workspaces, it, workspace_free); }
mtx_unlock(&instance.mtx);
json_object *obj = json_object_iter_peek_value(&it);
json_object *workspaces = json_object_object_get(obj, "workspaces");
size_t length = json_object_array_length(workspaces);
for (size_t i = 0; i < length; ++i) {
json_object *ws_obj = json_object_array_get_idx(workspaces, i);
// only add workspaces on the current yambar's monitor
struct json_object *output = json_object_object_get(ws_obj, "output");
if (strcmp(instance.monitor, json_object_get_string(output)) != 0)
continue;
struct niri_workspace *ws = calloc(1, sizeof(*ws));
ws->idx = json_object_get_int(json_object_object_get(ws_obj, "idx"));
ws->id = json_object_get_int(json_object_object_get(ws_obj, "id"));
ws->active = json_object_get_boolean(json_object_object_get(ws_obj, "is_active"));
ws->focused = json_object_get_boolean(json_object_object_get(ws_obj, "is_focused"));
ws->empty = json_object_get_int(json_object_object_get(ws_obj, "active_window_id")) == 0;
char const *name = json_object_get_string(json_object_object_get(ws_obj, "name"));
if (name)
ws->name = strdup(name);
mtx_lock(&instance.mtx);
bool inserted = false;
tll_foreach(instance.workspaces, it)
{
if (it->item->idx > ws->idx) {
tll_insert_before(instance.workspaces, it, ws);
inserted = true;
break;
}
}
if (!inserted)
tll_push_back(instance.workspaces, ws);
mtx_unlock(&instance.mtx);
events |= workspaces_changed;
}
}
// "WorkspaceActivated": {
// "id": 7,
// "focused":true
// }
else if (strcmp(key, "WorkspaceActivated") == 0) {
json_object *obj = json_object_iter_peek_value(&it);
int id = json_object_get_int(json_object_object_get(obj, "id"));
mtx_lock(&instance.mtx);
tll_foreach(instance.workspaces, it)
{
bool b = it->item->id == id;
it->item->focused = b;
it->item->active = b;
}
mtx_unlock(&instance.mtx);
events |= workspace_activated;
}
// "WorkspaceActiveWindowChanged": {
// "workspace_id": 3,
// "active_window_id": 8
// }
else if (strcmp(key, "WorkspaceActiveWindowChanged") == 0) {
json_object *obj = json_object_iter_peek_value(&it);
int id = json_object_get_int(json_object_object_get(obj, "id"));
bool empty = json_object_get_int(json_object_object_get(obj, "active_window_id")) == 0;
mtx_lock(&instance.mtx);
tll_foreach(instance.workspaces, it)
{
if (it->item->id == id) {
it->item->empty = empty;
break;
}
}
mtx_unlock(&instance.mtx);
events |= workspace_active_window_changed;
}
//
// "KeyboardLayoutsChanged": {
// "keyboard_layouts": {
// "names": [
// "English (US)",
// "Russian"
// ],
// "current_idx": 0
// }
// }
else if (strcmp(key, "KeyboardLayoutsChanged") == 0) {
tll_foreach(instance.keyboard_layouts, it) { tll_remove_and_free(instance.keyboard_layouts, it, free); }
json_object *obj = json_object_iter_peek_value(&it);
json_object *kb_layouts = json_object_object_get(obj, "keyboard_layouts");
instance.keyboard_layout_index = json_object_get_int(json_object_object_get(kb_layouts, "current_idx"));
json_object *names = json_object_object_get(kb_layouts, "names");
size_t names_length = json_object_array_length(names);
for (size_t i = 0; i < names_length; ++i) {
char const *name = json_object_get_string(json_object_array_get_idx(names, i));
tll_push_back(instance.keyboard_layouts, strdup(name));
}
events |= keyboard_layouts_changed;
}
// "KeyboardLayoutSwitched": {
// "idx": 1
// }
else if (strcmp(key, "KeyboardLayoutSwitched") == 0) {
json_object *obj = json_object_iter_peek_value(&it);
instance.keyboard_layout_index = json_object_get_int(json_object_object_get(obj, "idx"));
events |= keyboard_layouts_switched;
}
json_object_iter_next(&it);
}
json_object_put(json);
mtx_lock(&instance.mtx);
tll_foreach(instance.subscribers, it)
{
if (it->item->events & events)
if (write(it->item->fd, &(uint64_t){1}, sizeof(uint64_t)) == -1)
LOG_ERRNO("failed to write");
}
mtx_unlock(&instance.mtx);
}
static int
run(void *userdata)
{
static char msg[] = "\"EventStream\"\n";
static char expected[] = "{\"Ok\":\"Handled\"}";
if (write(instance.fd, msg, sizeof(msg) / sizeof(msg[0])) == -1) {
LOG_ERRNO("failed to sent message to niri socket");
return thrd_error;
}
static char buffer[8192];
if (read(instance.fd, buffer, sizeof(buffer) / sizeof(buffer[0]) - 1) == -1) {
LOG_ERRNO("failed to read response of niri socket");
return thrd_error;
}
char *saveptr;
char *response = strtok_r(buffer, "\n", &saveptr);
if (response == NULL || strcmp(expected, response) != 0) {
// unexpected first response, something went wrong
LOG_ERR("unexpected response of niri socket");
return thrd_error;
}
while ((response = strtok_r(NULL, "\n", &saveptr)) != NULL)
parser(response);
while (true) {
struct pollfd fds[] = {
(struct pollfd){.fd = instance.abort_fd, .events = POLLIN},
(struct pollfd){.fd = instance.fd, .events = POLLIN},
};
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) {
if (errno == EINTR)
continue;
LOG_ERRNO("failed to poll");
break;
}
if (fds[0].revents & POLLIN)
break;
static char buffer[8192];
ssize_t length = read(fds[1].fd, buffer, sizeof(buffer) / sizeof(buffer[0]));
if (length == 0)
break;
if (length == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
LOG_ERRNO("unable to read niri socket");
break;
}
buffer[length] = '\0';
saveptr = NULL;
response = strtok_r(buffer, "\n", &saveptr);
do {
parser(response);
} while ((response = strtok_r(NULL, "\n", &saveptr)) != NULL);
}
return thrd_success;
}
struct niri_socket *
niri_socket_open(char const *monitor)
{
if (instance.fd >= 0)
return &instance;
char const *path = getenv("NIRI_SOCKET");
if (path == NULL) {
LOG_ERR("NIRI_SOCKET is empty. Is niri running?");
return NULL;
}
if ((instance.fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) {
LOG_ERRNO("failed to create socket");
goto error;
}
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
if (connect(instance.fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
LOG_ERRNO("failed to connect to niri socket");
goto error;
}
if ((instance.abort_fd = eventfd(0, EFD_CLOEXEC)) == -1) {
LOG_ERRNO("failed to create abort_fd");
goto error;
}
if (mtx_init(&instance.mtx, mtx_plain) != thrd_success) {
LOG_ERR("failed to initialize mutex");
goto error;
}
if (thrd_create(&instance.thrd, run, NULL) != thrd_success) {
LOG_ERR("failed to create thread");
mtx_destroy(&instance.mtx);
goto error;
}
instance.monitor = monitor;
return &instance;
error:
if (instance.fd >= 0)
close(instance.fd);
if (instance.abort_fd >= 0)
close(instance.abort_fd);
instance.fd = -1;
instance.abort_fd = -1;
instance.monitor = NULL;
return NULL;
}
static void
socket_close(void)
{
if (write(instance.abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t))
LOG_ERRNO("failed to write to abort_fd");
thrd_join(instance.thrd, NULL);
close(instance.abort_fd);
close(instance.fd);
instance.abort_fd = -1;
instance.fd = -1;
mtx_destroy(&instance.mtx);
tll_free_and_free(instance.subscribers, free);
tll_free_and_free(instance.workspaces, workspace_free);
tll_free_and_free(instance.keyboard_layouts, free);
}
void
niri_socket_close(void)
{
static once_flag flag = ONCE_FLAG_INIT;
call_once(&flag, socket_close);
}
int
niri_socket_subscribe(enum niri_event events)
{
int fd = eventfd(0, EFD_CLOEXEC);
if (fd == -1) {
LOG_ERRNO("failed to create eventfd");
return -1;
}
struct niri_subscriber *subscriber = calloc(1, sizeof(*subscriber));
subscriber->events = events;
subscriber->fd = fd;
mtx_lock(&instance.mtx);
tll_push_back(instance.subscribers, subscriber);
mtx_unlock(&instance.mtx);
return subscriber->fd;
}

View file

@ -1,45 +0,0 @@
#pragma once
#include <stdbool.h>
#include <threads.h>
#include <tllist.h>
enum niri_event {
workspaces_changed = (1 << 0),
workspace_activated = (1 << 1),
workspace_active_window_changed = (1 << 2),
keyboard_layouts_changed = (1 << 3),
keyboard_layouts_switched = (1 << 4),
};
struct niri_subscriber {
int events;
int fd;
};
struct niri_workspace {
int id;
int idx;
char *name;
bool active;
bool focused;
bool empty;
};
struct niri_socket {
char const *monitor;
int abort_fd;
int fd;
tll(struct niri_subscriber *) subscribers;
tll(struct niri_workspace *) workspaces;
tll(char *) keyboard_layouts;
size_t keyboard_layout_index;
thrd_t thrd;
mtx_t mtx;
};
struct niri_socket *niri_socket_open(char const *monitor);
void niri_socket_close(void);
int niri_socket_subscribe(enum niri_event events);

View file

@ -1,160 +0,0 @@
#include <errno.h>
#include <json-c/json.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>
#define LOG_MODULE "niri-language"
#define LOG_ENABLE_DBG 0
#include "niri-common.h"
#include "../log.h"
#include "../particles/dynlist.h"
#include "../plugin.h"
struct private
{
struct particle *label;
struct niri_socket *niri;
};
static void
destroy(struct module *module)
{
struct private *private = module->private;
private->label->destroy(private->label);
free(private);
module_default_destroy(module);
}
static const char *
description(const struct module *module)
{
return "niri-lang";
}
static struct exposable *
content(struct module *module)
{
const struct private *private = module->private;
if (private->niri == NULL)
return dynlist_exposable_new(&((struct exposable *){0}), 0, 0, 0);
mtx_lock(&module->lock);
mtx_lock(&private->niri->mtx);
char *name = "???";
size_t i = 0;
tll_foreach(private->niri->keyboard_layouts, it)
{
if (i++ == private->niri->keyboard_layout_index)
name = it->item;
}
struct tag_set tags = {
.tags = (struct tag *[]){tag_new_string(module, "language", name)},
.count = 1,
};
struct exposable *exposable = private->label->instantiate(private->label, &tags);
tag_set_destroy(&tags);
mtx_unlock(&private->niri->mtx);
mtx_unlock(&module->lock);
return exposable;
}
static int
run(struct module *module)
{
struct private *private = module->private;
/* Ugly, but I didn't find better way for waiting
* the monitor's name to be set */
char const *monitor;
do {
monitor = module->bar->output_name(module->bar);
usleep(50);
} while (monitor == NULL);
private->niri = niri_socket_open(monitor);
if (private->niri == NULL)
return 1;
int fd = niri_socket_subscribe(keyboard_layouts_changed | keyboard_layouts_switched);
if (fd == -1) {
niri_socket_close();
return 1;
}
module->bar->refresh(module->bar);
while (true) {
struct pollfd fds[] = {
(struct pollfd){.fd = module->abort_fd, .events = POLLIN},
(struct pollfd){.fd = fd, .events = POLLIN},
};
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) {
if (errno == EINTR)
continue;
LOG_ERRNO("failed to poll");
break;
}
if (fds[0].revents & POLLIN)
break;
if (read(fds[1].fd, &(uint64_t){0}, sizeof(uint64_t)) == -1)
LOG_ERRNO("failed to read from eventfd");
module->bar->refresh(module->bar);
}
niri_socket_close();
return 0;
}
static struct module *
niri_language_new(struct particle *label)
{
struct private *private = calloc(1, sizeof(struct private));
private->label = label;
struct module *module = module_common_new();
module->private = private;
module->run = &run;
module->destroy = &destroy;
module->content = &content;
module->description = &description;
return module;
}
static struct module *
from_conf(struct yml_node const *node, struct conf_inherit inherited)
{
struct yml_node const *content = yml_get_value(node, "content");
return niri_language_new(conf_to_particle(content, inherited));
}
static bool
verify_conf(keychain_t *chain, const struct yml_node *node)
{
static struct attr_info const attrs[] = {
MODULE_COMMON_ATTRS,
};
return conf_verify_dict(chain, node, attrs);
}
const struct module_iface module_niri_language_iface = {
.verify_conf = &verify_conf,
.from_conf = &from_conf,
};
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
extern const struct module_iface iface __attribute__((weak, alias("module_niri_language_iface")));
#endif

View file

@ -1,163 +0,0 @@
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>
#define LOG_MODULE "niri-workspaces"
#define LOG_ENABLE_DBG 0
#include "niri-common.h"
#include "../log.h"
#include "../particles/dynlist.h"
#include "../plugin.h"
struct private
{
struct particle *label;
struct niri_socket *niri;
};
static void
destroy(struct module *module)
{
struct private *private = module->private;
private->label->destroy(private->label);
free(private);
module_default_destroy(module);
}
static const char *
description(const struct module *module)
{
return "niri-ws";
}
static struct exposable *
content(struct module *module)
{
struct private const *private = module->private;
if (private->niri == NULL)
return dynlist_exposable_new(&((struct exposable *){0}), 0, 0, 0);
mtx_lock(&module->lock);
mtx_lock(&private->niri->mtx);
size_t i = 0;
struct exposable *exposable[tll_length(private->niri->workspaces)];
tll_foreach(private->niri->workspaces, it)
{
struct tag_set tags = {
.tags = (struct tag*[]){
tag_new_int(module, "id", it->item->idx),
tag_new_string(module, "name", it->item->name),
tag_new_bool(module, "active", it->item->active),
tag_new_bool(module, "focused", it->item->focused),
tag_new_bool(module, "empty", it->item->empty),
},
.count = 5,
};
exposable[i++] = private->label->instantiate(private->label, &tags);
tag_set_destroy(&tags);
}
mtx_unlock(&private->niri->mtx);
mtx_unlock(&module->lock);
return dynlist_exposable_new(exposable, i, 0, 0);
}
static int
run(struct module *module)
{
struct private *private = module->private;
/* Ugly, but I didn't find better way for waiting
* the monitor's name to be set */
char const *monitor;
do {
monitor = module->bar->output_name(module->bar);
usleep(50);
} while (monitor == NULL);
private->niri = niri_socket_open(monitor);
if (private->niri == NULL)
return 1;
int fd = niri_socket_subscribe(workspaces_changed | workspace_activated | workspace_active_window_changed);
if (fd == -1) {
niri_socket_close();
return 1;
}
module->bar->refresh(module->bar);
while (true) {
struct pollfd fds[] = {
(struct pollfd){.fd = module->abort_fd, .events = POLLIN},
(struct pollfd){.fd = fd, .events = POLLIN},
};
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) {
if (errno == EINTR)
continue;
LOG_ERRNO("failed to poll");
break;
}
if (fds[0].revents & POLLIN)
break;
if (read(fds[1].fd, &(uint64_t){0}, sizeof(uint64_t)) == -1)
LOG_ERRNO("failed to read from eventfd");
module->bar->refresh(module->bar);
}
niri_socket_close();
return 0;
}
static struct module *
niri_workspaces_new(struct particle *label)
{
struct private *private = calloc(1, sizeof(struct private));
private->label = label;
struct module *module = module_common_new();
module->private = private;
module->run = &run;
module->destroy = &destroy;
module->content = &content;
module->description = &description;
return module;
}
static struct module *
from_conf(struct yml_node const *node, struct conf_inherit inherited)
{
struct yml_node const *content = yml_get_value(node, "content");
return niri_workspaces_new(conf_to_particle(content, inherited));
}
static bool
verify_conf(keychain_t *chain, const struct yml_node *node)
{
static struct attr_info const attrs[] = {
MODULE_COMMON_ATTRS,
};
return conf_verify_dict(chain, node, attrs);
}
const struct module_iface module_niri_workspaces_iface = {
.verify_conf = &verify_conf,
.from_conf = &from_conf,
};
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
extern const struct module_iface iface __attribute__((weak, alias("module_niri_workspaces_iface")));
#endif

View file

@ -33,7 +33,7 @@ struct output_informations {
uint32_t device_id;
uint32_t card_profile_device_id;
/* information */
/* informations */
bool muted;
uint16_t linear_volume; /* classic volume */
uint16_t cubic_volume; /* volume a la pulseaudio */
@ -45,16 +45,6 @@ struct output_informations {
};
static struct output_informations const output_informations_null;
static void
output_informations_destroy(struct output_informations *output_informations)
{
free(output_informations->name);
free(output_informations->description);
free(output_informations->icon);
free(output_informations->form_factor);
free(output_informations->bus);
}
struct data;
struct private
{
@ -223,23 +213,18 @@ node_find_route(struct data *data, bool is_sink)
static void
node_unhook_binded_node(struct data *data, bool is_sink)
{
struct private *private = data->module->private;
struct node **target_node = NULL;
struct spa_hook *target_listener = NULL;
void **target_proxy = NULL;
struct output_informations *output_informations = NULL;
if (is_sink) {
target_node = &data->binded_sink;
target_listener = &data->node_sink_listener;
target_proxy = &data->node_sink;
output_informations = &private->sink_informations;
} else {
target_node = &data->binded_source;
target_listener = &data->node_source_listener;
target_proxy = &data->node_source;
output_informations = &private->source_informations;
}
if (*target_node == NULL)
@ -250,9 +235,6 @@ node_unhook_binded_node(struct data *data, bool is_sink)
*target_node = NULL;
*target_proxy = NULL;
output_informations_destroy(output_informations);
*output_informations = output_informations_null;
}
static void
@ -351,7 +333,7 @@ device_events_param(void *userdata, int seq, uint32_t id, uint32_t index, uint32
X_FREE_SET(route->icon_name, X_STRDUP(data.icon_name));
route->direction = data.direction;
/* set missing information if possible */
/* set missing informations if possible */
struct private *private = device->data->module->private;
struct node *binded_node = NULL;
struct output_informations *output_informations = NULL;
@ -368,7 +350,7 @@ device_events_param(void *userdata, int seq, uint32_t id, uint32_t index, uint32
if (binded_node == NULL)
return;
/* Node's device is the same as route's device */
/* Node's device is the the same as route's device */
if (output_informations->device_id != route->device->id)
return;
@ -376,7 +358,7 @@ device_events_param(void *userdata, int seq, uint32_t id, uint32_t index, uint32
if (output_informations->card_profile_device_id != route->profile_device_id)
return;
/* Update missing information */
/* Update missing informations */
X_FREE_SET(output_informations->form_factor, X_STRDUP(route->form_factor));
X_FREE_SET(output_informations->icon, X_STRDUP(route->icon_name));
@ -402,7 +384,7 @@ node_events_info(void *userdata, struct pw_node_info const *info)
for (size_t i = 0; i < info->n_params; ++i) {
if (info->params[i].id == SPA_PARAM_Props) {
void *target_node = (node_data->is_sink ? data->node_sink : data->node_source);
/* Found it, will emit a param event, the param will then be handled
/* Found it, will emit a param event, the parem will then be handled
* in node_events_param */
pw_node_enum_params(target_node, 0, info->params[i].id, 0, -1, NULL);
break;
@ -416,18 +398,18 @@ node_events_info(void *userdata, struct pw_node_info const *info)
struct spa_dict_item const *item = NULL;
item = spa_dict_lookup_item(info->props, "node.name");
X_FREE_SET(output_informations->name, item != NULL ? X_STRDUP(item->value) : NULL);
if (item != NULL)
X_FREE_SET(output_informations->name, X_STRDUP(item->value));
item = spa_dict_lookup_item(info->props, "node.description");
X_FREE_SET(output_informations->description, item != NULL ? X_STRDUP(item->value) : NULL);
if (item != NULL)
X_FREE_SET(output_informations->description, X_STRDUP(item->value));
item = spa_dict_lookup_item(info->props, "device.id");
if (item != NULL) {
uint32_t value = 0;
spa_atou32(item->value, &value, 10);
output_informations->device_id = value;
} else {
output_informations->device_id = 0;
}
item = spa_dict_lookup_item(info->props, "card.profile.device");
@ -435,29 +417,30 @@ node_events_info(void *userdata, struct pw_node_info const *info)
uint32_t value = 0;
spa_atou32(item->value, &value, 10);
output_informations->card_profile_device_id = value;
} else {
output_informations->card_profile_device_id = 0;
}
/* Device's information has an more important priority than node's information */
/* Device's informations has an more important priority than node's informations */
/* icon_name */
struct route *route = node_find_route(data, node_data->is_sink);
if (route != NULL && route->icon_name != NULL)
X_FREE_SET(output_informations->icon, X_STRDUP(route->icon_name));
output_informations->icon = X_STRDUP(route->icon_name);
else {
item = spa_dict_lookup_item(info->props, "device.icon-name");
X_FREE_SET(output_informations->icon, item != NULL ? X_STRDUP(item->value) : NULL);
if (item != NULL)
X_FREE_SET(output_informations->icon, X_STRDUP(item->value));
}
/* form_factor */
if (route != NULL && route->form_factor != NULL)
X_FREE_SET(output_informations->form_factor, X_STRDUP(route->form_factor));
output_informations->form_factor = X_STRDUP(route->form_factor);
else {
item = spa_dict_lookup_item(info->props, "device.form-factor");
X_FREE_SET(output_informations->form_factor, item != NULL ? X_STRDUP(item->value) : NULL);
if (item != NULL)
X_FREE_SET(output_informations->form_factor, X_STRDUP(item->value));
}
item = spa_dict_lookup_item(info->props, "device.bus");
X_FREE_SET(output_informations->bus, item != NULL ? X_STRDUP(item->value) : NULL);
if (item != NULL)
X_FREE_SET(output_informations->bus, X_STRDUP(item->value));
data->module->bar->refresh(data->module->bar);
}
@ -676,7 +659,7 @@ static void
try_to_bind_node(struct node_data *node_data, char const *target_name, struct node **target_node, void **target_proxy,
struct spa_hook *target_listener)
{
/* profile deactivated */
/* profile deactived */
if (target_name == NULL)
return;
@ -844,8 +827,18 @@ destroy(struct module *module)
pipewire_deinit(private->data);
private->label->destroy(private->label);
output_informations_destroy(&private->sink_informations);
output_informations_destroy(&private->source_informations);
/* sink */
free(private->sink_informations.name);
free(private->sink_informations.description);
free(private->sink_informations.icon);
free(private->sink_informations.form_factor);
free(private->sink_informations.bus);
/* source */
free(private->source_informations.name);
free(private->source_informations.description);
free(private->source_informations.icon);
free(private->source_informations.form_factor);
free(private->source_informations.bus);
free(private);
module_default_destroy(module);

View file

@ -438,7 +438,7 @@ run(struct module *mod)
}
// Create refresh timer.
priv->refresh_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
priv->refresh_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
if (priv->refresh_timer_fd < 0) {
LOG_ERRNO("failed to create timerfd");
pa_mainloop_free(priv->mainloop);

View file

@ -161,10 +161,13 @@ content(struct module *mod)
static void
find_mount_points(const char *dev_path, mount_point_list_t *mount_points)
{
FILE *f = fopen("/proc/self/mountinfo", "re");
int fd = open("/proc/self/mountinfo", O_RDONLY | O_CLOEXEC);
FILE *f = fd >= 0 ? fdopen(fd, "r") : NULL;
if (f == NULL) {
if (fd < 0 || f == NULL) {
LOG_ERRNO("failed to open /proc/self/mountinfo");
if (fd >= 0)
close(fd);
return;
}

View file

@ -52,7 +52,6 @@ struct seat {
struct private
{
struct module *mod;
bool is_running;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct zriver_status_manager_v1 *status_manager;
struct particle *template;
@ -89,11 +88,6 @@ content(struct module *mod)
mtx_lock(&m->mod->lock);
if (!m->is_running) {
mtx_unlock(&m->mod->lock);
return dynlist_exposable_new(NULL, 0, 0, 0);
}
uint32_t urgent = 0;
uint32_t occupied = 0;
uint32_t output_focused = 0;
@ -691,8 +685,6 @@ run(struct module *mod)
goto out;
}
m->is_running = true;
wl_display_roundtrip(display);
while (true) {

View file

@ -130,7 +130,7 @@ update_application(struct module *mod)
char path[1024];
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
int fd = open(path, O_RDONLY | O_CLOEXEC);
int fd = open(path, O_RDONLY);
if (fd == -1)
return;

View file

@ -13,61 +13,6 @@
#include "map.h"
// String globbing match.
// Note: Uses "non-greedy" implementation for "*" wildcard matching
static bool
string_like(const char* name, const char* pattern)
{
LOG_DBG("pattern:%s name:%s", pattern, name);
int px = 0, nx = 0;
int nextpx = 0, nextnx = 0;
while (px < strlen(pattern) || nx < strlen(name)) {
if (px < strlen(pattern)) {
char c = pattern[px];
switch (c) {
case '?': {
// single character
px++;
nx++;
continue;
}
case '*': {
// zero or more glob
nextpx=px;
nextnx=nx+1;
px++;
continue;
}
default: {
// normal character
if (nx < strlen(name) && name[nx] == c)
{
px++;
nx++;
continue;
}
}
}
}
// mismatch
if (0 < nextnx && nextnx <= strlen(name)) {
px = nextpx;
nx = nextnx;
continue;
}
return false;
}
LOG_DBG("map: name %s matched all the pattern %s", name, pattern);
// Matched all of pattern to all of name. Success.
return true;
}
static bool
int_condition(const long tag_value, const long cond_value, enum map_op op)
{
@ -130,8 +75,6 @@ str_condition(const char *tag_value, const char *cond_value, enum map_op op)
return strcmp(tag_value, cond_value) >= 0;
case MAP_OP_GT:
return strcmp(tag_value, cond_value) > 0;
case MAP_OP_LIKE:
return string_like(tag_value, cond_value) != 0;
case MAP_OP_SELF:
LOG_WARN("using String tag as bool");
default:
@ -223,7 +166,6 @@ free_map_condition(struct map_condition *c)
case MAP_OP_LE:
case MAP_OP_LT:
case MAP_OP_GE:
case MAP_OP_LIKE:
case MAP_OP_GT:
free(c->value);
/* FALLTHROUGH */

View file

@ -9,7 +9,6 @@ enum map_op {
MAP_OP_GT,
MAP_OP_SELF,
MAP_OP_NOT,
MAP_OP_LIKE,
MAP_OP_AND,
MAP_OP_OR,

View file

@ -69,7 +69,6 @@ void yyerror(const char *s);
\< yylval.op = MAP_OP_LT; return CMP_OP;
>= yylval.op = MAP_OP_GE; return CMP_OP;
> yylval.op = MAP_OP_GT; return CMP_OP;
~~ yylval.op = MAP_OP_LIKE; return CMP_OP;
&& yylval.op = MAP_OP_AND; return BOOL_OP;
\|\| yylval.op = MAP_OP_OR; return BOOL_OP;
~ return NOT;

View file

@ -35,27 +35,27 @@ result: condition { MAP_CONDITION_PARSE_RESULT = $<condition>1; };
condition:
WORD {
$<condition>$ = malloc(sizeof(struct map_condition));
$<condition>$->tag = $<str>1;
$<condition>$->tag = $<str>1;
$<condition>$->op = MAP_OP_SELF;
}
|
WORD CMP_OP WORD {
$<condition>$ = malloc(sizeof(struct map_condition));
$<condition>$->tag = $<str>1;
$<condition>$->tag = $<str>1;
$<condition>$->op = $<op>2;
$<condition>$->value = $<str>3;
$<condition>$->value = $<str>3;
}
|
WORD CMP_OP STRING {
$<condition>$ = malloc(sizeof(struct map_condition));
$<condition>$->tag = $<str>1;
$<condition>$->tag = $<str>1;
$<condition>$->op = $<op>2;
$<condition>$->value = $<str>3;
$<condition>$->value = $<str>3;
}
|
L_PAR condition R_PAR { $<condition>$ = $<condition>2; }
|
NOT condition {
NOT condition {
$<condition>$ = malloc(sizeof(struct map_condition));
$<condition>$->cond1 = $<condition>2;
$<condition>$->op = MAP_OP_NOT;
@ -79,7 +79,7 @@ static char const*
token_to_str(yysymbol_kind_t tkn)
{
switch (tkn) {
case YYSYMBOL_CMP_OP: return "==, !=, <=, <, >=, >, ~~";
case YYSYMBOL_CMP_OP: return "==, !=, <=, <, >=, >";
case YYSYMBOL_BOOL_OP: return "||, &&";
case YYSYMBOL_L_PAR: return "(";
case YYSYMBOL_R_PAR: return ")";

View file

@ -84,12 +84,6 @@ EXTERN_MODULE(script);
#if defined(HAVE_PLUGIN_sway_xkb)
EXTERN_MODULE(sway_xkb);
#endif
#if defined(HAVE_PLUGIN_niri_language)
EXTERN_MODULE(niri_language);
#endif
#if defined(HAVE_PLUGIN_niri_workspaces)
EXTERN_MODULE(niri_workspaces);
#endif
#if defined(HAVE_PLUGIN_xkb)
EXTERN_MODULE(xkb);
#endif
@ -220,12 +214,6 @@ static void __attribute__((constructor)) init(void)
#if defined(HAVE_PLUGIN_sway_xkb)
REGISTER_CORE_MODULE(sway-xkb, sway_xkb);
#endif
#if defined(HAVE_PLUGIN_niri_language)
REGISTER_CORE_MODULE(niri-language, niri_language);
#endif
#if defined(HAVE_PLUGIN_niri_workspaces)
REGISTER_CORE_MODULE(niri-workspaces, niri_workspaces);
#endif
#if defined(HAVE_PLUGIN_xkb)
REGISTER_CORE_MODULE(xkb, xkb);
#endif

89
tag.c
View file

@ -430,12 +430,12 @@ sbuf_append(struct sbuf *s1, const char *s2)
// stores the number in "*value" on success
static bool
is_number(const char *str, long *value)
is_number(const char *str, int *value)
{
errno = 0;
char *end;
long v = strtol(str, &end, 10);
int v = strtol(str, &end, 10);
if (errno != 0 || *end != '\0')
return false;
@ -510,7 +510,12 @@ tags_expand_template(const char *template, const struct tag_set *tags)
FMT_HEX,
FMT_OCT,
FMT_PERCENT,
FMT_DIVIDE,
FMT_KBYTE,
FMT_MBYTE,
FMT_GBYTE,
FMT_KIBYTE,
FMT_MIBYTE,
FMT_GIBYTE,
} format
= FMT_DEFAULT;
@ -522,9 +527,8 @@ tags_expand_template(const char *template, const struct tag_set *tags)
} kind
= VALUE_VALUE;
long digits = 0;
long decimals = 2;
long divider = 1;
int digits = 0;
int decimals = 2;
bool zero_pad = false;
char *point = NULL;
@ -537,38 +541,18 @@ tags_expand_template(const char *template, const struct tag_set *tags)
format = FMT_OCT;
else if (strcmp(tag_args[i], "%") == 0)
format = FMT_PERCENT;
else if (*tag_args[i] == '/') {
format = FMT_DIVIDE;
const char *divider_str = tag_args[i] + 1;
if (!is_number(divider_str, &divider) || divider == 0) {
divider = 1;
LOG_WARN("tag `%s`: invalid divider %s, reset to 1", tag_name, divider_str);
}
}
else if (strcmp(tag_args[i], "kb") == 0) {
format = FMT_DIVIDE;
divider = 1000;
}
else if (strcmp(tag_args[i], "mb") == 0) {
format = FMT_DIVIDE;
divider = 1000 * 1000;
}
else if (strcmp(tag_args[i], "gb") == 0) {
format = FMT_DIVIDE;
divider = 1000 * 1000 * 1000;
}
else if (strcmp(tag_args[i], "kib") == 0) {
format = FMT_DIVIDE;
divider = 1024;
}
else if (strcmp(tag_args[i], "mib") == 0) {
format = FMT_DIVIDE;
divider = 1024 * 1024;
}
else if (strcmp(tag_args[i], "gib") == 0) {
format = FMT_DIVIDE;
divider = 1024 * 1024 * 1024;
}
else if (strcmp(tag_args[i], "kb") == 0)
format = FMT_KBYTE;
else if (strcmp(tag_args[i], "mb") == 0)
format = FMT_MBYTE;
else if (strcmp(tag_args[i], "gb") == 0)
format = FMT_GBYTE;
else if (strcmp(tag_args[i], "kib") == 0)
format = FMT_KIBYTE;
else if (strcmp(tag_args[i], "mib") == 0)
format = FMT_MIBYTE;
else if (strcmp(tag_args[i], "gib") == 0)
format = FMT_GIBYTE;
else if (strcmp(tag_args[i], "min") == 0)
kind = VALUE_MIN;
else if (strcmp(tag_args[i], "max") == 0)
@ -650,7 +634,20 @@ tags_expand_template(const char *template, const struct tag_set *tags)
break;
}
case FMT_DIVIDE: {
case FMT_KBYTE:
case FMT_MBYTE:
case FMT_GBYTE:
case FMT_KIBYTE:
case FMT_MIBYTE:
case FMT_GIBYTE: {
const long divider = format == FMT_KBYTE ? 1000
: format == FMT_MBYTE ? 1000 * 1000
: format == FMT_GBYTE ? 1000 * 1000 * 1000
: format == FMT_KIBYTE ? 1024
: format == FMT_MIBYTE ? 1024 * 1024
: format == FMT_GIBYTE ? 1024 * 1024 * 1024
: 1;
char str[24];
if (tag->type(tag) == TAG_TYPE_FLOAT) {
const char *fmt = zero_pad ? "%0*.*f" : "%*.*f";
@ -687,7 +684,19 @@ tags_expand_template(const char *template, const struct tag_set *tags)
fmt = zero_pad ? "%0*lu" : "%*lu";
break;
case FMT_DIVIDE: {
case FMT_KBYTE:
case FMT_MBYTE:
case FMT_GBYTE:
case FMT_KIBYTE:
case FMT_MIBYTE:
case FMT_GIBYTE: {
const long divider = format == FMT_KBYTE ? 1024
: format == FMT_MBYTE ? 1024 * 1024
: format == FMT_GBYTE ? 1024 * 1024 * 1024
: format == FMT_KIBYTE ? 1000
: format == FMT_MIBYTE ? 1000 * 1000
: format == FMT_GIBYTE ? 1000 * 1000 * 1000
: 1;
value /= divider;
fmt = zero_pad ? "%0*lu" : "%*lu";
break;

43
yml.c
View file

@ -366,47 +366,6 @@ format_error(enum yml_error err, const struct yml_node *parent, const struct yml
return err_str;
}
static char *
replace_env_variables(const char *str, size_t len)
{
char *result = strndup(str, len);
char *start, *key;
const char *end, *env_value;
const char* prefix = "${";
const char* suffix = "}";
const size_t pref_len = 2;
const size_t suff_len = 1;
size_t key_len;
while ((start = strstr(result, prefix)) != NULL &&
(end = strstr(start, suffix)) != NULL)
{
key_len = end - start - pref_len;
key = strndup(start + pref_len, key_len);
env_value = getenv(key);
if (env_value) {
size_t result_len = strlen(result);
size_t new_len = result_len - key_len - pref_len - suff_len + strlen(env_value);
char *new_result = malloc(new_len + 1);
strncpy(new_result, result, start - result);
new_result[start - result] = '\0';
strcat(new_result, env_value);
strcat(new_result, end + 1);
free(result);
result = new_result;
} else {
memmove(start, end + 1, strlen(end + 1) + 1);
}
free(key);
}
return result;
}
struct yml_node *
yml_load(FILE *yml, char **error)
{
@ -497,7 +456,7 @@ yml_load(FILE *yml, char **error)
case YAML_SCALAR_EVENT: {
struct yml_node *new_scalar = calloc(1, sizeof(*new_scalar));
new_scalar->type = SCALAR;
new_scalar->scalar.value = replace_env_variables((const char *)event.data.scalar.value, event.data.scalar.length);
new_scalar->scalar.value = strndup((const char *)event.data.scalar.value, event.data.scalar.length);
enum yml_error err = add_node(n, new_scalar, event.start_mark);
if (err != YML_ERR_NONE) {