diff --git a/.builds/alpine-x64.yml b/.builds/alpine-x64.yml index 1703a3d..e4ad80c 100644 --- a/.builds/alpine-x64.yml +++ b/.builds/alpine-x64.yml @@ -37,6 +37,10 @@ sources: # to: tasks: + - codespell: | + pip install codespell + cd yambar + ~/.local/bin/codespell README.md CHANGELOG.md *.c *.h doc/*.scd - fcft: | cd yambar/subprojects git clone https://codeberg.org/dnkl/fcft.git diff --git a/.clang-format b/.clang-format index 2436e90..528a36b 100644 --- a/.clang-format +++ b/.clang-format @@ -3,7 +3,6 @@ BasedOnStyle: GNU IndentWidth: 4 --- Language: Cpp -Standard: Auto PointerAlignment: Right ColumnLimit: 120 BreakBeforeBraces: Custom @@ -16,9 +15,3 @@ BraceWrapping: SpaceBeforeParens: ControlStatements Cpp11BracedListStyle: true - -WhitespaceSensitiveMacros: - - REGISTER_CORE_PARTICLE - - REGISTER_CORE_DECORATION - - REGISTER_CORE_PLUGIN - - REGISTER_CORE_MODULE diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..dd1db7b --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,114 @@ +image: alpine:latest + +stages: + - info + - build + +variables: + GIT_SUBMODULE_STRATEGY: normal + +before_script: + - apk update + - apk add musl-dev eudev-libs eudev-dev linux-headers meson ninja gcc scdoc + - apk add pixman-dev freetype-dev fontconfig-dev + - apk add libxcb-dev xcb-util-wm-dev xcb-util-cursor-dev yaml-dev + - apk add wayland-dev wayland-protocols wlroots-dev + - apk add json-c-dev libmpdclient-dev alsa-lib-dev pulseaudio-dev pipewire-dev + - apk add ttf-dejavu + - apk add git + - apk add flex bison + +versions: + stage: info + script: + - meson --version + - ninja --version + - cc --version + +debug: + stage: build + script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd .. + - apk add gcovr + - mkdir -p bld/debug + - cd bld/debug + - meson --buildtype=debug -Db_coverage=true ../.. + - ninja -k0 + - meson test --print-errorlogs + - ninja coverage-html + - mv meson-logs/coveragereport ../../coverage + - ninja coverage-text + - tail -2 meson-logs/coverage.txt + artifacts: + paths: + - coverage + coverage: '/^TOTAL.*\s+(\d+\%)$/' + +# valgrind: +# stage: build +# script: +# - apk add valgrind +# - mkdir -p bld/debug +# - cd bld/debug +# - meson --buildtype=debug ../.. +# - ninja -k0 +# - meson test --verbose --wrapper "valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=3" + +release: + stage: build + script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd .. + - mkdir -p bld/release + - cd bld/release + - meson --buildtype=minsize ../../ + - ninja -k0 + - meson test --print-errorlogs + +x11_only: + stage: build + script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd .. + - mkdir -p bld/debug + - cd bld/debug + - meson --buildtype=debug -Dbackend-x11=enabled -Dbackend-wayland=disabled ../../ + - ninja -k0 + - meson test --print-errorlogs + +wayland_only: + stage: build + script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd .. + - mkdir -p bld/debug + - cd bld/debug + - meson --buildtype=debug -Dbackend-x11=disabled -Dbackend-wayland=enabled ../../ + - ninja -k0 + - meson test --print-errorlogs + +plugins_as_shared_modules: + stage: build + script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd .. + - mkdir -p bld/debug + - cd bld/debug + - meson --buildtype=debug -Dcore-plugins-as-shared-libraries=true ../../ + - ninja -k0 + - meson test --print-errorlogs + +codespell: + image: alpine:latest + stage: build + script: + - apk add python3 + - apk add py3-pip + - pip install codespell + - codespell README.md CHANGELOG.md *.c *.h doc/*.scd diff --git a/.woodpecker.yaml b/.woodpecker.yml similarity index 80% rename from .woodpecker.yaml rename to .woodpecker.yml index e7c9151..058b08a 100644 --- a/.woodpecker.yaml +++ b/.woodpecker.yml @@ -1,25 +1,21 @@ -steps: - - name: codespell +pipeline: + codespell: when: - - event: [manual, pull_request] - - event: [push, tag] - branch: [master, releases/*] + branch: + - master + - releases/* image: alpine:latest commands: - - apk add openssl - apk add python3 - apk add py3-pip - - 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 - - deactivate + - codespell README.md CHANGELOG.md *.c *.h doc/*.scd - - name: subprojects + subprojects: when: - - event: [manual, pull_request] - - event: [push, tag] - branch: [master, releases/*] + branch: + - master + - releases/* image: alpine:latest commands: - apk add git @@ -28,12 +24,12 @@ steps: - git clone https://codeberg.org/dnkl/fcft.git - cd .. - - name: x64 + x64: when: - - event: [manual, pull_request] - - event: [push, tag] - branch: [master, releases/*] - depends_on: [subprojects] + branch: + - master + - releases/* + group: build image: alpine:latest commands: - apk update @@ -87,12 +83,12 @@ steps: - ./yambar --version - cd ../.. - - name: x86 + x86: when: - - event: [manual, pull_request] - - event: [push, tag] - branch: [master, releases/*] - depends_on: [subprojects] + branch: + - master + - releases/* + group: build image: i386/alpine:latest commands: - apk add musl-dev eudev-libs eudev-dev linux-headers meson ninja gcc scdoc diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e0e772..fd0b4e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,5 @@ # Changelog -* [Unreleased](#unreleased) -* [1.11.0](#1-11-0) -* [1.10.0](#1-10-0) * [1.9.0](#1-9-0) * [1.8.0](#1-8-0) * [1.7.0](#1-7-0) @@ -12,204 +9,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: `/` 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]). -* pipewire: added `spacing`, `left-spacing` and `right-spacing` - attributes. -* mpris: new module ([#53][53]). - -[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 -[53]: https://codeberg.org/dnkl/yambar/issues/53 - - -### 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 - -* battery: current smoothing, for improved discharge estimates. -* battery: scale option, for batteries that report 'charge' at a - different scale than 'current'. -* network: new `quality` tag (Wi-Fi only). -* Read alternative config from pipes and FIFOs (e.g. `--config - /dev/stdin`) ([#340][340]). -* Added `overlay` and `background` as possible `layer` values - ([#372][372]). - -[340]: https://codeberg.org/dnkl/yambar/pulls/340 -[372]: https://codeberg.org/dnkl/yambar/issues/372 - - -### Changed - -* log-level: default to `warning` -* network: use dynlist instead of fixed name ([#355][355]) - -[355]: https://codeberg.org/dnkl/yambar/pulls/355 - - -### Fixed - -* Compiler error _‘fmt’ may be used uninitialized_ ([#311][311]). -* map: conditions failing to match when they contain multiple, quoted - tag values ([#302][302]). -* Crash when hidden by an opaque window. -* Bar not resizing itself when the screen resolution is changed - ([#330][330]). -* i3/sway: incorrect empty/title state of workspaces ([#343][343]). -* mem: state updated on each bar redraw ([#352][352]). -* script: buffer overflow when reading large amounts of data. -* i3/sway: module fails when reloading config file ([#361][361]). -* Worked around bug in gcc causing a compilation error ([#350][350]). -* Miscalculation of list width in presence of empty particles ([#369][369]). -* Log-level not respected by syslog. - -[311]: https://codeberg.org/dnkl/yambar/issues/311 -[302]: https://codeberg.org/dnkl/yambar/issues/302 -[330]: https://codeberg.org/dnkl/yambar/issues/330 -[343]: https://codeberg.org/dnkl/yambar/issues/343 -[352]: https://codeberg.org/dnkl/yambar/issues/352 -[361]: https://codeberg.org/dnkl/yambar/issues/361 -[350]: https://codeberg.org/dnkl/yambar/issues/350 -[369]: https://codeberg.org/dnkl/yambar/issues/369 - - -### Contributors - -* Delgan -* Haden Collins -* Jordan Isaacs -* kotyk -* Leonardo Hernández Hernández -* oob -* rdbo -* Sertonix -* steovd -* Väinö Mäkelä -* Yiyu Zhou - - -## 1.10.0 - -### Added - -* Field width tag format option ([#246][246]) -* river: support for ‘layout’ events. -* dwl: support for specifying name of tags ([#256][256]) -* i3/sway: extend option `sort`; use `native` to sort numbered workspaces only. -* modules/dwl: handle the appid status ([#284][284]) -* battery: also show estimation for time to full ([#303][303]). -* on-click: tilde expansion ([#307][307]) -* script: tilde expansion of `path` ([#307][307]). - -[246]: https://codeberg.org/dnkl/yambar/issues/246 -[256]: https://codeberg.org/dnkl/yambar/pulls/256 -[284]: https://codeberg.org/dnkl/yambar/pulls/284 -[307]: https://codeberg.org/dnkl/yambar/issues/307 - - -### Changed - -* disk-io: `interval` renamed to `poll-interval` -* mem: `interval` renamed to `poll-interval` -* battery/network/script: `poll-interval` unit changed from seconds to - milliseconds ([#244][244]). -* all modules: minimum poll interval changed from 500ms to 250ms. -* network: do not use IPv6 link-local ([#281][281]) - -[244]: https://codeberg.org/dnkl/yambar/issues/244 -[281]: https://codeberg.org/dnkl/yambar/pulls/281 - - -### Fixed - -* Build failures for certain combinations of enabled and disabled - plugins ([#239][239]). -* Documentation for the `cpu` module; `interval` has been renamed to - `poll-interval` ([#241][241]). -* battery: module was not thread safe. -* dwl module reporting only the last part of the title ([#251][251]) -* i3/sway: regression; persistent workspaces shown twice - ([#253][253]). -* pipewire: use `roundf()` instead of `ceilf()` for more accuracy - ([#262][262]) -* Crash when a yaml anchor has a value that already exists in the - target yaml node ([#286][286]). -* battery: Fix time conversion in battery estimation ([#303][303]). -* battery: poll timeout being reset when receiving irrelevant udev - notification (leading to battery status never updating, in worst - case) ([#305][305]). - -[239]: https://codeberg.org/dnkl/yambar/issues/239 -[241]: https://codeberg.org/dnkl/yambar/issues/241 -[251]: https://codeberg.org/dnkl/yambar/pulls/251 -[253]: https://codeberg.org/dnkl/yambar/issues/253 -[262]: https://codeberg.org/dnkl/yambar/issues/262 -[286]: https://codeberg.org/dnkl/yambar/issues/286 -[305]: https://codeberg.org/dnkl/yambar/issues/305 - - -### Contributors - -* Leonardo Gibrowski Faé (Horus) -* Armin Fisslthaler -* Ben Brown -* David Bimmler -* Leonardo Hernández Hernández -* Ogromny -* Oleg Hahm -* Stanislav Ochotnický -* tiosgz -* Yutaro Ohno - - ## 1.9.0 ### Added diff --git a/PKGBUILD b/PKGBUILD index 6fc2d69..256706c 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,8 +1,7 @@ pkgname=yambar -pkgver=1.11.0 +pkgver=1.9.0 pkgrel=1 pkgdesc="Simplistic and highly configurable status panel for X and Wayland" -changelog=CHANGELOG.md arch=('x86_64' 'aarch64') url=https://codeberg.org/dnkl/yambar license=(mit) diff --git a/PKGBUILD.wayland-only b/PKGBUILD.wayland-only index 266fc06..b64ae25 100644 --- a/PKGBUILD.wayland-only +++ b/PKGBUILD.wayland-only @@ -1,5 +1,5 @@ pkgname=yambar-wayland -pkgver=1.11.0 +pkgver=1.9.0 pkgrel=1 pkgdesc="Simplistic and highly configurable status panel for Wayland" arch=('x86_64' 'aarch64') @@ -20,7 +20,6 @@ depends=( 'pipewire' 'fcft>=3.0.0' 'fcft<4.0.0') source=() -changelog=CHANGELOG.md pkgver() { cd ../.git &> /dev/null && git describe --tags --long | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' || diff --git a/README.md b/README.md index 4e825b3..c7b0505 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,7 @@ # Yambar -**This project is not developed anymore, and this repository will be -archived in a near future**. - -I do not have neither the time nor the will to work on this -anymore. Mainly because I do not use a bar myself anymore. - -There are also technical difficulties, caused by the fact that yambar -was initially X11, and only later was Wayland support added. - -This means I have to maintain a backend (X11) I have not used myself -in many years, as well as trying to work around technical limitations -imposed by the way both X11 and Wayland is supported, As my own use of -a bar has dwindled, the will to refactor and improve the backends has -disappeared. - -Yambar has seen a lot of contributions, for which I am very -grateful. I hope that means someone is willing to pick up where I left -of, and continue working on yambar. If not, we at least had a good -run; the first commit was in late 2018, roughly 6½ years ago! - - -[![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 @@ -80,9 +59,9 @@ bar: right: - clock: content: - - string: {text: , font: "Font Awesome 6 Free:style=solid:size=12"} + - string: {text: , font: "Font Awesome 5 Free:style=solid:size=12"} - string: {text: "{date}", right-margin: 5} - - string: {text: , font: "Font Awesome 6 Free:style=solid:size=12"} + - string: {text: , font: "Font Awesome 5 Free:style=solid:size=12"} - string: {text: "{time}"} ``` @@ -108,7 +87,6 @@ Available modules: * mem * mpd * network -* pipewire * pulse * removables * river @@ -128,7 +106,7 @@ mkdir -p bld/release && cd bld/release Second, configure the build (if you intend to install it globally, you might also want `--prefix=/usr`): ```sh -meson setup --buildtype=release ../.. +meson --buildtype=release ../.. ``` Optionally, explicitly disable a backend (or enable, if you want a diff --git a/bar/backend.h b/bar/backend.h index b7a9fcb..47fae95 100644 --- a/bar/backend.h +++ b/bar/backend.h @@ -7,8 +7,10 @@ struct backend { bool (*setup)(struct bar *bar); void (*cleanup)(struct bar *bar); - void (*loop)(struct bar *bar, void (*expose)(const struct bar *bar), - void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)); + void (*loop)(struct bar *bar, + void (*expose)(const struct bar *bar), + void (*on_mouse)(struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y)); void (*commit)(const struct bar *bar); void (*refresh)(const struct bar *bar); void (*set_cursor)(struct bar *bar, const char *cursor); diff --git a/bar/bar.c b/bar/bar.c index 109f210..10e0785 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -1,15 +1,15 @@ #include "bar.h" #include "private.h" -#include -#include -#include -#include -#include #include +#include #include +#include +#include #include +#include #include +#include #include @@ -18,17 +18,17 @@ #include "../log.h" #if defined(ENABLE_X11) -#include "xcb.h" + #include "xcb.h" #endif #if defined(ENABLE_WAYLAND) -#include "wayland.h" + #include "wayland.h" #endif #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 @@ -75,8 +75,9 @@ expose(const struct bar *_bar) const struct private *bar = _bar->private; pixman_image_t *pix = bar->pix; - pixman_image_fill_rectangles(PIXMAN_OP_SRC, pix, &bar->background, 1, - &(pixman_rectangle16_t){0, 0, bar->width, bar->height_with_border}); + pixman_image_fill_rectangles( + PIXMAN_OP_SRC, pix, &bar->background, 1, + &(pixman_rectangle16_t){0, 0, bar->width, bar->height_with_border}); pixman_image_fill_rectangles( PIXMAN_OP_OVER, pix, &bar->border.color, 4, @@ -85,15 +86,20 @@ expose(const struct bar *_bar) {0, 0, bar->border.left_width, bar->height_with_border}, /* Right */ - {bar->width - bar->border.right_width, 0, bar->border.right_width, bar->height_with_border}, + {bar->width - bar->border.right_width, + 0, bar->border.right_width, bar->height_with_border}, /* Top */ - {bar->border.left_width, 0, bar->width - bar->border.left_width - bar->border.right_width, + {bar->border.left_width, + 0, + bar->width - bar->border.left_width - bar->border.right_width, bar->border.top_width}, /* Bottom */ - {bar->border.left_width, bar->height_with_border - bar->border.bottom_width, - bar->width - bar->border.left_width - bar->border.right_width, bar->border.bottom_width}, + {bar->border.left_width, + bar->height_with_border - bar->border.bottom_width, + bar->width - bar->border.left_width - bar->border.right_width, + bar->border.bottom_width}, }); for (size_t i = 0; i < bar->left.count; i++) { @@ -130,8 +136,12 @@ expose(const struct bar *_bar) int x = bar->border.left_width + bar->left_margin - bar->left_spacing; pixman_region32_t clip; pixman_region32_init_rect( - &clip, bar->border.left_width + bar->left_margin, bar->border.top_width, - (bar->width - bar->left_margin - bar->right_margin - bar->border.left_width - bar->border.right_width), + &clip, + bar->border.left_width + bar->left_margin, + bar->border.top_width, + (bar->width - + bar->left_margin - bar->right_margin - + bar->border.left_width - bar->border.right_width), bar->height); pixman_image_set_clip_region32(pix, &clip); pixman_region32_fini(&clip); @@ -151,7 +161,11 @@ expose(const struct bar *_bar) x += bar->left_spacing + e->width + bar->right_spacing; } - x = bar->width - (right_width + bar->left_spacing + bar->right_margin + bar->border.right_width); + x = bar->width - ( + right_width + + bar->left_spacing + + bar->right_margin + + bar->border.right_width); for (size_t i = 0; i < bar->right.count; i++) { const struct exposable *e = bar->right.exps[i]; @@ -163,6 +177,7 @@ expose(const struct bar *_bar) bar->backend.iface->commit(_bar); } + static void refresh(const struct bar *bar) { @@ -185,12 +200,15 @@ output_name(const struct bar *bar) } static void -on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn, int x, int y) +on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn, + int x, int y) { struct private *bar = _bar->private; - if ((y < bar->border.top_width || y >= (bar->height_with_border - bar->border.bottom_width)) - || (x < bar->border.left_width || x >= (bar->width - bar->border.right_width))) { + if ((y < bar->border.top_width || + y >= (bar->height_with_border - bar->border.bottom_width)) || + (x < bar->border.left_width || x >= (bar->width - bar->border.right_width))) + { set_cursor(_bar, "left_ptr"); return; } @@ -232,7 +250,10 @@ on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn, int x, mx += e->width + bar->right_spacing; } - mx = bar->width - (right_width + bar->left_spacing + bar->right_margin + bar->border.right_width); + mx = bar->width - (right_width + + bar->left_spacing + + bar->right_margin + + bar->border.right_width); for (size_t i = 0; i < bar->right.count; i++) { struct exposable *e = bar->right.exps[i]; @@ -273,7 +294,8 @@ run(struct bar *_bar) { struct private *bar = _bar->private; - bar->height_with_border = bar->height + bar->border.top_width + bar->border.bottom_width; + bar->height_with_border = + bar->height + bar->border.top_width + bar->border.bottom_width; if (!bar->backend.iface->setup(_bar)) { bar->backend.iface->cleanup(_bar); @@ -325,7 +347,8 @@ run(struct bar *_bar) thrd_join(thrd_left[i], &mod_ret); if (mod_ret != 0) { const struct module *m = bar->left.mods[i]; - LOG_ERR("module: LEFT #%zu (%s): non-zero exit value: %d", i, m->description(m), mod_ret); + LOG_ERR("module: LEFT #%zu (%s): non-zero exit value: %d", + i, m->description(m), mod_ret); } ret = ret == 0 && mod_ret != 0 ? mod_ret : ret; } @@ -333,7 +356,8 @@ run(struct bar *_bar) thrd_join(thrd_center[i], &mod_ret); if (mod_ret != 0) { const struct module *m = bar->center.mods[i]; - LOG_ERR("module: CENTER #%zu (%s): non-zero exit value: %d", i, m->description(m), mod_ret); + LOG_ERR("module: CENTER #%zu (%s): non-zero exit value: %d", + i, m->description(m), mod_ret); } ret = ret == 0 && mod_ret != 0 ? mod_ret : ret; } @@ -341,7 +365,8 @@ run(struct bar *_bar) thrd_join(thrd_right[i], &mod_ret); if (mod_ret != 0) { const struct module *m = bar->right.mods[i]; - LOG_ERR("module: RIGHT #%zu (%s): non-zero exit value: %d", i, m->description(m), mod_ret); + LOG_ERR("module: RIGHT #%zu (%s): non-zero exit value: %d", + i, m->description(m), mod_ret); } ret = ret == 0 && mod_ret != 0 ? mod_ret : ret; } diff --git a/bar/bar.h b/bar/bar.h index ce91247..717b690 100644 --- a/bar/bar.h +++ b/bar/bar.h @@ -18,7 +18,7 @@ struct bar { }; enum bar_location { BAR_TOP, BAR_BOTTOM }; -enum bar_layer { BAR_LAYER_OVERLAY, BAR_LAYER_TOP, BAR_LAYER_BOTTOM, BAR_LAYER_BACKGROUND }; +enum bar_layer { BAR_LAYER_TOP, BAR_LAYER_BOTTOM }; enum bar_backend { BAR_BACKEND_AUTO, BAR_BACKEND_XCB, BAR_BACKEND_WAYLAND }; struct bar_config { diff --git a/bar/private.h b/bar/private.h index d48b07f..f216c99 100644 --- a/bar/private.h +++ b/bar/private.h @@ -3,8 +3,7 @@ #include "../bar/bar.h" #include "backend.h" -struct private -{ +struct private { /* From bar_config */ char *monitor; enum bar_layer layer; diff --git a/bar/wayland.c b/bar/wayland.c index 86ab252..edbf0db 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -1,25 +1,25 @@ #include "wayland.h" -#include -#include -#include -#include #include #include #include +#include #include +#include +#include +#include +#include #include #include -#include #include #include #include #include -#include #include +#include #define LOG_MODULE "bar:wayland" #define LOG_ENABLE_DBG 0 @@ -28,10 +28,6 @@ #include "private.h" -#if !defined(MFD_NOEXEC_SEAL) -#define MFD_NOEXEC_SEAL 0 -#endif - struct buffer { bool busy; size_t width; @@ -116,15 +112,16 @@ struct wayland_backend { /* We're already waiting for a frame done callback */ bool render_scheduled; - tll(struct buffer) buffers; /* List of SHM buffers */ - struct buffer *next_buffer; /* Bar is rendering to this one */ - struct buffer *pending_buffer; /* Finished, but not yet rendered */ + tll(struct buffer) buffers; /* List of SHM buffers */ + struct buffer *next_buffer; /* Bar is rendering to this one */ + struct buffer *pending_buffer; /* Finished, but not yet rendered */ struct wl_callback *frame_callback; double aggregated_scroll; bool have_discrete; - void (*bar_on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y); + void (*bar_on_mouse)(struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y); }; static void @@ -156,7 +153,7 @@ bar_backend_wayland_new(void) static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { - // printf("SHM format: 0x%08x\n", format); + //printf("SHM format: 0x%08x\n", format); } static const struct wl_shm_listener shm_listener = { @@ -166,7 +163,10 @@ static const struct wl_shm_listener shm_listener = { static void update_cursor_surface(struct wayland_backend *backend, struct seat *seat) { - if (seat->pointer.serial == 0 || seat->pointer.cursor == NULL || seat->pointer.surface == NULL) { + if (seat->pointer.serial == 0 || + seat->pointer.cursor == NULL || + seat->pointer.surface == NULL) + { return; } @@ -175,12 +175,17 @@ update_cursor_surface(struct wayland_backend *backend, struct seat *seat) const int scale = seat->pointer.scale; wl_surface_set_buffer_scale(seat->pointer.surface, scale); - wl_surface_attach(seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); + wl_surface_attach( + seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); - wl_pointer_set_cursor(seat->wl_pointer, seat->pointer.serial, seat->pointer.surface, image->hotspot_x / scale, - image->hotspot_y / scale); + wl_pointer_set_cursor( + seat->wl_pointer, seat->pointer.serial, + seat->pointer.surface, + image->hotspot_x / scale, image->hotspot_y / scale); - wl_surface_damage_buffer(seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); + + wl_surface_damage_buffer( + seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); wl_surface_commit(seat->pointer.surface); wl_display_flush(backend->display); @@ -210,9 +215,11 @@ reload_cursor_theme(struct seat *seat, int new_scale) } } - LOG_INFO("%s: cursor theme: %s, size: %u, scale: %d", seat->name, cursor_theme, cursor_size, new_scale); + LOG_INFO("%s: cursor theme: %s, size: %u, scale: %d", + seat->name, cursor_theme, cursor_size, new_scale); - struct wl_cursor_theme *theme = wl_cursor_theme_load(cursor_theme, cursor_size * new_scale, seat->backend->shm); + struct wl_cursor_theme *theme = wl_cursor_theme_load( + cursor_theme, cursor_size * new_scale, seat->backend->shm); if (theme == NULL) { LOG_ERR("%s: failed to load cursor theme", seat->name); @@ -224,7 +231,8 @@ reload_cursor_theme(struct seat *seat, int new_scale) } static void -wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, +wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct seat *seat = data; @@ -240,7 +248,8 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, str } static void -wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) +wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { struct seat *seat = data; struct wayland_backend *backend = seat->backend; @@ -252,7 +261,8 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, str } static void -wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) +wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct seat *seat = data; struct wayland_backend *backend = seat->backend; @@ -261,12 +271,14 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_f seat->pointer.y = wl_fixed_to_int(surface_y) * backend->scale; backend->active_seat = seat; - backend->bar_on_mouse(backend->bar, ON_MOUSE_MOTION, MOUSE_BTN_NONE, seat->pointer.x, seat->pointer.y); + backend->bar_on_mouse( + backend->bar, ON_MOUSE_MOTION, MOUSE_BTN_NONE, + seat->pointer.x, seat->pointer.y); } static void -wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, - uint32_t state) +wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { struct seat *seat = data; struct wayland_backend *backend = seat->backend; @@ -277,31 +289,23 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, ui enum mouse_button btn; switch (button) { - case BTN_LEFT: - btn = MOUSE_BTN_LEFT; - break; - case BTN_MIDDLE: - btn = MOUSE_BTN_MIDDLE; - break; - case BTN_RIGHT: - btn = MOUSE_BTN_RIGHT; - break; - case BTN_SIDE: - btn = MOUSE_BTN_PREVIOUS; - break; - case BTN_EXTRA: - btn = MOUSE_BTN_NEXT; - break; + case BTN_LEFT: btn = MOUSE_BTN_LEFT; break; + case BTN_MIDDLE: btn = MOUSE_BTN_MIDDLE; break; + case BTN_RIGHT: btn = MOUSE_BTN_RIGHT; break; + case BTN_SIDE: btn = MOUSE_BTN_PREVIOUS; break; + case BTN_EXTRA: btn = MOUSE_BTN_NEXT; break; default: return; } - backend->bar_on_mouse(backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y); + backend->bar_on_mouse( + backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y); } } static void -wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) +wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; @@ -317,18 +321,24 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32 const double amount = wl_fixed_to_double(value); - if ((backend->aggregated_scroll > 0 && amount < 0) || (backend->aggregated_scroll < 0 && amount > 0)) { + if ((backend->aggregated_scroll > 0 && amount < 0) || + (backend->aggregated_scroll < 0 && amount > 0)) + { backend->aggregated_scroll = amount; } else backend->aggregated_scroll += amount; - enum mouse_button btn = backend->aggregated_scroll > 0 ? MOUSE_BTN_WHEEL_DOWN : MOUSE_BTN_WHEEL_UP; + enum mouse_button btn = backend->aggregated_scroll > 0 + ? MOUSE_BTN_WHEEL_DOWN + : MOUSE_BTN_WHEEL_UP; const double step = bar->trackpad_sensitivity; const double adjust = backend->aggregated_scroll > 0 ? -step : step; while (fabs(backend->aggregated_scroll) >= step) { - backend->bar_on_mouse(backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y); + backend->bar_on_mouse( + backend->bar, ON_MOUSE_CLICK, btn, + seat->pointer.x, seat->pointer.y); backend->aggregated_scroll += adjust; } } @@ -342,12 +352,14 @@ wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) } static void -wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source) +wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { } static void -wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) +wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; @@ -358,7 +370,8 @@ wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, u } static void -wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) +wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) return; @@ -367,12 +380,16 @@ wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axi struct wayland_backend *backend = seat->backend; backend->have_discrete = true; - enum mouse_button btn = discrete > 0 ? MOUSE_BTN_WHEEL_DOWN : MOUSE_BTN_WHEEL_UP; + enum mouse_button btn = discrete > 0 + ? MOUSE_BTN_WHEEL_DOWN + : MOUSE_BTN_WHEEL_UP; int count = abs(discrete); for (int32_t i = 0; i < count; i++) { - backend->bar_on_mouse(backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y); + backend->bar_on_mouse( + backend->bar, ON_MOUSE_CLICK, btn, + seat->pointer.x, seat->pointer.y); } } @@ -389,14 +406,16 @@ static const struct wl_pointer_listener pointer_listener = { }; static void -seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { struct seat *seat = data; if (caps & WL_SEAT_CAPABILITY_POINTER) { if (seat->wl_pointer == NULL) { assert(seat->pointer.surface == NULL); - seat->pointer.surface = wl_compositor_create_surface(seat->backend->compositor); + seat->pointer.surface = wl_compositor_create_surface( + seat->backend->compositor); if (seat->pointer.surface == NULL) { LOG_ERR("%s: failed to create pointer surface", seat->name); @@ -436,8 +455,10 @@ static const struct wl_seat_listener seat_listener = { }; static void -output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, - int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform) +output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, + int32_t physical_width, int32_t physical_height, + int32_t subpixel, const char *make, const char *model, + int32_t transform) { struct monitor *mon = data; mon->width_mm = physical_width; @@ -445,29 +466,19 @@ output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, i } static void -output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) +output_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int32_t width, int32_t height, int32_t refresh) +{ +} + +static void +output_done(void *data, struct wl_output *wl_output) { } static bool update_size(struct wayland_backend *backend); static void refresh(const struct bar *_bar); -static void -output_done(void *data, struct wl_output *wl_output) -{ - struct monitor *mon = data; - - if (mon->backend->monitor == mon) { - int old_scale = mon->backend->scale; - int old_width = mon->backend->width; - - update_size(mon->backend); - - if (mon->backend->scale != old_scale || mon->backend->width != old_width) - refresh(mon->backend->bar); - } -} - static void output_scale(void *data, struct wl_output *wl_output, int32_t factor) { @@ -476,6 +487,14 @@ output_scale(void *data, struct wl_output *wl_output, int32_t factor) return; mon->scale = factor; + + if (mon->backend->monitor == mon) { + int old_scale = mon->backend->scale; + update_size(mon->backend); + + if (mon->backend->scale != old_scale) + refresh(mon->backend->bar); + } } #if defined(WL_OUTPUT_NAME_SINCE_VERSION) @@ -490,7 +509,8 @@ output_name(void *data, struct wl_output *wl_output, const char *name) #if defined(WL_OUTPUT_DESCRIPTION_SINCE_VERSION) static void -output_description(void *data, struct wl_output *wl_output, const char *description) +output_description(void *data, struct wl_output *wl_output, + const char *description) { } #endif @@ -509,7 +529,9 @@ static const struct wl_output_listener output_listener = { }; static void -xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) +xdg_output_handle_logical_position(void *data, + struct zxdg_output_v1 *xdg_output, + int32_t x, int32_t y) { struct monitor *mon = data; mon->x = x; @@ -517,7 +539,8 @@ xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output } static void -xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) +xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, + int32_t width, int32_t height) { struct monitor *mon = data; mon->width_px = width; @@ -532,8 +555,9 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) { const struct monitor *mon = data; - LOG_INFO("monitor: %s: %dx%d+%d+%d (%dx%dmm)", mon->name, mon->width_px, mon->height_px, mon->x, mon->y, - mon->width_mm, mon->height_mm); + LOG_INFO("monitor: %s: %dx%d+%d+%d (%dx%dmm)", + mon->name, mon->width_px, mon->height_px, + mon->x, mon->y, mon->width_mm, mon->height_mm); struct wayland_backend *backend = mon->backend; struct private *bar = backend->bar->private; @@ -545,11 +569,15 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) return; } - const bool output_is_our_configured_monitor - = (bar->monitor != NULL && mon->name != NULL && strcmp(bar->monitor, mon->name) == 0); + const bool output_is_our_configured_monitor = ( + bar->monitor != NULL && + mon->name != NULL && + strcmp(bar->monitor, mon->name) == 0); - const bool output_is_last_mapped = (backend->last_mapped_monitor != NULL && mon->name != NULL - && strcmp(backend->last_mapped_monitor, mon->name) == 0); + const bool output_is_last_mapped = ( + backend->last_mapped_monitor != NULL && + mon->name != NULL && + strcmp(backend->last_mapped_monitor, mon->name) == 0); if (output_is_our_configured_monitor) LOG_DBG("%s: using this monitor (user configured)", mon->name); @@ -571,7 +599,8 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) } static void -xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name) +xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, + const char *name) { struct monitor *mon = data; free(mon->name); @@ -579,7 +608,8 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char } static void -xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description) +xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, + const char *description) { } @@ -597,12 +627,14 @@ verify_iface_version(const char *iface, uint32_t version, uint32_t wanted) if (version >= wanted) return true; - LOG_ERR("%s: need interface version %u, but compositor only implements %u", iface, wanted, version); + LOG_ERR("%s: need interface version %u, but compositor only implements %u", + iface, wanted, version); return false; } static void -handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) +handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { LOG_DBG("global: 0x%08x, interface=%s, version=%u", name, interface, version); struct wayland_backend *backend = data; @@ -612,7 +644,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - backend->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, required); + backend->compositor = wl_registry_bind( + registry, name, &wl_compositor_interface, required); } else if (strcmp(interface, wl_shm_interface.name) == 0) { @@ -620,7 +653,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - backend->shm = wl_registry_bind(registry, name, &wl_shm_interface, required); + backend->shm = wl_registry_bind( + registry, name, &wl_shm_interface, required); wl_shm_add_listener(backend->shm, &shm_listener, backend); } @@ -629,9 +663,13 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, required); + struct wl_output *output = wl_registry_bind( + registry, name, &wl_output_interface, required); - tll_push_back(backend->monitors, ((struct monitor){.backend = backend, .wl_name = name, .output = output})); + tll_push_back(backend->monitors, ((struct monitor){ + .backend = backend, + .wl_name = name, + .output = output})); struct monitor *mon = &tll_back(backend->monitors); wl_output_add_listener(output, &output_listener, mon); @@ -644,7 +682,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha assert(backend->xdg_output_manager != NULL); if (backend->xdg_output_manager != NULL) { - mon->xdg = zxdg_output_manager_v1_get_xdg_output(backend->xdg_output_manager, mon->output); + mon->xdg = zxdg_output_manager_v1_get_xdg_output( + backend->xdg_output_manager, mon->output); zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon); } @@ -655,7 +694,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - backend->layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, required); + backend->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, required); } else if (strcmp(interface, wl_seat_interface.name) == 0) { @@ -663,10 +703,12 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - struct wl_seat *seat = wl_registry_bind(registry, name, &wl_seat_interface, required); + struct wl_seat *seat = wl_registry_bind( + registry, name, &wl_seat_interface, required); assert(seat != NULL); - tll_push_back(backend->seats, ((struct seat){.backend = backend, .seat = seat, .id = name})); + tll_push_back( + backend->seats, ((struct seat){.backend = backend, .seat = seat, .id = name})); wl_seat_add_listener(seat, &seat_listener, &tll_back(backend->seats)); } @@ -676,7 +718,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - backend->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, required); + backend->xdg_output_manager = wl_registry_bind( + registry, name, &zxdg_output_manager_v1_interface, required); } } @@ -685,8 +728,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { struct wayland_backend *backend = data; - tll_foreach(backend->seats, it) - { + tll_foreach(backend->seats, it) { if (it->item.id == name) { if (backend->active_seat == &it->item) backend->active_seat = NULL; @@ -696,8 +738,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) } } - tll_foreach(backend->monitors, it) - { + tll_foreach(backend->monitors, it) { struct monitor *mon = &it->item; if (mon->wl_name == name) { LOG_INFO("%s disconnected/disabled", mon->name); @@ -722,7 +763,8 @@ static const struct wl_registry_listener registry_listener = { }; static void -layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h) +layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t w, uint32_t h) { struct wayland_backend *backend = data; backend->width = w * backend->scale; @@ -765,43 +807,33 @@ create_surface(struct wayland_backend *backend) wl_surface_add_listener(backend->surface, &surface_listener, backend); - enum zwlr_layer_shell_v1_layer layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; - - switch (bar->layer) { - case BAR_LAYER_BACKGROUND: - layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; - break; - - case BAR_LAYER_BOTTOM: - layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; - break; - - case BAR_LAYER_TOP: - layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; - break; - - case BAR_LAYER_OVERLAY: - layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; - break; - } + enum zwlr_layer_shell_v1_layer layer = bar->layer == BAR_LAYER_BOTTOM + ? ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM + : ZWLR_LAYER_SHELL_V1_LAYER_TOP; backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - backend->layer_shell, backend->surface, backend->monitor != NULL ? backend->monitor->output : NULL, layer, - "panel"); + backend->layer_shell, backend->surface, + backend->monitor != NULL ? backend->monitor->output : NULL, + layer, "panel"); if (backend->layer_surface == NULL) { LOG_ERR("failed to create layer shell surface"); return false; } - zwlr_layer_surface_v1_add_listener(backend->layer_surface, &layer_surface_listener, backend); + zwlr_layer_surface_v1_add_listener( + backend->layer_surface, &layer_surface_listener, backend); /* Aligned to top, maximum width */ - enum zwlr_layer_surface_v1_anchor top_or_bottom - = bar->location == BAR_TOP ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + enum zwlr_layer_surface_v1_anchor top_or_bottom = bar->location == BAR_TOP + ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; - zwlr_layer_surface_v1_set_anchor(backend->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT - | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | top_or_bottom); + zwlr_layer_surface_v1_set_anchor( + backend->layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + top_or_bottom); return true; } @@ -834,7 +866,7 @@ destroy_surface(struct wayland_backend *backend) static void buffer_release(void *data, struct wl_buffer *wl_buffer) { - // printf("buffer release\n"); + //printf("buffer release\n"); struct buffer *buffer = data; assert(buffer->busy); buffer->busy = false; @@ -847,8 +879,7 @@ static const struct wl_buffer_listener buffer_listener = { static struct buffer * get_buffer(struct wayland_backend *backend) { - tll_foreach(backend->buffers, it) - { + tll_foreach(backend->buffers, it) { if (!it->item.busy && it->item.width == backend->width && it->item.height == backend->height) { it->item.busy = true; return &it->item; @@ -876,16 +907,7 @@ get_buffer(struct wayland_backend *backend) /* Backing memory for SHM */ #if defined(MEMFD_CREATE) - /* - * Older kernels reject MFD_NOEXEC_SEAL with EINVAL. Try first - * *with* it, and if that fails, try again *without* it. - */ - errno = 0; - pool_fd = memfd_create("yambar-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL); - - if (pool_fd < 0 && errno == EINVAL) { - pool_fd = memfd_create("yambar-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING); - } + pool_fd = memfd_create("yambar-wayland-shm-buffer-pool", MFD_CLOEXEC); #elif defined(__FreeBSD__) // memfd_create on FreeBSD 13 is SHM_ANON without sealing support pool_fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600); @@ -900,7 +922,8 @@ get_buffer(struct wayland_backend *backend) } /* Total size */ - const uint32_t stride = stride_for_format_and_width(PIXMAN_a8r8g8b8, backend->width); + const uint32_t stride = stride_for_format_and_width( + PIXMAN_a8r8g8b8, backend->width); size = stride * backend->height; if (ftruncate(pool_fd, size) == -1) { @@ -914,50 +937,43 @@ get_buffer(struct wayland_backend *backend) goto err; } -#if defined(MEMFD_CREATE) - /* Seal file - we no longer allow any kind of resizing */ - /* TODO: wayland mmaps(PROT_WRITE), for some unknown reason, hence we cannot use F_SEAL_FUTURE_WRITE */ - if (fcntl(pool_fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0) { - LOG_ERRNO("failed to seal SHM backing memory file"); - /* This is not a fatal error */ - } -#endif - pool = wl_shm_create_pool(backend->shm, pool_fd, size); if (pool == NULL) { LOG_ERR("failed to create SHM pool"); goto err; } - buf = wl_shm_pool_create_buffer(pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888); + buf = wl_shm_pool_create_buffer( + pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888); if (buf == NULL) { LOG_ERR("failed to create SHM buffer"); goto err; } /* We use the entire pool for our single buffer */ - wl_shm_pool_destroy(pool); - pool = NULL; - close(pool_fd); - pool_fd = -1; + wl_shm_pool_destroy(pool); pool = NULL; + close(pool_fd); pool_fd = -1; - pix = pixman_image_create_bits_no_clear(PIXMAN_a8r8g8b8, backend->width, backend->height, (uint32_t *)mmapped, - stride); + pix = pixman_image_create_bits_no_clear( + PIXMAN_a8r8g8b8, backend->width, backend->height, (uint32_t *)mmapped, stride); if (pix == NULL) { LOG_ERR("failed to create pixman image"); goto err; } /* Push to list of available buffers, but marked as 'busy' */ - tll_push_back(backend->buffers, ((struct buffer){ - .busy = true, - .width = backend->width, - .height = backend->height, - .size = size, - .mmapped = mmapped, - .wl_buf = buf, - .pix = pix, - })); + tll_push_back( + backend->buffers, + ((struct buffer){ + .busy = true, + .width = backend->width, + .height = backend->height, + .size = size, + .mmapped = mmapped, + .wl_buf = buf, + .pix = pix, + }) + ); struct buffer *ret = &tll_back(backend->buffers); wl_buffer_add_listener(ret->wl_buf, &buffer_listener, ret); @@ -987,8 +1003,7 @@ guess_scale(const struct wayland_backend *backend) bool all_have_same_scale = true; int last_scale = -1; - tll_foreach(backend->monitors, it) - { + tll_foreach(backend->monitors, it) { if (last_scale == -1) last_scale = it->item.scale; else if (last_scale != it->item.scale) { @@ -1016,6 +1031,9 @@ update_size(struct wayland_backend *backend) assert(backend->surface != NULL); + if (backend->scale == scale) + return true; + backend->scale = scale; int height = bar->height_with_border; @@ -1024,21 +1042,29 @@ update_size(struct wayland_backend *backend) bar->height = height - bar->border.top_width - bar->border.bottom_width; bar->height_with_border = height; - zwlr_layer_surface_v1_set_size(backend->layer_surface, 0, bar->height_with_border / scale); + zwlr_layer_surface_v1_set_size( + backend->layer_surface, 0, bar->height_with_border / scale); zwlr_layer_surface_v1_set_exclusive_zone( backend->layer_surface, - (bar->height_with_border + (bar->location == BAR_TOP ? bar->border.bottom_margin : bar->border.top_margin)) - / scale); + (bar->height_with_border + (bar->location == BAR_TOP + ? bar->border.bottom_margin + : bar->border.top_margin)) + / scale); - zwlr_layer_surface_v1_set_margin(backend->layer_surface, bar->border.top_margin / scale, - bar->border.right_margin / scale, bar->border.bottom_margin / scale, - bar->border.left_margin / scale); + zwlr_layer_surface_v1_set_margin( + backend->layer_surface, + bar->border.top_margin / scale, + bar->border.right_margin / scale, + bar->border.bottom_margin / scale, + bar->border.left_margin / scale + ); /* Trigger a 'configure' event, after which we'll have the width */ wl_surface_commit(backend->surface); wl_display_roundtrip(backend->display); - if (backend->width == -1 || backend->height != bar->height_with_border) { + if (backend->width == -1 || + backend->height != bar->height_with_border) { LOG_ERR("failed to get panel width"); return false; } @@ -1108,7 +1134,8 @@ setup(struct bar *_bar) return false; } - assert(backend->monitor == NULL || backend->width / backend->monitor->scale <= backend->monitor->width_px); + assert(backend->monitor == NULL || + backend->width / backend->monitor->scale <= backend->monitor->width_px); if (pipe2(backend->pipe_fds, O_CLOEXEC | O_NONBLOCK) == -1) { LOG_ERRNO("failed to create pipe"); @@ -1130,8 +1157,7 @@ cleanup(struct bar *_bar) if (backend->pipe_fds[1] >= 0) close(backend->pipe_fds[1]); - tll_foreach(backend->monitors, it) - { + tll_foreach(backend->monitors, it) { struct monitor *mon = &it->item; free(mon->name); @@ -1146,13 +1172,13 @@ cleanup(struct bar *_bar) if (backend->xdg_output_manager != NULL) zxdg_output_manager_v1_destroy(backend->xdg_output_manager); - tll_foreach(backend->seats, it) seat_destroy(&it->item); + tll_foreach(backend->seats, it) + seat_destroy(&it->item); tll_free(backend->seats); destroy_surface(backend); - tll_foreach(backend->buffers, it) - { + tll_foreach(backend->buffers, it) { if (it->item.wl_buf != NULL) wl_buffer_destroy(it->item.wl_buf); if (it->item.pix != NULL) @@ -1177,11 +1203,14 @@ cleanup(struct bar *_bar) /* Destroyed when freeing buffer list */ bar->pix = NULL; + } static void -loop(struct bar *_bar, void (*expose)(const struct bar *bar), - void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)) +loop(struct bar *_bar, + void (*expose)(const struct bar *bar), + void (*on_mouse)(struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y)) { struct private *bar = _bar->private; struct wayland_backend *backend = bar->backend.data; @@ -1223,7 +1252,7 @@ loop(struct bar *_bar, void (*expose)(const struct bar *bar), bool do_expose = false; /* Coalesce “refresh” commands */ - __attribute__((unused)) size_t count = 0; + size_t count = 0; while (true) { uint8_t command; ssize_t r = read(backend->pipe_fds[0], &command, sizeof(command)); @@ -1268,23 +1297,22 @@ out: if (!send_abort_to_modules) return; - if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) { + if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) + != sizeof(uint64_t)) + { LOG_ERRNO("failed to signal abort to modules"); } - // wl_display_cancel_read(backend->display); + //wl_display_cancel_read(backend->display); } static void -surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) +surface_enter(void *data, struct wl_surface *wl_surface, + struct wl_output *wl_output) { struct wayland_backend *backend = data; - free(backend->last_mapped_monitor); - backend->last_mapped_monitor = NULL; - - tll_foreach(backend->monitors, it) - { + tll_foreach(backend->monitors, it) { struct monitor *mon = &it->item; if (mon->output != wl_output) @@ -1304,7 +1332,8 @@ surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_ou } static void -surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output) +surface_leave(void *data, struct wl_surface *wl_surface, + struct wl_output *wl_output) { struct wayland_backend *backend = data; const struct monitor *mon = backend->monitor; @@ -1323,7 +1352,8 @@ static const struct wl_surface_listener surface_listener = { .leave = &surface_leave, }; -static void frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data); +static void frame_callback( + void *data, struct wl_callback *wl_callback, uint32_t callback_data); static const struct wl_callback_listener frame_listener = { .done = &frame_callback, @@ -1332,7 +1362,7 @@ static const struct wl_callback_listener frame_listener = { static void frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data) { - // printf("frame callback\n"); + //printf("frame callback\n"); struct private *bar = data; struct wayland_backend *backend = bar->backend.data; @@ -1359,7 +1389,7 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da backend->pending_buffer = NULL; backend->render_scheduled = true; } else - ; // printf("nothing more to do\n"); + ;//printf("nothing more to do\n"); } static void @@ -1368,7 +1398,7 @@ commit(const struct bar *_bar) struct private *bar = _bar->private; struct wayland_backend *backend = bar->backend.data; - // printf("commit: %dxl%d\n", backend->width, backend->height); + //printf("commit: %dxl%d\n", backend->width, backend->height); if (backend->next_buffer == NULL) return; @@ -1377,7 +1407,7 @@ commit(const struct bar *_bar) assert(backend->next_buffer->busy); if (backend->render_scheduled) { - // printf("already scheduled\n"); + //printf("already scheduled\n"); if (backend->pending_buffer != NULL) backend->pending_buffer->busy = false; @@ -1386,7 +1416,7 @@ commit(const struct bar *_bar) backend->next_buffer = NULL; } else { - // printf("scheduling new frame callback\n"); + //printf("scheduling new frame callback\n"); struct buffer *buffer = backend->next_buffer; assert(buffer->busy); @@ -1414,7 +1444,9 @@ refresh(const struct bar *_bar) const struct private *bar = _bar->private; const struct wayland_backend *backend = bar->backend.data; - if (write(backend->pipe_fds[1], &(uint8_t){1}, sizeof(uint8_t)) != sizeof(uint8_t)) { + if (write(backend->pipe_fds[1], &(uint8_t){1}, sizeof(uint8_t)) + != sizeof(uint8_t)) + { LOG_ERRNO("failed to signal 'refresh' to main thread"); } } @@ -1434,7 +1466,8 @@ set_cursor(struct bar *_bar, const char *cursor) seat->pointer.xcursor = cursor; - seat->pointer.cursor = wl_cursor_theme_get_cursor(seat->pointer.theme, cursor); + seat->pointer.cursor = wl_cursor_theme_get_cursor( + seat->pointer.theme, cursor); if (seat->pointer.cursor == NULL) { LOG_ERR("%s: failed to load cursor '%s'", seat->name, cursor); diff --git a/bar/xcb.c b/bar/xcb.c index ae52bf3..d8c5f9c 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -1,16 +1,16 @@ #include "xcb.h" -#include #include +#include +#include #include #include -#include #include +#include #include #include -#include #include #include #include @@ -39,6 +39,7 @@ struct xcb_backend { void *client_pixmap; size_t client_pixmap_size; pixman_image_t *pix; + }; void * @@ -54,8 +55,11 @@ setup(struct bar *_bar) struct private *bar = _bar->private; struct xcb_backend *backend = bar->backend.data; - if (bar->border.left_margin != 0 || bar->border.right_margin != 0 || bar->border.top_margin != 0 - || bar->border.bottom_margin) { + if (bar->border.left_margin != 0 || + bar->border.right_margin != 0 || + bar->border.top_margin != 0 || + bar->border.bottom_margin) + { LOG_WARN("non-zero border margins ignored in X11 backend"); } @@ -72,8 +76,10 @@ setup(struct bar *_bar) xcb_screen_t *screen = xcb_aux_get_screen(backend->conn, default_screen); - xcb_randr_get_monitors_reply_t *monitors - = xcb_randr_get_monitors_reply(backend->conn, xcb_randr_get_monitors(backend->conn, screen->root, 0), &e); + xcb_randr_get_monitors_reply_t *monitors = xcb_randr_get_monitors_reply( + backend->conn, + xcb_randr_get_monitors(backend->conn, screen->root, 0), + &e); if (e != NULL) { LOG_ERR("failed to get monitor list: %s", xcb_error(e)); @@ -84,13 +90,17 @@ setup(struct bar *_bar) /* Find monitor coordinates and width/height */ bool found_monitor = false; - for (xcb_randr_monitor_info_iterator_t it = xcb_randr_get_monitors_monitors_iterator(monitors); it.rem > 0; - xcb_randr_monitor_info_next(&it)) { + for (xcb_randr_monitor_info_iterator_t it = + xcb_randr_get_monitors_monitors_iterator(monitors); + it.rem > 0; + xcb_randr_monitor_info_next(&it)) + { const xcb_randr_monitor_info_t *mon = it.data; char *name = get_atom_name(backend->conn, mon->name); - LOG_INFO("monitor: %s: %ux%u+%u+%u (%ux%umm)", name, mon->width, mon->height, mon->x, mon->y, - mon->width_in_millimeters, mon->height_in_millimeters); + LOG_INFO("monitor: %s: %ux%u+%u+%u (%ux%umm)", name, + mon->width, mon->height, mon->x, mon->y, + mon->width_in_millimeters, mon->height_in_millimeters); /* User wants a specific monitor, and this is not the one */ if (bar->monitor != NULL && strcmp(bar->monitor, name) != 0) { @@ -101,11 +111,14 @@ 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; - if ((bar->monitor != NULL && strcmp(bar->monitor, name) == 0) || (bar->monitor == NULL && mon->primary)) { + if ((bar->monitor != NULL && strcmp(bar->monitor, name) == 0) || + (bar->monitor == NULL && mon->primary)) + { /* Exact match */ free(name); break; @@ -142,34 +155,61 @@ setup(struct bar *_bar) LOG_DBG("using a %hhu-bit visual", depth); backend->colormap = xcb_generate_id(backend->conn); - xcb_create_colormap(backend->conn, 0, backend->colormap, screen->root, vis->visual_id); + xcb_create_colormap( + backend->conn, 0, backend->colormap, screen->root, vis->visual_id); backend->win = xcb_generate_id(backend->conn); xcb_create_window( - backend->conn, depth, backend->win, screen->root, backend->x, backend->y, bar->width, bar->height_with_border, - 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vis->visual_id, - (XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP), - (const uint32_t[]){screen->black_pixel, screen->white_pixel, - (XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS - | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_STRUCTURE_NOTIFY), - backend->colormap}); + backend->conn, + depth, backend->win, screen->root, + backend->x, backend->y, bar->width, bar->height_with_border, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, vis->visual_id, + (XCB_CW_BACK_PIXEL | + XCB_CW_BORDER_PIXEL | + XCB_CW_EVENT_MASK | + XCB_CW_COLORMAP), + (const uint32_t []){ + screen->black_pixel, + screen->white_pixel, + (XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_POINTER_MOTION | + XCB_EVENT_MASK_STRUCTURE_NOTIFY), + backend->colormap} + ); const char *title = "yambar"; - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, - strlen(title), title); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, + strlen(title), title); - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, - (const uint32_t[]){getpid()}); - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, 1, - (const uint32_t[]){_NET_WM_WINDOW_TYPE_DOCK}); - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_STATE, XCB_ATOM_ATOM, 32, 2, - (const uint32_t[]){_NET_WM_STATE_ABOVE, _NET_WM_STATE_STICKY}); - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, - (const uint32_t[]){0xffffffff}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){getpid()}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, + 1, (const uint32_t []){_NET_WM_WINDOW_TYPE_DOCK}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_STATE, XCB_ATOM_ATOM, 32, + 2, (const uint32_t []){_NET_WM_STATE_ABOVE, _NET_WM_STATE_STICKY}); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){0xffffffff}); /* Always on top */ - xcb_configure_window(backend->conn, backend->win, XCB_CONFIG_WINDOW_STACK_MODE, - (const uint32_t[]){XCB_STACK_MODE_ABOVE}); + xcb_configure_window( + backend->conn, backend->win, XCB_CONFIG_WINDOW_STACK_MODE, + (const uint32_t []){XCB_STACK_MODE_ABOVE}); uint32_t top_strut, bottom_strut; uint32_t top_pair[2], bottom_pair[2]; @@ -192,38 +232,42 @@ setup(struct bar *_bar) uint32_t strut[] = { /* left/right/top/bottom */ - 0, - 0, + 0, 0, top_strut, bottom_strut, /* start/end pairs for left/right/top/bottom */ - 0, - 0, - 0, - 0, - top_pair[0], - top_pair[1], - bottom_pair[0], - bottom_pair[1], + 0, 0, + 0, 0, + top_pair[0], top_pair[1], + bottom_pair[0], bottom_pair[1], }; - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4, - strut); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, + 4, strut); - xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, - 32, 12, strut); + xcb_change_property( + backend->conn, + XCB_PROP_MODE_REPLACE, backend->win, + _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, + 12, strut); backend->gc = xcb_generate_id(backend->conn); - xcb_create_gc(backend->conn, backend->gc, backend->win, XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, - (const uint32_t[]){screen->white_pixel, 0}); + xcb_create_gc(backend->conn, backend->gc, backend->win, + XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, + (const uint32_t []){screen->white_pixel, 0}); - const uint32_t stride = stride_for_format_and_width(PIXMAN_a8r8g8b8, bar->width); + const uint32_t stride = stride_for_format_and_width( + PIXMAN_a8r8g8b8, bar->width); backend->client_pixmap_size = stride * bar->height_with_border; backend->client_pixmap = malloc(backend->client_pixmap_size); - backend->pix = pixman_image_create_bits_no_clear(PIXMAN_a8r8g8b8, bar->width, bar->height_with_border, - (uint32_t *)backend->client_pixmap, stride); + backend->pix = pixman_image_create_bits_no_clear( + PIXMAN_a8r8g8b8, bar->width, bar->height_with_border, + (uint32_t *)backend->client_pixmap, stride); bar->pix = backend->pix; xcb_map_window(backend->conn, backend->win); @@ -266,8 +310,10 @@ cleanup(struct bar *_bar) } static void -loop(struct bar *_bar, void (*expose)(const struct bar *bar), - void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)) +loop(struct bar *_bar, + void (*expose)(const struct bar *bar), + void (*on_mouse)(struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y)) { struct private *bar = _bar->private; struct xcb_backend *backend = bar->backend.data; @@ -277,7 +323,10 @@ loop(struct bar *_bar, void (*expose)(const struct bar *bar), const int fd = xcb_get_file_descriptor(backend->conn); while (true) { - struct pollfd fds[] = {{.fd = _bar->abort_fd, .events = POLLIN}, {.fd = fd, .events = POLLIN}}; + struct pollfd fds[] = { + {.fd = _bar->abort_fd, .events = POLLIN}, + {.fd = fd, .events = POLLIN} + }; poll(fds, sizeof(fds) / sizeof(fds[0]), -1); @@ -286,14 +335,18 @@ loop(struct bar *_bar, void (*expose)(const struct bar *bar), if (fds[1].revents & POLLHUP) { LOG_WARN("disconnected from XCB"); - if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) { + if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) + != sizeof(uint64_t)) + { LOG_ERRNO("failed to signal abort to modules"); } break; } - for (xcb_generic_event_t *e = xcb_wait_for_event(backend->conn); e != NULL; - e = xcb_poll_for_event(backend->conn)) { + for (xcb_generic_event_t *e = xcb_wait_for_event(backend->conn); + e != NULL; + e = xcb_poll_for_event(backend->conn)) + { switch (XCB_EVENT_RESPONSE_TYPE(e)) { case 0: LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)e)); @@ -316,12 +369,9 @@ loop(struct bar *_bar, void (*expose)(const struct bar *bar), const xcb_button_release_event_t *evt = (void *)e; switch (evt->detail) { - case 1: - case 2: - case 3: - case 4: - case 5: - on_mouse(_bar, ON_MOUSE_CLICK, evt->detail, evt->event_x, evt->event_y); + case 1: case 2: case 3: case 4: case 5: + on_mouse(_bar, ON_MOUSE_CLICK, + evt->detail, evt->event_x, evt->event_y); break; } break; @@ -355,9 +405,10 @@ commit(const struct bar *_bar) const struct private *bar = _bar->private; const struct xcb_backend *backend = bar->backend.data; - xcb_put_image(backend->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, backend->win, backend->gc, bar->width, - bar->height_with_border, 0, 0, 0, backend->depth, backend->client_pixmap_size, - backend->client_pixmap); + xcb_put_image( + backend->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, backend->win, backend->gc, + bar->width, bar->height_with_border, 0, 0, 0, + backend->depth, backend->client_pixmap_size, backend->client_pixmap); xcb_flush(backend->conn); } @@ -369,19 +420,23 @@ 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); - *evt = (xcb_expose_event_t){.response_type = XCB_EXPOSE, - .window = backend->win, - .x = 0, - .y = 0, - .width = bar->width, - .height = bar->height, - .count = 1}; + *evt = (xcb_expose_event_t){ + .response_type = XCB_EXPOSE, + .window = backend->win, + .x = 0, + .y = 0, + .width = bar->width, + .height = bar->height, + .count = 1 + }; - xcb_send_event(backend->conn, false, backend->win, XCB_EVENT_MASK_EXPOSURE, (char *)evt); + xcb_send_event( + backend->conn, false, backend->win, XCB_EVENT_MASK_EXPOSURE, + (char *)evt); xcb_flush(backend->conn); free(evt); @@ -403,7 +458,8 @@ set_cursor(struct bar *_bar, const char *cursor) xcb_free_cursor(backend->conn, backend->cursor); backend->cursor = xcb_cursor_load_cursor(backend->cursor_ctx, cursor); - xcb_change_window_attributes(backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor); + xcb_change_window_attributes( + backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor); } static const char * diff --git a/char32.c b/char32.c index eb3abb4..0ca029a 100644 --- a/char32.c +++ b/char32.c @@ -1,15 +1,15 @@ #include "char32.h" -#include #include #include +#include #include #if defined __has_include -#if __has_include() -#include -#endif + #if __has_include () + #include + #endif #endif #define LOG_MODULE "char32" @@ -24,13 +24,14 @@ * - both use the same encoding (though we require that encoding to be UTF-32) */ -_Static_assert(sizeof(wchar_t) == sizeof(char32_t), "wchar_t vs. char32_t size mismatch"); +_Static_assert( + sizeof(wchar_t) == sizeof(char32_t), "wchar_t vs. char32_t size mismatch"); #if !defined(__STDC_UTF_32__) || !__STDC_UTF_32__ -#error "char32_t does not use UTF-32" + #error "char32_t does not use UTF-32" #endif #if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__) -#error "wchar_t does not use UTF-32" + #error "wchar_t does not use UTF-32" #endif size_t diff --git a/char32.h b/char32.h index 1e7a9de..b01a7d3 100644 --- a/char32.h +++ b/char32.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include size_t c32len(const char32_t *s); char32_t *ambstoc32(const char *src); diff --git a/completions/zsh/_yambar b/completions/zsh/_yambar index 90b1117..65b3100 100644 --- a/completions/zsh/_yambar +++ b/completions/zsh/_yambar @@ -8,6 +8,6 @@ _arguments \ '(-c --config)'{-c,--config}'[alternative configuration file]:filename:_files' \ '(-C --validate)'{-C,--validate}'[verify configuration then quit]' \ '(-p --print-pid)'{-p,--print-pid}'[print PID to this file or FD when up and running]:pidfile:_files' \ - '(-d --log-level)'{-d,--log-level}'[log level (warning)]:loglevel:(info warning error none)' \ + '(-d --log-level)'{-d,--log-level}'[log level (info)]:loglevel:(info warning error none)' \ '(-l --log-colorize)'{-l,--log-colorize}'[enable or disable colorization of log output on stderr]:logcolor:(never always auto)' \ '(-s --log-no-syslog)'{-s,--log-no-syslog}'[disable syslog logging]' diff --git a/config-verify.c b/config-verify.c index ed7d2f5..a099ef7 100644 --- a/config-verify.c +++ b/config-verify.c @@ -1,7 +1,7 @@ #include "config.h" -#include #include +#include #include @@ -16,9 +16,11 @@ conf_err_prefix(const keychain_t *chain, const struct yml_node *node) static char msg[4096]; int idx = 0; - idx += snprintf(&msg[idx], sizeof(msg) - idx, "%zu:%zu: ", yml_source_line(node), yml_source_column(node)); + idx += snprintf(&msg[idx], sizeof(msg) - idx, "%zu:%zu: ", + yml_source_line(node), yml_source_column(node)); - tll_foreach(*chain, key) idx += snprintf(&msg[idx], sizeof(msg) - idx, "%s.", key->item); + tll_foreach(*chain, key) + idx += snprintf(&msg[idx], sizeof(msg) - idx, "%s.", key->item); /* Remove trailing "." */ msg[idx - 1] = '\0'; @@ -43,7 +45,8 @@ conf_verify_int(keychain_t *chain, const struct yml_node *node) if (yml_value_is_int(node)) return true; - LOG_ERR("%s: value is not an integer: '%s'", conf_err_prefix(chain, node), yml_value_as_string(node)); + LOG_ERR("%s: value is not an integer: '%s'", + conf_err_prefix(chain, node), yml_value_as_string(node)); return false; } @@ -53,7 +56,8 @@ conf_verify_unsigned(keychain_t *chain, const struct yml_node *node) if (yml_value_is_int(node) && yml_value_as_int(node) >= 0) return true; - LOG_ERR("%s: value is not a positive integer: '%s'", conf_err_prefix(chain, node), yml_value_as_string(node)); + LOG_ERR("%s: value is not a positive integer: '%s'", + conf_err_prefix(chain, node), yml_value_as_string(node)); return false; } @@ -63,7 +67,8 @@ conf_verify_bool(keychain_t *chain, const struct yml_node *node) if (yml_value_is_bool(node)) return true; - LOG_ERR("%s: value is not a boolean: '%s'", conf_err_prefix(chain, node), yml_value_as_string(node)); + LOG_ERR("%s: value is not a boolean: '%s'", + conf_err_prefix(chain, node), yml_value_as_string(node)); return false; } @@ -76,7 +81,10 @@ conf_verify_list(keychain_t *chain, const struct yml_node *node, return false; } - for (struct yml_list_iter iter = yml_list_iter(node); iter.node != NULL; yml_list_next(&iter)) { + for (struct yml_list_iter iter = yml_list_iter(node); + iter.node != NULL; + yml_list_next(&iter)) + { if (!verify(chain, iter.node)) return false; } @@ -85,7 +93,8 @@ conf_verify_list(keychain_t *chain, const struct yml_node *node, } bool -conf_verify_enum(keychain_t *chain, const struct yml_node *node, const char *values[], size_t count) +conf_verify_enum(keychain_t *chain, const struct yml_node *node, + const char *values[], size_t count) { const char *s = yml_value_as_string(node); if (s == NULL) { @@ -106,7 +115,8 @@ conf_verify_enum(keychain_t *chain, const struct yml_node *node, const char *val } bool -conf_verify_dict(keychain_t *chain, const struct yml_node *node, const struct attr_info info[]) +conf_verify_dict(keychain_t *chain, const struct yml_node *node, + const struct attr_info info[]) { if (!yml_is_dict(node)) { LOG_ERR("%s: must be a dictionary", conf_err_prefix(chain, node)); @@ -121,7 +131,10 @@ conf_verify_dict(keychain_t *chain, const struct yml_node *node, const struct at bool exists[count]; memset(exists, 0, sizeof(exists)); - for (struct yml_dict_iter it = yml_dict_iter(node); it.key != NULL; yml_dict_next(&it)) { + for (struct yml_dict_iter it = yml_dict_iter(node); + it.key != NULL; + yml_dict_next(&it)) + { const char *key = yml_value_as_string(it.key); if (key == NULL) { LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key)); @@ -161,43 +174,23 @@ conf_verify_dict(keychain_t *chain, const struct yml_node *node, const struct at return true; } -static bool -verify_on_click_path(keychain_t *chain, const struct yml_node *node) -{ - if (!conf_verify_string(chain, node)) - return false; - -#if 1 - /* We allow non-absolute paths in on-click handlers */ - return true; -#else - const char *path = yml_value_as_string(node); - - const bool is_absolute = path[0] == '/'; - const bool is_tilde = path[0] == '~' && path[1] == '/'; - - if (!is_absolute && !is_tilde) { - LOG_ERR("%s: path must be either absolute, or begin with '~/", conf_err_prefix(chain, node)); - return false; - } - - return true; -#endif -} - bool conf_verify_on_click(keychain_t *chain, const struct yml_node *node) { /* on-click: */ const char *s = yml_value_as_string(node); if (s != NULL) - return verify_on_click_path(chain, node); + return true; static const struct attr_info info[] = { - {"left", false, &verify_on_click_path}, {"middle", false, &verify_on_click_path}, - {"right", false, &verify_on_click_path}, {"wheel-up", false, &verify_on_click_path}, - {"wheel-down", false, &verify_on_click_path}, {"previous", false, &verify_on_click_path}, - {"next", false, &verify_on_click_path}, {NULL, false, NULL}, + {"left", false, &conf_verify_string}, + {"middle", false, &conf_verify_string}, + {"right", false, &conf_verify_string}, + {"wheel-up", false, &conf_verify_string}, + {"wheel-down", false, &conf_verify_string}, + {"previous", false, &conf_verify_string}, + {"next", false, &conf_verify_string}, + {NULL, false, NULL}, }; return conf_verify_dict(chain, node, info); @@ -216,18 +209,21 @@ conf_verify_color(keychain_t *chain, const struct yml_node *node) int v = sscanf(s, "%02x%02x%02x%02x", &r, &g, &b, &a); if (strlen(s) != 8 || v != 4) { - LOG_ERR("%s: value must be a color ('rrggbbaa', e.g ff00ffff)", conf_err_prefix(chain, node)); + LOG_ERR("%s: value must be a color ('rrggbbaa', e.g ff00ffff)", + conf_err_prefix(chain, node)); return false; } return true; } + bool conf_verify_font(keychain_t *chain, const struct yml_node *node) { if (!yml_is_scalar(node)) { - LOG_ERR("%s: font must be a fontconfig-formatted string", conf_err_prefix(chain, node)); + LOG_ERR("%s: font must be a fontconfig-formatted string", + conf_err_prefix(chain, node)); return false; } @@ -237,7 +233,8 @@ conf_verify_font(keychain_t *chain, const struct yml_node *node) bool conf_verify_font_shaping(keychain_t *chain, const struct yml_node *node) { - return conf_verify_enum(chain, node, (const char *[]){"full", /*"graphemes",*/ "none"}, 2); + return conf_verify_enum( + chain, node, (const char *[]){"full", /*"graphemes",*/ "none"}, 2); } bool @@ -247,8 +244,7 @@ conf_verify_decoration(keychain_t *chain, const struct yml_node *node) if (yml_dict_length(node) != 1) { LOG_ERR("%s: decoration must be a dictionary with a single key; " - "the name of the particle", - conf_err_prefix(chain, node)); + "the name of the particle", conf_err_prefix(chain, node)); return false; } @@ -264,7 +260,8 @@ conf_verify_decoration(keychain_t *chain, const struct yml_node *node) const struct deco_iface *iface = plugin_load_deco(deco_name); if (iface == NULL) { - LOG_ERR("%s: invalid decoration name: %s", conf_err_prefix(chain, deco), deco_name); + LOG_ERR("%s: invalid decoration name: %s", + conf_err_prefix(chain, deco), deco_name); return false; } @@ -281,7 +278,10 @@ conf_verify_particle_list_items(keychain_t *chain, const struct yml_node *node) { assert(yml_is_list(node)); - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it)) + { if (!conf_verify_particle(chain, it.node)) return false; } @@ -296,8 +296,7 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node) if (yml_dict_length(node) != 1) { LOG_ERR("%s: particle must be a dictionary with a single key; " - "the name of the particle", - conf_err_prefix(chain, node)); + "the name of the particle", conf_err_prefix(chain, node)); return false; } @@ -313,7 +312,8 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node) const struct particle_iface *iface = plugin_load_particle(particle_name); if (iface == NULL) { - LOG_ERR("%s: invalid particle name: %s", conf_err_prefix(chain, particle), particle_name); + LOG_ERR("%s: invalid particle name: %s", + conf_err_prefix(chain, particle), particle_name); return false; } @@ -335,18 +335,19 @@ conf_verify_particle(keychain_t *chain, const struct yml_node *node) else if (yml_is_list(node)) return conf_verify_particle_list_items(chain, node); else { - LOG_ERR("%s: particle must be either a dictionary or a list", conf_err_prefix(chain, node)); + LOG_ERR("%s: particle must be either a dictionary or a list", + conf_err_prefix(chain, node)); return false; } } + static bool verify_module(keychain_t *chain, const struct yml_node *node) { if (!yml_is_dict(node) || yml_dict_length(node) != 1) { LOG_ERR("%s: module must be a dictionary with a single key; " - "the name of the module", - conf_err_prefix(chain, node)); + "the name of the module", conf_err_prefix(chain, node)); return false; } @@ -362,7 +363,8 @@ verify_module(keychain_t *chain, const struct yml_node *node) const struct module_iface *iface = plugin_load_module(mod_name); if (iface == NULL) { - LOG_ERR("%s: invalid module name: %s", conf_err_prefix(chain, node), mod_name); + LOG_ERR( + "%s: invalid module name: %s", conf_err_prefix(chain, node), mod_name); return false; } @@ -384,7 +386,10 @@ verify_module_list(keychain_t *chain, const struct yml_node *node) return false; } - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it)) + { if (!verify_module(chain, it.node)) return false; } @@ -396,12 +401,18 @@ static bool verify_bar_border(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { - {"width", false, &conf_verify_unsigned}, {"left-width", false, &conf_verify_unsigned}, - {"right-width", false, &conf_verify_unsigned}, {"top-width", false, &conf_verify_unsigned}, - {"bottom-width", false, &conf_verify_unsigned}, {"color", false, &conf_verify_color}, - {"margin", false, &conf_verify_unsigned}, {"left-margin", false, &conf_verify_unsigned}, - {"right-margin", false, &conf_verify_unsigned}, {"top-margin", false, &conf_verify_unsigned}, - {"bottom-margin", false, &conf_verify_unsigned}, {NULL, false, NULL}, + {"width", false, &conf_verify_unsigned}, + {"left-width", false, &conf_verify_unsigned}, + {"right-width", false, &conf_verify_unsigned}, + {"top-width", false, &conf_verify_unsigned}, + {"bottom-width", false, &conf_verify_unsigned}, + {"color", false, &conf_verify_color}, + {"margin", false, &conf_verify_unsigned}, + {"left-margin", false, &conf_verify_unsigned}, + {"right-margin", false, &conf_verify_unsigned}, + {"top-margin", false, &conf_verify_unsigned}, + {"bottom-margin", false, &conf_verify_unsigned}, + {NULL, false, NULL}, }; return conf_verify_dict(chain, node, attrs); @@ -416,7 +427,7 @@ verify_bar_location(keychain_t *chain, const struct yml_node *node) static bool verify_bar_layer(keychain_t *chain, const struct yml_node *node) { - return conf_verify_enum(chain, node, (const char *[]){"overlay", "top", "bottom", "background"}, 4); + return conf_verify_enum(chain, node, (const char *[]){"top", "bottom"}, 2); } bool diff --git a/config-verify.h b/config-verify.h index 8ad44ce..0a4ae34 100644 --- a/config-verify.h +++ b/config-verify.h @@ -26,14 +26,17 @@ chain_pop(keychain_t *chain) tll_pop_back(*chain); } -const char *conf_err_prefix(const keychain_t *chain, const struct yml_node *node); +const char *conf_err_prefix( + const keychain_t *chain, const struct yml_node *node); + bool conf_verify_string(keychain_t *chain, const struct yml_node *node); bool conf_verify_int(keychain_t *chain, const struct yml_node *node); bool conf_verify_unsigned(keychain_t *chain, const struct yml_node *node); bool conf_verify_bool(keychain_t *chain, const struct yml_node *node); -bool conf_verify_enum(keychain_t *chain, const struct yml_node *node, const char *values[], size_t count); +bool conf_verify_enum(keychain_t *chain, const struct yml_node *node, + const char *values[], size_t count); bool conf_verify_list(keychain_t *chain, const struct yml_node *node, bool (*verify)(keychain_t *chain, const struct yml_node *node)); bool conf_verify_dict(keychain_t *chain, const struct yml_node *node, diff --git a/config.c b/config.c index 0f80364..3d32678 100644 --- a/config.c +++ b/config.c @@ -1,10 +1,10 @@ #include "config.h" +#include +#include +#include #include #include -#include -#include -#include #include @@ -21,7 +21,9 @@ static uint8_t hex_nibble(char hex) { - assert((hex >= '0' && hex <= '9') || (hex >= 'a' && hex <= 'f') || (hex >= 'A' && hex <= 'F')); + assert((hex >= '0' && hex <= '9') || + (hex >= 'a' && hex <= 'f') || + (hex >= 'A' && hex <= 'F')); if (hex >= '0' && hex <= '9') return hex - '0'; @@ -55,9 +57,9 @@ conf_to_color(const struct yml_node *node) alpha |= alpha << 8; return (pixman_color_t){ - .red = (uint32_t)(red << 8 | red) * alpha / 0xffff, + .red = (uint32_t)(red << 8 | red) * alpha / 0xffff, .green = (uint32_t)(green << 8 | green) * alpha / 0xffff, - .blue = (uint32_t)(blue << 8 | blue) * alpha / 0xffff, + .blue = (uint32_t)(blue << 8 | blue) * alpha / 0xffff, .alpha = alpha, }; } @@ -72,7 +74,10 @@ conf_to_font(const struct yml_node *node) const char **fonts = NULL; char *copy = strdup(font_spec); - for (const char *font = strtok(copy, ","); font != NULL; font = strtok(NULL, ",")) { + for (const char *font = strtok(copy, ","); + font != NULL; + font = strtok(NULL, ",")) + { /* Trim spaces, strictly speaking not necessary, but looks nice :) */ while (isspace(font[0])) font++; @@ -107,7 +112,9 @@ conf_to_font_shaping(const struct yml_node *node) else if (strcmp(v, "graphemes") == 0) { static bool have_warned = false; - if (!have_warned && !(fcft_capabilities() & FCFT_CAPABILITY_GRAPHEME_SHAPING)) { + if (!have_warned && + !(fcft_capabilities() & FCFT_CAPABILITY_GRAPHEME_SHAPING)) + { have_warned = true; LOG_WARN("cannot enable grapheme shaping; no support in fcft"); } @@ -117,7 +124,9 @@ conf_to_font_shaping(const struct yml_node *node) else if (strcmp(v, "full") == 0) { static bool have_warned = false; - if (!have_warned && !(fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING)) { + if (!have_warned && + !(fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING)) + { have_warned = true; LOG_WARN("cannot enable full text shaping; no support in fcft"); } @@ -145,20 +154,25 @@ conf_to_deco(const struct yml_node *node) } static struct particle * -particle_simple_list_from_config(const struct yml_node *node, struct conf_inherit inherited) +particle_simple_list_from_config(const struct yml_node *node, + struct conf_inherit inherited) { size_t count = yml_list_length(node); struct particle *parts[count]; size_t idx = 0; - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it), idx++) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it), idx++) + { parts[idx] = conf_to_particle(it.node, inherited); } /* Lazy-loaded function pointer to particle_list_new() */ - static struct particle *(*particle_list_new)(struct particle *common, struct particle *particles[], size_t count, - int left_spacing, int right_spacing) - = NULL; + static struct particle *(*particle_list_new)( + struct particle *common, + struct particle *particles[], size_t count, + int left_spacing, int right_spacing) = NULL; if (particle_list_new == NULL) { const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE); @@ -167,8 +181,9 @@ particle_simple_list_from_config(const struct yml_node *node, struct conf_inheri assert(particle_list_new != NULL); } - struct particle *common = particle_common_new(0, 0, NULL, fcft_clone(inherited.font), inherited.font_shaping, - inherited.foreground, NULL); + struct particle *common = particle_common_new( + 0, 0, NULL, fcft_clone(inherited.font), inherited.font_shaping, + inherited.foreground, NULL); return particle_list_new(common, parts, count, 0, 2); } @@ -191,49 +206,25 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *foreground_node = yml_get_value(pair.value, "foreground"); const struct yml_node *deco_node = yml_get_value(pair.value, "deco"); - int left = margin != NULL ? yml_value_as_int(margin) : left_margin != NULL ? yml_value_as_int(left_margin) : 0; - int right = margin != NULL ? yml_value_as_int(margin) : right_margin != NULL ? yml_value_as_int(right_margin) : 0; + int left = margin != NULL ? yml_value_as_int(margin) : + left_margin != NULL ? yml_value_as_int(left_margin) : 0; + int right = margin != NULL ? yml_value_as_int(margin) : + right_margin != NULL ? yml_value_as_int(right_margin) : 0; - char *on_click_templates[MOUSE_BTN_COUNT] = {NULL}; + const char *on_click_templates[MOUSE_BTN_COUNT] = {NULL}; if (on_click != NULL) { - const char *yml_legacy = yml_value_as_string(on_click); - - if (yml_legacy != NULL) { - char *legacy = NULL; - - if (yml_legacy[0] == '~' && yml_legacy[1] == '/') { - const char *home_dir = getenv("HOME"); - - if (home_dir != NULL) - if (asprintf(&legacy, "%s/%s", home_dir, yml_legacy + 2) < 0) - legacy = NULL; - - if (legacy == NULL) - legacy = strdup(yml_legacy); - } else - legacy = strdup(yml_legacy); + const char *legacy = yml_value_as_string(on_click); + if (legacy != NULL) on_click_templates[MOUSE_BTN_LEFT] = legacy; - } - else if (yml_is_dict(on_click)) { - for (struct yml_dict_iter it = yml_dict_iter(on_click); it.key != NULL; yml_dict_next(&it)) { + if (yml_is_dict(on_click)) { + for (struct yml_dict_iter it = yml_dict_iter(on_click); + it.key != NULL; + yml_dict_next(&it)) + { const char *key = yml_value_as_string(it.key); - const char *yml_template = yml_value_as_string(it.value); - - char *template = NULL; - - if (yml_template[0] == '~' && yml_template[1] == '/') { - const char *home_dir = getenv("HOME"); - - if (home_dir != NULL) - if (asprintf(&template, "%s/%s", home_dir, yml_template + 2) < 0) - template = NULL; - - if (template == NULL) - template = strdup(yml_template); - } else - template = strdup(yml_template); + const char *template = yml_value_as_string(it.value); if (strcmp(key, "left") == 0) on_click_templates[MOUSE_BTN_LEFT] = template; @@ -266,14 +257,16 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited) * clone the font, since each particle takes ownership of its own * font. */ - struct fcft_font *font = font_node != NULL ? conf_to_font(font_node) : fcft_clone(inherited.font); - enum font_shaping font_shaping - = font_shaping_node != NULL ? conf_to_font_shaping(font_shaping_node) : inherited.font_shaping; - pixman_color_t foreground = foreground_node != NULL ? conf_to_color(foreground_node) : inherited.foreground; + struct fcft_font *font = font_node != NULL + ? conf_to_font(font_node) : fcft_clone(inherited.font); + enum font_shaping font_shaping = font_shaping_node != NULL + ? conf_to_font_shaping(font_shaping_node) : inherited.font_shaping; + pixman_color_t foreground = foreground_node != NULL + ? conf_to_color(foreground_node) : inherited.foreground; /* Instantiate base/common particle */ - struct particle *common - = particle_common_new(left, right, on_click_templates, font, font_shaping, foreground, deco); + struct particle *common = particle_common_new( + left, right, on_click_templates, font, font_shaping, foreground, deco); const struct particle_iface *iface = plugin_load_particle(type); @@ -301,7 +294,8 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) conf.height = yml_value_as_int(height); const struct yml_node *location = yml_get_value(bar, "location"); - conf.location = strcmp(yml_value_as_string(location), "top") == 0 ? BAR_TOP : BAR_BOTTOM; + conf.location = strcmp(yml_value_as_string(location), "top") == 0 + ? BAR_TOP : BAR_BOTTOM; const struct yml_node *background = yml_get_value(bar, "background"); conf.background = conf_to_color(background); @@ -317,18 +311,15 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) const struct yml_node *layer = yml_get_value(bar, "layer"); if (layer != NULL) { const char *tmp = yml_value_as_string(layer); - if (strcmp(tmp, "overlay") == 0) - conf.layer = BAR_LAYER_OVERLAY; - else if (strcmp(tmp, "top") == 0) + if (strcmp(tmp, "top") == 0) conf.layer = BAR_LAYER_TOP; else if (strcmp(tmp, "bottom") == 0) conf.layer = BAR_LAYER_BOTTOM; - else if (strcmp(tmp, "background") == 0) - conf.layer = BAR_LAYER_BACKGROUND; else assert(false); } + const struct yml_node *spacing = yml_get_value(bar, "spacing"); if (spacing != NULL) conf.left_spacing = conf.right_spacing = yml_value_as_int(spacing); @@ -353,8 +344,11 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) if (right_margin != NULL) conf.right_margin = yml_value_as_int(right_margin); - const struct yml_node *trackpad_sensitivity = yml_get_value(bar, "trackpad-sensitivity"); - conf.trackpad_sensitivity = trackpad_sensitivity != NULL ? yml_value_as_int(trackpad_sensitivity) : 30; + const struct yml_node *trackpad_sensitivity = + yml_get_value(bar, "trackpad-sensitivity"); + conf.trackpad_sensitivity = trackpad_sensitivity != NULL + ? yml_value_as_int(trackpad_sensitivity) + : 30; const struct yml_node *border = yml_get_value(bar, "border"); if (border != NULL) { @@ -371,8 +365,10 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) const struct yml_node *bottom_margin = yml_get_value(border, "bottom-margin"); if (width != NULL) - conf.border.left_width = conf.border.right_width = conf.border.top_width = conf.border.bottom_width - = yml_value_as_int(width); + conf.border.left_width = + conf.border.right_width = + conf.border.top_width = + conf.border.bottom_width = yml_value_as_int(width); if (left_width != NULL) conf.border.left_width = yml_value_as_int(left_width); @@ -387,8 +383,10 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) conf.border.color = conf_to_color(color); if (margin != NULL) - conf.border.left_margin = conf.border.right_margin = conf.border.top_margin = conf.border.bottom_margin - = yml_value_as_int(margin); + conf.border.left_margin = + conf.border.right_margin = + conf.border.top_margin = + conf.border.bottom_margin = yml_value_as_int(margin); if (left_margin != NULL) conf.border.left_margin = yml_value_as_int(left_margin); @@ -443,7 +441,10 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) struct module **mods = calloc(count, sizeof(*mods)); size_t idx = 0; - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it), idx++) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it), idx++) + { struct yml_dict_iter m = yml_dict_iter(it.node); const char *mod_name = yml_value_as_string(m.key); @@ -455,13 +456,16 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend) */ const struct yml_node *mod_font = yml_get_value(m.value, "font"); const struct yml_node *mod_font_shaping = yml_get_value(m.value, "font-shaping"); - const struct yml_node *mod_foreground = yml_get_value(m.value, "foreground"); + const struct yml_node *mod_foreground = yml_get_value( + m.value, "foreground"); struct conf_inherit mod_inherit = { - .font = mod_font != NULL ? conf_to_font(mod_font) : inherited.font, - .font_shaping - = mod_font_shaping != NULL ? conf_to_font_shaping(mod_font_shaping) : inherited.font_shaping, - .foreground = mod_foreground != NULL ? conf_to_color(mod_foreground) : inherited.foreground, + .font = mod_font != NULL + ? conf_to_font(mod_font) : inherited.font, + .font_shaping = mod_font_shaping != NULL + ? conf_to_font_shaping(mod_font_shaping) : inherited.font_shaping, + .foreground = mod_foreground != NULL + ? conf_to_color(mod_foreground) : inherited.foreground, }; const struct module_iface *iface = plugin_load_module(mod_name); diff --git a/config.h b/config.h index 86c2f4e..ceb4b85 100644 --- a/config.h +++ b/config.h @@ -1,9 +1,9 @@ #pragma once +#include +#include "yml.h" #include "bar/bar.h" #include "font-shaping.h" -#include "yml.h" -#include struct bar; struct particle; @@ -25,5 +25,6 @@ struct conf_inherit { pixman_color_t foreground; }; -struct particle *conf_to_particle(const struct yml_node *node, struct conf_inherit inherited); +struct particle *conf_to_particle( + const struct yml_node *node, struct conf_inherit inherited); struct deco *conf_to_deco(const struct yml_node *node); diff --git a/decoration.h b/decoration.h index ba44e43..efb79e2 100644 --- a/decoration.h +++ b/decoration.h @@ -4,11 +4,10 @@ struct deco { void *private; - void (*expose)(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height); + void (*expose)(const struct deco *deco, pixman_image_t *pix, + int x, int y, int width, int height); void (*destroy)(struct deco *deco); }; -#define DECORATION_COMMON_ATTRS \ - { \ - NULL, false, NULL \ - } +#define DECORATION_COMMON_ATTRS \ + {NULL, false, NULL} diff --git a/decorations/background.c b/decorations/background.c index f1430f1..b3b9ed2 100644 --- a/decorations/background.c +++ b/decorations/background.c @@ -1,13 +1,12 @@ #include -#include "../config-verify.h" #include "../config.h" +#include "../config-verify.h" #include "../decoration.h" #include "../plugin.h" -struct private -{ - // struct rgba color; +struct private { + //struct rgba color; pixman_color_t color; }; @@ -23,7 +22,9 @@ static void expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) { const struct private *d = deco->private; - pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 1, &(pixman_rectangle16_t){x, y, width, height}); + pixman_image_fill_rectangles( + PIXMAN_OP_OVER, pix, &d->color, 1, + &(pixman_rectangle16_t){x, y, width, height}); } static struct deco * diff --git a/decorations/border.c b/decorations/border.c index e93fc4e..5868e88 100644 --- a/decorations/border.c +++ b/decorations/border.c @@ -1,7 +1,7 @@ #include -#include "../config-verify.h" #include "../config.h" +#include "../config-verify.h" #include "../decoration.h" #include "../plugin.h" @@ -12,8 +12,7 @@ #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) -struct private -{ +struct private { pixman_color_t color; int size; }; @@ -30,20 +29,21 @@ static void expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) { const struct private *d = deco->private; - pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 4, - (pixman_rectangle16_t[]){ - /* Top */ - {x, y, width, min(d->size, height)}, + pixman_image_fill_rectangles( + PIXMAN_OP_OVER, pix, &d->color, 4, + (pixman_rectangle16_t []){ + /* Top */ + {x, y, width, min(d->size, height)}, - /* Bottom */ - {x, max(y + height - d->size, y), width, min(d->size, height)}, + /* Bottom */ + {x, max(y + height - d->size, y), width, min(d->size, height)}, - /* Left */ - {x, y, min(d->size, width), height}, + /* Left */ + {x, y, min(d->size, width), height}, - /* Right */ - {max(x + width - d->size, x), y, min(d->size, width), height}, - }); + /* Right */ + {max(x + width - d->size, x), y, min(d->size, width), height}, + }); } static struct deco * @@ -66,7 +66,9 @@ from_conf(const struct yml_node *node) { const struct yml_node *color = yml_get_value(node, "color"); const struct yml_node *size = yml_get_value(node, "size"); - return border_new(conf_to_color(color), size != NULL ? yml_value_as_int(size) : 1); + return border_new( + conf_to_color(color), + size != NULL ? yml_value_as_int(size) : 1); } static bool diff --git a/decorations/overline.c b/decorations/overline.c index e9ff8be..1beb896 100644 --- a/decorations/overline.c +++ b/decorations/overline.c @@ -1,12 +1,11 @@ #include -#include "../config-verify.h" #include "../config.h" +#include "../config-verify.h" #include "../decoration.h" #include "../plugin.h" -struct private -{ +struct private { int size; pixman_color_t color; }; @@ -23,7 +22,9 @@ static void expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) { const struct private *d = deco->private; - pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 1, &(pixman_rectangle16_t){x, y, width, d->size}); + pixman_image_fill_rectangles( + PIXMAN_OP_OVER, pix, &d->color, 1, + &(pixman_rectangle16_t){x, y, width, d->size}); } static struct deco * diff --git a/decorations/stack.c b/decorations/stack.c index d8420d2..16c58ee 100644 --- a/decorations/stack.c +++ b/decorations/stack.c @@ -1,14 +1,13 @@ #include #define LOG_MODULE "stack" -#include "../config-verify.h" -#include "../config.h" -#include "../decoration.h" #include "../log.h" +#include "../config.h" +#include "../config-verify.h" +#include "../decoration.h" #include "../plugin.h" -struct private -{ +struct private { struct deco **decos; size_t count; }; @@ -58,7 +57,10 @@ from_conf(const struct yml_node *node) struct deco *decos[count]; size_t idx = 0; - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it), idx++) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it), idx++) + { decos[idx] = conf_to_deco(it.node); } @@ -73,7 +75,10 @@ verify_conf(keychain_t *chain, const struct yml_node *node) return false; } - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it)) + { if (!conf_verify_decoration(chain, it.node)) return false; } diff --git a/decorations/underline.c b/decorations/underline.c index 0175116..5b8bbd3 100644 --- a/decorations/underline.c +++ b/decorations/underline.c @@ -1,12 +1,11 @@ #include -#include "../config-verify.h" #include "../config.h" +#include "../config-verify.h" #include "../decoration.h" #include "../plugin.h" -struct private -{ +struct private { int size; pixman_color_t color; }; @@ -23,8 +22,9 @@ static void expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) { const struct private *d = deco->private; - pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 1, - &(pixman_rectangle16_t){x, y + height - d->size, width, d->size}); + pixman_image_fill_rectangles( + PIXMAN_OP_OVER, pix, &d->color, 1, + &(pixman_rectangle16_t){x, y + height - d->size, width, d->size}); } static struct deco * diff --git a/doc/meson.build b/doc/meson.build index e801bf1..fa9673d 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -34,12 +34,8 @@ endif if plugin_mpd_enabled plugin_pages += ['yambar-modules-mpd.5.scd'] endif -if plugin_mpris_enabled - plugin_pages += ['yambar-modules-mpris.5.scd'] -endif if plugin_i3_enabled plugin_pages += ['yambar-modules-i3.5.scd'] - plugin_pages += ['yambar-modules-sway.5.scd'] endif if plugin_label_enabled plugin_pages += ['yambar-modules-label.5.scd'] @@ -47,12 +43,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 @@ -78,7 +68,6 @@ endif foreach man_src : ['yambar.1.scd', 'yambar.5.scd', 'yambar-decorations.5.scd', - 'yambar-modules.5.scd', 'yambar-particles.5.scd', 'yambar-tags.5.scd'] + plugin_pages parts = man_src.split('.') diff --git a/doc/yambar-decorations.5.scd b/doc/yambar-decorations.5.scd index 3d7c379..9dd21b8 100644 --- a/doc/yambar-decorations.5.scd +++ b/doc/yambar-decorations.5.scd @@ -137,7 +137,7 @@ content: # STACK -This particle combines multiple decorations. +This particles combines multiple decorations. ## CONFIGURATION diff --git a/doc/yambar-modules-battery.5.scd b/doc/yambar-modules-battery.5.scd index aab2106..101c02b 100644 --- a/doc/yambar-modules-battery.5.scd +++ b/doc/yambar-modules-battery.5.scd @@ -57,20 +57,7 @@ the state *unknown* under other conditions. | poll-interval : int : no -: How often, in milliseconds, to poll for capacity changes - (default=*60000*). Set to `0` to disable polling (*warning*: many - batteries do not support asynchronous reporting). Cannot be less - than 250ms. -| battery-scale -: int -: no -: How much to scale down the battery charge amount. Some batteries - report too high resulting in bad discharge estimates. Default=1. -| smoothing-secs -: int -: no -: How many seconds to perform smoothing over for battery discharge - estimates. Default=100s. +: How often, in seconds, to poll for capacity changes (default=*60*). Set to `0` to disable polling (*warning*: many batteries do not support asynchronous reporting). # EXAMPLES @@ -79,7 +66,7 @@ bar: left: - battery: name: BAT0 - poll-interval: 30000 + poll-interval: 30 content: string: {text: "BAT: {capacity}% {estimate}"} ``` diff --git a/doc/yambar-modules-cpu.5.scd b/doc/yambar-modules-cpu.5.scd index 090ccdd..1b4219e 100644 --- a/doc/yambar-modules-cpu.5.scd +++ b/doc/yambar-modules-cpu.5.scd @@ -28,11 +28,11 @@ total CPU usage. :[ *Type* :[ *Req* :< *Description* -| poll-interval +| interval : int : no -: Refresh interval of the CPU usage stats in milliseconds - (default=500). Cannot be less then 250ms. +: Refresh interval of the CPU usage stats in ms (default=500). Cannot + be less then 500 ms # EXAMPLES @@ -41,7 +41,7 @@ total CPU usage. bar: left: - cpu: - poll-interval: 2500 + interval: 2500 content: map: conditions: @@ -55,7 +55,7 @@ bar: bar: left: - cpu: - poll-interval: 2500 + interval: 2500 content: map: conditions: diff --git a/doc/yambar-modules-disk-io.5.scd b/doc/yambar-modules-disk-io.5.scd index 3f51e79..4def79f 100644 --- a/doc/yambar-modules-disk-io.5.scd +++ b/doc/yambar-modules-disk-io.5.scd @@ -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 @@ -35,11 +35,11 @@ currently present in the machine. :[ *Type* :[ *Req* :< *Description* -| poll-interval +| interval : int : no -: Refresh interval of disk's stats in milliseconds (default=500). - Cannot be less then 250ms. +: Refresh interval of disk's stats in ms (default=500). + Cannot be less then 500 ms # EXAMPLES @@ -50,7 +50,7 @@ formatting in b/s, kb/s, mb/s, or gb/s, as appropriate. bar: left: - disk-io: - poll-interval: 1000 + interval: 1000 content: map: conditions: diff --git a/doc/yambar-modules-dwl.5.scd b/doc/yambar-modules-dwl.5.scd index 1562e56..be34de1 100644 --- a/doc/yambar-modules-dwl.5.scd +++ b/doc/yambar-modules-dwl.5.scd @@ -7,8 +7,8 @@ dwl - This module provides information about dwl tags, and information. This module provides a map of each tags present in dwl. -Each tags has its _id_, its _name_, its status (_selected_, _empty_, _urgent_) -and the global data like _title_, _appid_, _fullscreen_, _floating_, +Each tags has its _id_, its status (_selected_, _empty_, _urgent_) +and the global data like _title_, _fullscreen_, _floating_, _selmon_, and _layout_). The tags start a 1. For needs where you only want information about the global data and not the _tags_, there is a tag with the id _0_ that contains only the global data. @@ -28,10 +28,7 @@ Running multiple instances at the same time may result in :< *Description* | id : int -: dwl tag id. -| name -: string -: The name of the tag (defaults to _id_ if not set). +: Dwl tag id. | selected : bool : True if the tag is currently selected. @@ -44,9 +41,6 @@ Running multiple instances at the same time may result in | title : string : The currently focused window's title. -| appid -: string -: The currently focused window's application id. | fullscreen : bool : True if there is a fullscreen window in the current tag. @@ -70,10 +64,6 @@ Running multiple instances at the same time may result in : int : yes : The number of defined tags in the dwl `config.def.h`. -| name-of-tags -: list -: false -: The name of the tags (must have the same length that _number-of-tags_). | dwl-info-filename : string : yes @@ -87,18 +77,16 @@ bar: - dwl: number-of-tags: 9 dwl-info-filename: "/home/ogromny/dwl_info" - name-of-tags: [ , , , , , , , ,  ] content: list: items: - map: conditions: + selected: {string: {text: "-> {id}"}} + ~empty: {string: {text: "{id}"}} + urgent: {string: {text: "=> {id} <="}} # default tag id == 0: {string: {text: "{layout} {title}"}} - - selected: {string: {text: "-> {name}"}} - ~empty: {string: {text: "{name}"}} - urgent: {string: {text: "=> {name} <="}} ``` # SEE ALSO diff --git a/doc/yambar-modules-i3.5.scd b/doc/yambar-modules-i3.5.scd index 2014a3c..37d54bf 100644 --- a/doc/yambar-modules-i3.5.scd +++ b/doc/yambar-modules-i3.5.scd @@ -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) @@ -70,7 +67,7 @@ with the _application_ and _title_ tags to replace the X11-only | sort : enum : no -: How to sort the list of workspaces; one of _none_, _native_, _ascending_ or _descending_, defaults to _none_. Use _native_ to sort numbered workspaces only. +: How to sort the list of workspaces; one of _none_, _ascending_ or _descending_, defaults to _none_. | strip-workspace-numbers : bool : no diff --git a/doc/yambar-modules-mem.5.scd b/doc/yambar-modules-mem.5.scd index fc0a9eb..82a70c3 100644 --- a/doc/yambar-modules-mem.5.scd +++ b/doc/yambar-modules-mem.5.scd @@ -30,11 +30,10 @@ mem - This module provides the memory usage :[ *Type* :[ *Req* :< *Description* -| poll-interval +| interval : string : no -: Refresh interval of the memory usage stats in milliseconds - (default=500). Cannot be less then 250ms. +: Refresh interval of the memory usage stats in ms (default=500). Cannot be less then 500 ms # EXAMPLES @@ -42,7 +41,7 @@ mem - This module provides the memory usage bar: left: - mem: - poll-interval: 2500 + interval: 2500 content: string: {text: "{used:mb}MB"} ``` diff --git a/doc/yambar-modules-mpd.5.scd b/doc/yambar-modules-mpd.5.scd index d89407a..aff6227 100644 --- a/doc/yambar-modules-mpd.5.scd +++ b/doc/yambar-modules-mpd.5.scd @@ -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 diff --git a/doc/yambar-modules-mpris.5.scd b/doc/yambar-modules-mpris.5.scd deleted file mode 100644 index 510dc8f..0000000 --- a/doc/yambar-modules-mpris.5.scd +++ /dev/null @@ -1,101 +0,0 @@ -yambar-modules-mpris(5) - -# NAME -mpris - This module provides MPRIS status such as currently playing artist/album/song - -# TAGS - -[[ *Name* -:[ *Type* -:< *Description* -| state -: string -: One of *offline*, *stopped*, *paused* or *playing* -| shuffle -: bool -: True if the *shuffle* flag is set -| repeat -: string -: One of *none*, *track* or *paylist* -| volume -: range -: Volume in percentage -| album -: string -: Currently playing album -| artist -: string -: Artist of currently playing song -| title -: string -: Title of currently playing song -| file -: string -: Filename or URL of currently playing song -| pos -: string -: *%M:%S*-formatted string describing the song's current position - (also see _elapsed_) -| end -: string -: *%M:%S*-formatted string describing the song's total length (also - see _duration_) -| elapsed -: realtime -: Position in currently playing song, in milliseconds. Can be used - with a _progress-bar_ particle. - -# CONFIGURATION - -[[ *Name* -:[ *Type* -:[ *Req* -:< *Description* -| identities -: list of string -: yes -: A list of MPRIS client identities -| query_timeout -: int -: no -: Dbus/MPRIS client connection timeout in ms. Try setting/incrementing - this value if the module reports a timeout error. Defaults to 500. - -# EXAMPLES - -``` -bar: - center: - - mpris: - identities: - - "spotify" - - "firefox" - content: - map: - conditions: - state != offline && state != stopped: - - string: {text: "{artist}", max: 30 } - - string: {text: "-" } - - string: {text: "{title}", max: 30 } -``` - -# NOTE - -The 'identity' refers a part of your clients DBus bus name. -You can obtain a list of active client names using: - -``` -Systemd: > busctl --user --list -Playerctl: > playerctl --list-all -Libdbus: > dbus-send --session --print-reply --type=method_call \ - --dest='org.freedesktop.DBus' /org org.freedesktop.DBus.ListNames -``` - -MPRIS client bus names start with 'org.mpris.MediaPlayer2.'. -For example, firefox may use the bus name: -'org.mpris.MediaPlayer2.firefox.instance_1_7' which -gives us the identity 'firefox' - -# SEE ALSO - -*yambar-modules*(5), *yambar-particles*(5), *yambar-tags*(5), *yambar-decorations*(5) diff --git a/doc/yambar-modules-network.5.scd b/doc/yambar-modules-network.5.scd index afbbae3..7bb9afc 100644 --- a/doc/yambar-modules-network.5.scd +++ b/doc/yambar-modules-network.5.scd @@ -6,12 +6,11 @@ network - This module monitors network connection state # DESCRIPTION This module monitors network connection state; disconnected/connected -state and MAC/IP addresses. It instantiates the provided _content_ -particle for each network interface. +state and MAC/IP addresses. Note: while the module internally tracks all assigned IPv4/IPv6 addresses, it currently exposes only a single IPv4 and a single IPv6 -address per network interface. +address. # TAGS @@ -21,16 +20,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 @@ -56,9 +45,6 @@ address per network interface. | signal : int : Signal strength, in dBm (Wi-Fi only) -| quality -: range -: Quality of the signal, in percent (Wi-Fi only) | rx-bitrate : int : RX bitrate, in bits/s @@ -79,45 +65,26 @@ address per network interface. :[ *Type* :[ *Req* :< *Description* -| left-spacing -: int -: no -: Space, in pixels, in the left side of each rendered volume -| right-spacing -: int -: no -: Space, in pixels, on the right side of each rendered volume -| spacing -: int -: no -: Short-hand for setting both _left-spacing_ and _right-spacing_ +| name +: string +: yes +: Name of network interface to monitor | poll-interval : int : no -: Periodically (in milliseconds) update the signal, quality, rx+tx bitrate, and - ul+dl speed tags (default=0). Setting it to 0 disables updates. Cannot be less - than 250ms. +: Periodically (in seconds) update the signal, rx+tx bitrate, and + ul+dl speed tags. # EXAMPLES -Display all Ethernet (including WLAN) devices. This excludes loopback, -bridges etc. - ``` bar: left: - network: + name: wlp3s0 content: - map: - conditions: - type == ether || type == wlan: - map: - default: - string: {text: "{name}: {state} ({ipv4})"} - conditions: - ipv4 == "": - string: {text: "{name}: {state}"} + string: {text: "{name}: {state} ({ipv4})"} ``` # SEE ALSO diff --git a/doc/yambar-modules-niri-language.5.scd b/doc/yambar-modules-niri-language.5.scd deleted file mode 100644 index befa41e..0000000 --- a/doc/yambar-modules-niri-language.5.scd +++ /dev/null @@ -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) - diff --git a/doc/yambar-modules-niri-workspaces.5.scd b/doc/yambar-modules-niri-workspaces.5.scd deleted file mode 100644 index 812bade..0000000 --- a/doc/yambar-modules-niri-workspaces.5.scd +++ /dev/null @@ -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) - diff --git a/doc/yambar-modules-pipewire.5.scd b/doc/yambar-modules-pipewire.5.scd index 8010449..0f7a40b 100644 --- a/doc/yambar-modules-pipewire.5.scd +++ b/doc/yambar-modules-pipewire.5.scd @@ -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 @@ -39,28 +39,8 @@ pipewire - Monitors pipewire for volume, mute/unmute, device change # CONFIGURATION -[[ *Name* -:[ *Type* -:[ *Req* -:< *Description* -| left-spacing -: int -: no -: Space, in pixels, in the left side of each rendered volume -| right-spacing -: int -: no -: Space, in pixels, on the right side of each rendered volume -| spacing -: int -: no -: Short-hand for setting both _left-spacing_ and _right-spacing_ -| content -: particle -: yes -: Unlike other modules, _content_ is a template particle that will be - expanded twice (i.e. into a list of two elements). The first - element is the 'sink', and the second element the 'source'. +No additional attributes supported, only the generic ones (see +*GENERIC CONFIGURATION* in *yambar-modules*(5)) # EXAMPLES diff --git a/doc/yambar-modules-river.5.scd b/doc/yambar-modules-river.5.scd index 3bf3b61..7f2920f 100644 --- a/doc/yambar-modules-river.5.scd +++ b/doc/yambar-modules-river.5.scd @@ -54,16 +54,14 @@ once for all 32 river tags. This means you probably want to use a :< *Description* | seat : string -: The name of the seat. +: The name of the seat (*title* particle only, see CONFIGURATION) | title : string -: The seat's focused view's title. +: The seat's focused view's title (*title* particle only, see CONFIGURATION) | mode : string -: The seat's current mode (entered with e.g. *riverctl enter-mode foobar*). -| layout -: string -: Current layout of the output currently focused by the seat. +: The seat's current mode (entered with e.g. *riverctl enter-mode foobar*) + # CONFIGURATION @@ -92,7 +90,7 @@ once for all 32 river tags. This means you probably want to use a bar: left: - river: - title: {string: { text: "{seat} - {title} ({layout}/{mode})" }} + title: {string: { text: "{seat} - {title} ({mode})" }} content: map: conditions: diff --git a/doc/yambar-modules-script.5.scd b/doc/yambar-modules-script.5.scd index 48722cf..17ac34e 100644 --- a/doc/yambar-modules-script.5.scd +++ b/doc/yambar-modules-script.5.scd @@ -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 @@ -70,8 +70,7 @@ User defined. | path : string : yes -: Path to script/binary to execute. Must either be an absolute path, - or start with *~/*. +: Path to script/binary to execute. Must be an absolute path. | args : list of strings : no @@ -79,8 +78,8 @@ User defined. | poll-interval : integer : no -: Number of milliseconds between each script run. If unset, or set to - 0, continuous mode is used. +: Number of seconds between each script run. If unset, continuous mode + is used. # EXAMPLES diff --git a/doc/yambar-modules.5.scd b/doc/yambar-modules.5.scd index 1ec4871..177418f 100644 --- a/doc/yambar-modules.5.scd +++ b/doc/yambar-modules.5.scd @@ -38,7 +38,7 @@ For example, to render _backlight_ as " 20%", you could use: ``` content: - string: - font: Font Awesome 6 Free:style=solid:pixelsize=14 + font: Font Awesome 5 Free:style=solid:pixelsize=14 text:  - string: font: Adobe Helvetica:pixelsize=12 @@ -91,7 +91,7 @@ In these cases, you can define an anchor point, either at top-level, or in a module's _anchors_ attribute: ``` -awesome: &awesome Font Awesome 6 Free:style=solid:pixelsize=14 +awesome: &awesome Font Awesome 5 Free:style=solid:pixelsize=14 ``` @@ -142,26 +142,14 @@ Available modules have their own pages: *yambar-modules-clock*(5) -*yambar-modules-cpu*(5) - -*yambar-modules-disk-io*(5) - -*yambar-modules-dwl*(5) - -*yambar-modules-foreign-toplevel*(5) - *yambar-modules-i3*(5) *yambar-modules-label*(5) -*yambar-modules-mem*(5) - *yambar-modules-mpd*(5) *yambar-modules-network*(5) -*yambar-modules-pipewire*(5) - *yambar-modules-pulse*(5) *yambar-modules-removables*(5) @@ -174,10 +162,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) diff --git a/doc/yambar-particles.5.scd b/doc/yambar-particles.5.scd index 325ef89..adf4485 100644 --- a/doc/yambar-particles.5.scd +++ b/doc/yambar-particles.5.scd @@ -44,11 +44,10 @@ following attributes are supported by all particles: | on-click : associative array/string : no -: When set to a string, executes the string as a command when the - particle is left-clicked. Tags can be used. Note that the string is - *not* executed in a shell. Environment variables are not expanded. - *~/* is expanded, but only in the first argument. The same applies - to all attributes associated with it, below. +: When set to a string, executes the string as a command when the particle + is left-clicked. Tags can be used. Note that the string is *not* + executed in a shell. The same applies to all attributes associated with + it, below. | on-click.left : string : no @@ -155,7 +154,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 +213,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 +259,6 @@ To match for empty strings, use ' "" ': == "" ``` -String glob matching - -To perform string matching using globbing with "\*" & "?" characters: -\* Match any zero or more characters. ? Match exactly any one -character. - -``` - ~~ "hello*" -``` - -Will match any string starting with "hello", including "hello", -"hello1", "hello123", etc. - -``` - ~~ "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 +450,7 @@ itself when needed. ``` content: - progress-bar: + progres-bar: tag: tag_name length: 20 start: {string: {text: ├}} diff --git a/doc/yambar-tags.5.scd b/doc/yambar-tags.5.scd index b6b8b56..488fc77 100644 --- a/doc/yambar-tags.5.scd +++ b/doc/yambar-tags.5.scd @@ -58,77 +58,43 @@ be used. [[ *Formatter* :[ *Kind* -:[ *Applies to* -:< *Description* -| [0][.] -: format -: Numeric tags (integer and floats) -: The width reserved to the field. The leading '0' is optional and - indicates zero padding, as opposed to space padding. The trailing - '.' is also optional +:[ *Description* +:< *Applies to* | . : format -: Float tags : How many decimals to print -| [0][.] -: format -: N: numeric tags, M: float tags -: Combined version of the two previous formatters +: Float tags | hex : format -: All tag types : Renders a tag's value in hex +: All tag types | oct : format -: All tag types : Renders a tag's value in octal +: All tag types | % : 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 +: Range tags | 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) +: All tag types | kib, mib, gib : format -: All tag types : Same as *kb*, *mb* and *gb*, but divide by 1024^n instead of 1000^n. +: All tag types | min : selector -: Range tags : Renders a range tag's minimum value +: Range tags | max : selector -: Range tags : Renders a range tag's maximum value +: Range tags | unit : selector -: Realtime tags : Renders a realtime tag's unit (e.g. "s", or "ms") +: Realtime tags -# EXAMPLES - -- A numeric (float or int) tag with at least 3 digits, zero-padded if - necessary: - -``` -{tag:03} -``` - -- A float tag with 2 decimals: - -``` -{tag:.2} -``` - -- A "byte count" tag in gigabytes: - -``` -{tag:gib}GB -``` diff --git a/doc/yambar.1.scd b/doc/yambar.1.scd index 2aaa46f..a34f13c 100644 --- a/doc/yambar.1.scd +++ b/doc/yambar.1.scd @@ -25,11 +25,11 @@ 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 - syslog. Default: _warning_. + syslog. Default: _info_. *-l*,*--log-colorize*=[{*never*,*always*,*auto*}] Enables or disables colorization of log output on stderr. diff --git a/doc/yambar.5.scd b/doc/yambar.5.scd index 38c521d..d7bf0b8 100644 --- a/doc/yambar.5.scd +++ b/doc/yambar.5.scd @@ -14,8 +14,8 @@ types that are frequently used: - *font*: this is a comma separated list of fonts in _fontconfig_ format. Example of valid values: - - Font Awesome 6 Brands - - Font Awesome 6 Free:style=solid + - Font Awesome 5 Brands + - Font Awesome 5 Free:style=solid - Dina:pixelsize=10:slant=italic - Dina:pixelsize=10:weight=bold - *color*: an rgba hexstring; _RRGGBBAA_. Examples: @@ -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* @@ -54,8 +49,7 @@ types that are frequently used: | layer : string : no -: Layer to put bar on. One of _overlay_, _top_, _bottom_ or - _background_. Wayland only. Default: _bottom_. +: Layer to put bar on. One of _top_ or _bottom_. Wayland only | left-spacing : int : no diff --git a/examples/configurations/laptop.conf b/examples/configurations/laptop.conf index 1bdd16c..96383ca 100644 --- a/examples/configurations/laptop.conf +++ b/examples/configurations/laptop.conf @@ -4,9 +4,9 @@ # For X11/i3, you'll want to replace calls to swaymsg with i3-msg, and # the sway-xkb module with the xkb module. -# fonts we'll be reusing here and there -awesome: &awesome Font Awesome 6 Free:style=solid:pixelsize=14 -awesome_brands: &awesome_brands Font Awesome 6 Brands:pixelsize=16 +# fonts we'll be re-using here and there +awesome: &awesome Font Awesome 5 Free:style=solid:pixelsize=14 +awesome_brands: &awesome_brands Font Awesome 5 Brands:pixelsize=16 std_underline: &std_underline {underline: { size: 2, color: ff0000ff}} @@ -169,40 +169,34 @@ bar: - string: {text: , font: *awesome} - string: {text: "{layout}"} - network: + name: enp1s0 content: map: - default: {empty: {}} conditions: - name == enp1s0: + ~carrier: {empty: {}} + carrier: map: + default: {string: {text: , font: *awesome, foreground: ffffff66}} conditions: - ~carrier: {empty: {}} - carrier: - map: - default: {string: {text: , font: *awesome, foreground: ffffff66}} - conditions: - state == up && ipv4 != "": {string: {text: , font: *awesome}} + state == up && ipv4 != "": {string: {text: , font: *awesome}} - network: - poll-interval: 1000 + name: wlp2s0 + poll-interval: 1 content: map: - default: {empty: {}} + default: {string: {text: , font: *awesome, foreground: ffffff66}} conditions: - name == wlp2s0: + state == down: {string: {text: , font: *awesome, foreground: ff0000ff}} + state == up: map: - default: {string: {text: , font: *awesome, foreground: ffffff66}} - conditions: - state == down: {string: {text: , font: *awesome, foreground: ff0000ff}} - state == up: - map: - default: - - string: {text: , font: *awesome} - - string: {text: "{ssid} {dl-speed:mb}/{ul-speed:mb} Mb/s"} + default: + - string: {text: , font: *awesome} + - string: {text: "{ssid} {dl-speed:mb}/{ul-speed:mb} Mb/s"} - conditions: - ipv4 == "": - - string: {text: , font: *awesome, foreground: ffffff66} - - string: {text: "{ssid} {dl-speed:mb}/{ul-speed:mb} Mb/s", foreground: ffffff66} + conditions: + ipv4 == "": + - string: {text: , font: *awesome, foreground: ffffff66} + - string: {text: "{ssid} {dl-speed:mb}/{ul-speed:mb} Mb/s", foreground: ffffff66} - alsa: card: hw:PCH mixer: Master @@ -227,7 +221,7 @@ bar: content: [ string: {text: , font: *awesome}, string: {text: "{percent}%"}] - battery: name: BAT0 - poll-interval: 30000 + poll-interval: 30 anchors: discharging: &discharging list: diff --git a/examples/configurations/river-tags.conf b/examples/configurations/river-tags.conf index 28bc0b9..54289e6 100644 --- a/examples/configurations/river-tags.conf +++ b/examples/configurations/river-tags.conf @@ -15,20 +15,20 @@ bar: anchors: - base: &river_base left-margin: 10 - right-margin: 13 + right-margin: 13 default: {string: {text: , font: *hack}} conditions: - id == 1: {string: {text: ﳐ, font: *hack}} - id == 2: {string: {text: , font: *hack}} - id == 3: {string: {text: , font: *hack}} - id == 4: {string: {text: , font: *hack}} - id == 5: {string: {text: , font: *hack}} - id == 10: {string: {text: "scratchpad", font: *hack}} - id == 11: {string: {text: "work", font: *hack}} + id == 1: {string: {text: ﳐ, font: *hack}} + id == 2: {string: {text: , font: *hack}} + id == 3: {string: {text: , font: *hack}} + id == 4: {string: {text: , font: *hack}} + id == 5: {string: {text: , font: *hack}} + id == 10: {string: {text: "scratchpad", font: *hack}} + id == 11: {string: {text: "work", font: *hack}} content: map: - on-click: + 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)))" diff --git a/examples/river-minimal.yml b/examples/river-minimal.yml deleted file mode 100644 index 2ca225f..0000000 --- a/examples/river-minimal.yml +++ /dev/null @@ -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}"} diff --git a/examples/scripts/dwl-tags.sh b/examples/scripts/dwl-tags.sh index 4999548..7b70fff 100755 --- a/examples/scripts/dwl-tags.sh +++ b/examples/scripts/dwl-tags.sh @@ -19,7 +19,7 @@ # # Now the fun part # -# Example configuration: +# Exemple configuration: # # - script: # path: /absolute/path/to/dwl-tags.sh @@ -136,3 +136,4 @@ done unset -v output title layout activetags selectedtags unset -v tags name + diff --git a/examples/scripts/pacman.sh b/examples/scripts/pacman.sh index 5026b5a..a04b7a9 100755 --- a/examples/scripts/pacman.sh +++ b/examples/scripts/pacman.sh @@ -12,16 +12,16 @@ # {aur} int number of aur packages # {pkg} int sum of both # -# Examples configuration: +# Exemples configuration: # - script: # path: /absolute/path/to/pacman.sh -# args: [] +# args: [] # content: { string: { text: "{pacman} + {aur} = {pkg}" } } # # To display a message when there is no update: # - script: # path: /absolute/path/to/pacman.sh -# args: [] +# args: [] # content: # map: # default: { string: { text: "{pacman} + {aur} = {pkg}" } } @@ -47,9 +47,9 @@ while true; do # Change interval # NUMBER[SUFFIXE] # Possible suffix: - # "s" seconds / "m" minutes / "h" hours / "d" days + # "s" seconds / "m" minutes / "h" hours / "d" days interval="1h" - + # Change your aur manager aur_helper="paru" @@ -62,7 +62,7 @@ while true; do else aur_num=$("${aur_helper}" -Qmu | wc -l) fi - + pkg_num=$(( pacman_num + aur_num )) printf -- '%s\n' "pacman|int|${pacman_num}" @@ -76,3 +76,4 @@ done unset -v interval aur_helper pacman_num aur_num pkg_num unset -f _err + diff --git a/external/river-status-unstable-v1.xml b/external/river-status-unstable-v1.xml index e9629dd..6a74256 100644 --- a/external/river-status-unstable-v1.xml +++ b/external/river-status-unstable-v1.xml @@ -16,7 +16,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - + A global factory for objects that receive status information specific to river. It could be used to implement, for example, a status bar. @@ -47,7 +47,7 @@ - + This interface allows clients to receive information about the current windowing state of an output. @@ -83,21 +83,6 @@ - - - - Sent once on binding the interface should a layout name exist and again - whenever the name changes. - - - - - - - Sent when the current layout name has been removed without a new one - being set, for example when the active layout generator disconnects. - - diff --git a/log.c b/log.c index ba4ebd9..5864853 100644 --- a/log.c +++ b/log.c @@ -1,6 +1,5 @@ #include "log.h" -#include #include #include #include @@ -10,12 +9,13 @@ #include #include #include +#include #define ALEN(v) (sizeof(v) / sizeof((v)[0])) #define UNUSED __attribute__((unused)) static bool colorize = false; -static bool do_syslog = false; +static bool do_syslog = true; static enum log_class log_level = LOG_CLASS_NONE; static const struct { @@ -32,28 +32,23 @@ static const struct { }; void -log_init(enum log_colorize _colorize, bool _do_syslog, enum log_facility syslog_facility, enum log_class _log_level) +log_init(enum log_colorize _colorize, bool _do_syslog, + enum log_facility syslog_facility, enum log_class _log_level) { static const int facility_map[] = { [LOG_FACILITY_USER] = LOG_USER, [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); + ? false : _colorize == LOG_COLORIZE_ALWAYS + ? true : isatty(STDERR_FILENO); do_syslog = _do_syslog; log_level = _log_level; int slvl = log_level_map[_log_level].syslog_equivalent; if (do_syslog && slvl != -1) { - openlog(NULL, /*LOG_PID*/ 0, facility_map[syslog_facility]); + openlog(NULL, /*LOG_PID*/0, facility_map[syslog_facility]); setlogmask(LOG_UPTO(slvl)); } } @@ -66,8 +61,8 @@ log_deinit(void) } static void -_log(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, int sys_errno, - va_list va) +_log(enum log_class log_class, const char *module, const char *file, int lineno, + const char *fmt, int sys_errno, va_list va) { assert(log_class > LOG_CLASS_NONE); assert(log_class < ALEN(log_level_map)); @@ -97,8 +92,9 @@ _log(enum log_class log_class, const char *module, const char *file, int lineno, } static void -_sys_log(enum log_class log_class, const char *module, const char UNUSED *file, int UNUSED lineno, const char *fmt, - int sys_errno, va_list va) +_sys_log(enum log_class log_class, const char *module, + const char UNUSED *file, int UNUSED lineno, + const char *fmt, int sys_errno, va_list va) { assert(log_class > LOG_CLASS_NONE); assert(log_class < ALEN(log_level_map)); @@ -106,9 +102,6 @@ _sys_log(enum log_class log_class, const char *module, const char UNUSED *file, if (!do_syslog) return; - if (log_class > log_level) - return; - /* Map our log level to syslog's level */ int level = log_level_map[log_class].syslog_equivalent; @@ -123,7 +116,8 @@ _sys_log(enum log_class log_class, const char *module, const char UNUSED *file, } void -log_msg_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, va_list va) +log_msg_va(enum log_class log_class, const char *module, + const char *file, int lineno, const char *fmt, va_list va) { va_list va2; va_copy(va2, va); @@ -133,7 +127,8 @@ log_msg_va(enum log_class log_class, const char *module, const char *file, int l } void -log_msg(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...) +log_msg(enum log_class log_class, const char *module, + const char *file, int lineno, const char *fmt, ...) { va_list va; va_start(va, fmt); @@ -142,13 +137,17 @@ log_msg(enum log_class log_class, const char *module, const char *file, int line } void -log_errno_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, va_list va) +log_errno_va(enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, va_list va) { log_errno_provided_va(log_class, module, file, lineno, errno, fmt, va); } void -log_errno(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...) +log_errno(enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, ...) { va_list va; va_start(va, fmt); @@ -157,7 +156,8 @@ log_errno(enum log_class log_class, const char *module, const char *file, int li } void -log_errno_provided_va(enum log_class log_class, const char *module, const char *file, int lineno, int errno_copy, +log_errno_provided_va(enum log_class log_class, const char *module, + const char *file, int lineno, int errno_copy, const char *fmt, va_list va) { va_list va2; @@ -168,7 +168,8 @@ log_errno_provided_va(enum log_class log_class, const char *module, const char * } void -log_errno_provided(enum log_class log_class, const char *module, const char *file, int lineno, int errno_copy, +log_errno_provided(enum log_class log_class, const char *module, + const char *file, int lineno, int errno_copy, const char *fmt, ...) { va_list va; diff --git a/log.h b/log.h index 48f16fe..94fd178 100644 --- a/log.h +++ b/log.h @@ -1,43 +1,68 @@ #pragma once -#include #include +#include enum log_colorize { LOG_COLORIZE_NEVER, LOG_COLORIZE_ALWAYS, LOG_COLORIZE_AUTO }; enum log_facility { LOG_FACILITY_USER, LOG_FACILITY_DAEMON }; -enum log_class { LOG_CLASS_NONE, LOG_CLASS_ERROR, LOG_CLASS_WARNING, LOG_CLASS_INFO, LOG_CLASS_DEBUG }; +enum log_class { + LOG_CLASS_NONE, + LOG_CLASS_ERROR, + LOG_CLASS_WARNING, + LOG_CLASS_INFO, + LOG_CLASS_DEBUG +}; -void log_init(enum log_colorize colorize, bool do_syslog, enum log_facility syslog_facility, enum log_class log_level); +void log_init(enum log_colorize colorize, bool do_syslog, + enum log_facility syslog_facility, enum log_class log_level); void log_deinit(void); -void log_msg(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...) - __attribute__((format(printf, 5, 6))); +void log_msg( + enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, ...) __attribute__((format (printf, 5, 6))); -void log_errno(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...) - __attribute__((format(printf, 5, 6))); +void log_errno( + enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, ...) __attribute__((format (printf, 5, 6))); -void log_errno_provided(enum log_class log_class, const char *module, const char *file, int lineno, int _errno, - const char *fmt, ...) __attribute__((format(printf, 6, 7))); +void log_errno_provided( + enum log_class log_class, const char *module, + const char *file, int lineno, int _errno, + const char *fmt, ...) __attribute__((format (printf, 6, 7))); + +void log_msg_va( + enum log_class log_class, const char *module, + const char *file, int lineno, const char *fmt, va_list va) __attribute__((format (printf, 5, 0))); +void log_errno_va( + enum log_class log_class, const char *module, + const char *file, int lineno, + const char *fmt, va_list va) __attribute__((format (printf, 5, 0))); +void log_errno_provided_va( + enum log_class log_class, const char *module, + const char *file, int lineno, int _errno, + const char *fmt, va_list va) __attribute__((format (printf, 6, 0))); -void log_msg_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, va_list va) - __attribute__((format(printf, 5, 0))); -void log_errno_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, - va_list va) __attribute__((format(printf, 5, 0))); -void log_errno_provided_va(enum log_class log_class, const char *module, const char *file, int lineno, int _errno, - const char *fmt, va_list va) __attribute__((format(printf, 6, 0))); int log_level_from_string(const char *str); const char *log_level_string_hint(void); -#define LOG_ERR(...) log_msg(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) -#define LOG_ERRNO(...) log_errno(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) -#define LOG_ERRNO_P(_errno, ...) \ - log_errno_provided(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, _errno, __VA_ARGS__) -#define LOG_WARN(...) log_msg(LOG_CLASS_WARNING, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) -#define LOG_INFO(...) log_msg(LOG_CLASS_INFO, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) +#define LOG_ERR(...) \ + log_msg(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) +#define LOG_ERRNO(...) \ + log_errno(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) +#define LOG_ERRNO_P(_errno, ...) \ + log_errno_provided(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, \ + _errno, __VA_ARGS__) +#define LOG_WARN(...) \ + log_msg(LOG_CLASS_WARNING, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) +#define LOG_INFO(...) \ + log_msg(LOG_CLASS_INFO, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG -#define LOG_DBG(...) log_msg(LOG_CLASS_DEBUG, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) + #define LOG_DBG(...) \ + log_msg(LOG_CLASS_DEBUG, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) #else -#define LOG_DBG(...) + #define LOG_DBG(...) #endif diff --git a/main.c b/main.c index c355843..7aab81a 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,4 @@ #include -#include -#include #include #include #include @@ -11,12 +9,14 @@ #include #include #include +#include +#include -#include -#include +#include #include #include -#include +#include +#include #include "bar/bar.h" #include "config.h" @@ -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; @@ -131,7 +131,7 @@ print_usage(const char *prog_name) " -c,--config=FILE alternative configuration file\n" " -C,--validate verify configuration then quit\n" " -p,--print-pid=FILE|FD print PID to file or FD\n" - " -d,--log-level={info|warning|error|none} log level (warning)\n" + " -d,--log-level={info|warning|error|none} log level (info)\n" " -l,--log-colorize=[never|always|auto] enable/disable colorization of log output on stderr\n" " -s,--log-no-syslog disable syslog logging\n" " -v,--version show the version number and quit\n"); @@ -147,8 +147,9 @@ print_pid(const char *pid_file, bool *unlink_at_exit) int pid_fd = strtoul(pid_file, &end, 10); if (errno != 0 || *end != '\0') { - if ((pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) - < 0) { + if ((pid_fd = open(pid_file, + O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { LOG_ERRNO("%s: failed to open", pid_file); return false; } else @@ -177,16 +178,16 @@ int main(int argc, char *const *argv) { static const struct option longopts[] = { - {"backend", required_argument, 0, 'b'}, - {"config", required_argument, 0, 'c'}, - {"validate", no_argument, 0, 'C'}, - {"print-pid", required_argument, 0, 'p'}, - {"log-level", required_argument, 0, 'd'}, - {"log-colorize", optional_argument, 0, 'l'}, - {"log-no-syslog", no_argument, 0, 's'}, - {"version", no_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {NULL, no_argument, 0, 0}, + {"backend", required_argument, 0, 'b'}, + {"config", required_argument, 0, 'c'}, + {"validate", no_argument, 0, 'C'}, + {"print-pid", required_argument, 0, 'p'}, + {"log-level", required_argument, 0, 'd'}, + {"log-colorize", optional_argument, 0, 'l'}, + {"log-no-syslog", no_argument, 0, 's'}, + {"version", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {NULL, no_argument, 0, 0}, }; bool unlink_pid_file = false; @@ -196,7 +197,7 @@ main(int argc, char *const *argv) char *config_path = NULL; enum bar_backend backend = BAR_BACKEND_AUTO; - enum log_class log_level = LOG_CLASS_WARNING; + enum log_class log_level = LOG_CLASS_INFO; enum log_colorize log_colorize = LOG_COLORIZE_AUTO; bool log_syslog = true; @@ -222,8 +223,9 @@ main(int argc, char *const *argv) if (stat(optarg, &st) == -1) { fprintf(stderr, "%s: invalid configuration file: %s\n", optarg, strerror(errno)); return EXIT_FAILURE; - } else if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) { - fprintf(stderr, "%s: invalid configuration file: neither a regular file nor a pipe or FIFO\n", optarg); + } else if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "%s: invalid configuration file: not a regular file\n", + optarg); return EXIT_FAILURE; } @@ -242,7 +244,11 @@ main(int argc, char *const *argv) case 'd': { int lvl = log_level_from_string(optarg); if (lvl < 0) { - fprintf(stderr, "-d,--log-level: %s: argument must be one of %s\n", optarg, log_level_string_hint()); + fprintf( + stderr, + "-d,--log-level: %s: argument must be one of %s\n", + optarg, + log_level_string_hint()); return EXIT_FAILURE; } log_level = lvl; @@ -286,9 +292,12 @@ main(int argc, char *const *argv) log_init(log_colorize, log_syslog, LOG_FACILITY_DAEMON, log_level); - _Static_assert((int)LOG_CLASS_ERROR == (int)FCFT_LOG_CLASS_ERROR, "fcft log level enum offset"); - _Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS, "fcft colorize enum mismatch"); - fcft_init((enum fcft_log_colorize)log_colorize, log_syslog, (enum fcft_log_class)log_level); + _Static_assert((int)LOG_CLASS_ERROR == (int)FCFT_LOG_CLASS_ERROR, + "fcft log level enum offset"); + _Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS, + "fcft colorize enum mismatch"); + fcft_init((enum fcft_log_colorize)log_colorize, log_syslog, + (enum fcft_log_class)log_level); atexit(&fcft_fini); const struct sigaction sa = {.sa_handler = &signal_handler}; diff --git a/meson.build b/meson.build index 67d3096..763b412 100644 --- a/meson.build +++ b/meson.build @@ -1,22 +1,18 @@ project('yambar', 'c', - version: '1.11.0', + version: '1.9.0', license: 'MIT', - meson_version: '>=0.60.0', + meson_version: '>=0.59.0', default_options: ['c_std=c18', 'warning_level=1', + 'werror=true', 'b_ndebug=if-release']) is_debug_build = get_option('buildtype').startswith('debug') plugs_as_libs = get_option('core-plugins-as-shared-libraries') cc = meson.get_compiler('c') -cc_flags = [ - '-Werror=all' - ] -if cc.has_function('memfd_create', - args: ['-D_GNU_SOURCE=200809L'], - prefix: '#include ') +if cc.has_function('memfd_create') add_project_arguments('-DMEMFD_CREATE', language: 'c') endif @@ -78,7 +74,6 @@ tllist = dependency('tllist', version: '>=1.0.1', fallback: 'tllist') fcft = dependency('fcft', version: ['>=3.0.0', '<4.0.0'], fallback: 'fcft') add_project_arguments( - cc_flags + ['-D_GNU_SOURCE'] + (is_debug_build ? ['-D_DEBUG'] : []) + (backend_x11 ? ['-DENABLE_X11'] : []) + @@ -179,11 +174,10 @@ summary( 'Clock': plugin_clock_enabled, 'CPU monitoring': plugin_cpu_enabled, 'Disk I/O monitoring': plugin_disk_io_enabled, - 'dwl (dwm for Wayland)': plugin_dwl_enabled, + 'DWL (dwm for Wayland)': plugin_dwl_enabled, 'Foreign toplevel (window tracking for Wayland)': plugin_foreign_toplevel_enabled, 'Memory monitoring': plugin_mem_enabled, 'Music Player Daemon (MPD)': plugin_mpd_enabled, - 'Media Player Remote Interface Specificaion (MPRIS)': plugin_mpris_enabled, 'i3+Sway': plugin_i3_enabled, 'Label': plugin_label_enabled, 'Network monitoring': plugin_network_enabled, @@ -193,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, }, diff --git a/meson_options.txt b/meson_options.txt index 23a8e11..03c0ead 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -19,15 +19,13 @@ option('plugin-cpu', type: 'feature', value: 'auto', option('plugin-disk-io', type: 'feature', value: 'auto', description: 'Disk I/O support') option('plugin-dwl', type: 'feature', value: 'auto', - description: 'dwl (dwm for wayland) support') + description: 'DWL (dwm for wayland) support') option('plugin-foreign-toplevel', type: 'feature', value: 'auto', description: 'Foreign toplevel (window tracking for Wayland) support') option('plugin-mem', type: 'feature', value: 'auto', description: 'Memory monitoring support') option('plugin-mpd', type: 'feature', value: 'auto', description: 'Music Player Daemon (MPD) support') -option('plugin-mpris', type: 'feature', value: 'enabled', - description: 'Media Player Remote Interface Specificaion (MPRIS) support') option('plugin-i3', type: 'feature', value: 'auto', description: 'i3+Sway support') option('plugin-label', type: 'feature', value: 'auto', @@ -46,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', diff --git a/module.c b/module.c index d3bde3b..1e80c32 100644 --- a/module.c +++ b/module.c @@ -1,6 +1,6 @@ #include "module.h" -#include #include +#include #include struct module * diff --git a/module.h b/module.h index 3a83cdc..5f1bc7c 100644 --- a/module.h +++ b/module.h @@ -35,9 +35,9 @@ void module_default_destroy(struct module *mod); struct exposable *module_begin_expose(struct module *mod); /* List of attributes *all* modules implement */ -#define MODULE_COMMON_ATTRS \ - {"content", true, &conf_verify_particle}, {"anchors", false, NULL}, {"font", false, &conf_verify_font}, \ - {"foreground", false, &conf_verify_color}, \ - { \ - NULL, false, NULL \ - } +#define MODULE_COMMON_ATTRS \ + {"content", true, &conf_verify_particle}, \ + {"anchors", false, NULL}, \ + {"font", false, &conf_verify_font}, \ + {"foreground", false, &conf_verify_color}, \ + {NULL, false, NULL} diff --git a/modules/alsa.c b/modules/alsa.c index 8d7cd25..6003ae6 100644 --- a/modules/alsa.c +++ b/modules/alsa.c @@ -1,8 +1,8 @@ -#include #include #include -#include +#include #include +#include #include @@ -10,10 +10,10 @@ #define LOG_MODULE "alsa" #define LOG_ENABLE_DBG 0 +#include "../log.h" #include "../bar/bar.h" #include "../config-verify.h" #include "../config.h" -#include "../log.h" #include "../plugin.h" enum channel_type { CHANNEL_PLAYBACK, CHANNEL_CAPTURE }; @@ -29,8 +29,7 @@ struct channel { bool muted; }; -struct private -{ +struct private { char *card; char *mixer; char *volume_name; @@ -71,8 +70,7 @@ static void destroy(struct module *mod) { struct private *m = mod->private; - tll_foreach(m->channels, it) - { + tll_foreach(m->channels, it) { channel_free(&it->item); tll_remove(m->channels, it); } @@ -131,7 +129,9 @@ content(struct module *mod) if (use_db) { bool use_linear = db_max - db_min <= 24 * 100; if (use_linear) { - percent = db_min - db_max > 0 ? round(100. * (db_cur - db_min) / (db_max - db_min)) : 0; + percent = db_min - db_max > 0 + ? round(100. * (db_cur - db_min) / (db_max - db_min)) + : 0; } else { double normalized = pow(10, (double)(db_cur - db_max) / 6000.); if (db_min != SND_CTL_TLV_DB_GAIN_MUTE) { @@ -141,7 +141,9 @@ content(struct module *mod) percent = round(100. * normalized); } } else { - percent = vol_max - vol_min > 0 ? round(100. * (vol_cur - vol_min) / (vol_max - vol_min)) : 0; + percent = vol_max - vol_min > 0 + ? round(100. * (vol_cur - vol_min) / (vol_max - vol_min)) + : 0; } struct tag_set tags = { @@ -171,94 +173,107 @@ update_state(struct module *mod, snd_mixer_elem_t *elem) /* If volume level can be changed (i.e. this isn't just a switch; * e.g. a digital channel), get current channel levels */ - tll_foreach(m->channels, it) - { + tll_foreach(m->channels, it) { struct channel *chan = &it->item; - const bool has_volume = chan->type == CHANNEL_PLAYBACK ? m->has_playback_volume : m->has_capture_volume; - const bool has_db = chan->type == CHANNEL_PLAYBACK ? m->has_playback_db : m->has_capture_db; + const bool has_volume = chan->type == CHANNEL_PLAYBACK + ? m->has_playback_volume : m->has_capture_volume; + const bool has_db = chan->type == CHANNEL_PLAYBACK + ? m->has_playback_db : m->has_capture_db; if (!has_volume && !has_db) continue; + if (has_db) { chan->use_db = true; - const long min = chan->type == CHANNEL_PLAYBACK ? m->playback_db_min : m->capture_db_min; - const long max = chan->type == CHANNEL_PLAYBACK ? m->playback_db_max : m->capture_db_max; + const long min = chan->type == CHANNEL_PLAYBACK + ? m->playback_db_min : m->capture_db_min; + const long max = chan->type == CHANNEL_PLAYBACK + ? m->playback_db_max : m->capture_db_max; assert(min <= max); - int r = chan->type == CHANNEL_PLAYBACK ? snd_mixer_selem_get_playback_dB(elem, chan->id, &chan->db_cur) - : snd_mixer_selem_get_capture_dB(elem, chan->id, &chan->db_cur); + int r = chan->type == CHANNEL_PLAYBACK + ? snd_mixer_selem_get_playback_dB(elem, chan->id, &chan->db_cur) + : snd_mixer_selem_get_capture_dB(elem, chan->id, &chan->db_cur); if (r < 0) { - LOG_ERR("%s,%s: %s: failed to get current dB", m->card, m->mixer, chan->name); + LOG_ERR("%s,%s: %s: failed to get current dB", + m->card, m->mixer, chan->name); } if (chan->db_cur < min) { - LOG_WARN("%s,%s: %s: current dB is less than the indicated minimum: " - "%ld < %ld", - m->card, m->mixer, chan->name, chan->db_cur, min); + LOG_WARN( + "%s,%s: %s: current dB is less than the indicated minimum: " + "%ld < %ld", m->card, m->mixer, chan->name, chan->db_cur, min); chan->db_cur = min; } if (chan->db_cur > max) { - LOG_WARN("%s,%s: %s: current dB is greater than the indicated maximum: " - "%ld > %ld", - m->card, m->mixer, chan->name, chan->db_cur, max); + LOG_WARN( + "%s,%s: %s: current dB is greater than the indicated maximum: " + "%ld > %ld", m->card, m->mixer, chan->name, chan->db_cur, max); chan->db_cur = max; } assert(chan->db_cur >= min); - assert(chan->db_cur <= max); + assert(chan->db_cur <= max ); - LOG_DBG("%s,%s: %s: dB: %ld", m->card, m->mixer, chan->name, chan->db_cur); + LOG_DBG("%s,%s: %s: dB: %ld", + m->card, m->mixer, chan->name, chan->db_cur); } else chan->use_db = false; - const long min = chan->type == CHANNEL_PLAYBACK ? m->playback_vol_min : m->capture_vol_min; - const long max = chan->type == CHANNEL_PLAYBACK ? m->playback_vol_max : m->capture_vol_max; + const long min = chan->type == CHANNEL_PLAYBACK + ? m->playback_vol_min : m->capture_vol_min; + const long max = chan->type == CHANNEL_PLAYBACK + ? m->playback_vol_max : m->capture_vol_max; assert(min <= max); - int r = chan->type == CHANNEL_PLAYBACK ? snd_mixer_selem_get_playback_volume(elem, chan->id, &chan->vol_cur) - : snd_mixer_selem_get_capture_volume(elem, chan->id, &chan->vol_cur); + int r = chan->type == CHANNEL_PLAYBACK + ? snd_mixer_selem_get_playback_volume(elem, chan->id, &chan->vol_cur) + : snd_mixer_selem_get_capture_volume(elem, chan->id, &chan->vol_cur); if (r < 0) { - LOG_ERR("%s,%s: %s: failed to get current volume", m->card, m->mixer, chan->name); + LOG_ERR("%s,%s: %s: failed to get current volume", + m->card, m->mixer, chan->name); } if (chan->vol_cur < min) { - LOG_WARN("%s,%s: %s: current volume is less than the indicated minimum: " - "%ld < %ld", - m->card, m->mixer, chan->name, chan->vol_cur, min); + LOG_WARN( + "%s,%s: %s: current volume is less than the indicated minimum: " + "%ld < %ld", m->card, m->mixer, chan->name, chan->vol_cur, min); chan->vol_cur = min; } if (chan->vol_cur > max) { - LOG_WARN("%s,%s: %s: current volume is greater than the indicated maximum: " - "%ld > %ld", - m->card, m->mixer, chan->name, chan->vol_cur, max); + LOG_WARN( + "%s,%s: %s: current volume is greater than the indicated maximum: " + "%ld > %ld", m->card, m->mixer, chan->name, chan->vol_cur, max); chan->vol_cur = max; } assert(chan->vol_cur >= min); - assert(chan->vol_cur <= max); + assert(chan->vol_cur <= max ); - LOG_DBG("%s,%s: %s: volume: %ld", m->card, m->mixer, chan->name, chan->vol_cur); + LOG_DBG("%s,%s: %s: volume: %ld", + m->card, m->mixer, chan->name, chan->vol_cur); } /* Get channels’ muted state */ - tll_foreach(m->channels, it) - { + tll_foreach(m->channels, it) { struct channel *chan = &it->item; int unmuted; - int r = chan->type == CHANNEL_PLAYBACK ? snd_mixer_selem_get_playback_switch(elem, chan->id, &unmuted) - : snd_mixer_selem_get_capture_switch(elem, chan->id, &unmuted); + int r = chan->type == CHANNEL_PLAYBACK + ? snd_mixer_selem_get_playback_switch(elem, chan->id, &unmuted) + : snd_mixer_selem_get_capture_switch(elem, chan->id, &unmuted); if (r < 0) { - LOG_WARN("%s,%s: %s: failed to get muted state", m->card, m->mixer, chan->name); + LOG_WARN("%s,%s: %s: failed to get muted state", + m->card, m->mixer, chan->name); unmuted = 1; } @@ -294,8 +309,10 @@ run_while_online(struct module *mod) return ret; } - if (snd_mixer_attach(handle, m->card) != 0 || snd_mixer_selem_register(handle, NULL, NULL) != 0 - || snd_mixer_load(handle) != 0) { + if (snd_mixer_attach(handle, m->card) != 0 || + snd_mixer_selem_register(handle, NULL, NULL) != 0 || + snd_mixer_load(handle) != 0) + { LOG_ERR("failed to attach to card"); ret = RUN_FAILED_CONNECT; goto err; @@ -306,7 +323,7 @@ run_while_online(struct module *mod) snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, m->mixer); - snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid); + snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); if (elem == NULL) { LOG_ERR("failed to find mixer"); goto err; @@ -315,24 +332,30 @@ run_while_online(struct module *mod) /* Get playback volume range */ m->has_playback_volume = snd_mixer_selem_has_playback_volume(elem) > 0; if (m->has_playback_volume) { - if (snd_mixer_selem_get_playback_volume_range(elem, &m->playback_vol_min, &m->playback_vol_max) < 0) { - LOG_ERR("%s,%s: failed to get playback volume range", m->card, m->mixer); + if (snd_mixer_selem_get_playback_volume_range( + elem, &m->playback_vol_min, &m->playback_vol_max) < 0) + { + LOG_ERR("%s,%s: failed to get playback volume range", + m->card, m->mixer); assert(m->playback_vol_min == 0); assert(m->playback_vol_max == 0); } if (m->playback_vol_min > m->playback_vol_max) { - LOG_WARN("%s,%s: indicated minimum playback volume is greater than the " - "maximum: %ld > %ld", - m->card, m->mixer, m->playback_vol_min, m->playback_vol_max); + LOG_WARN( + "%s,%s: indicated minimum playback volume is greater than the " + "maximum: %ld > %ld", + m->card, m->mixer, m->playback_vol_min, m->playback_vol_max); m->playback_vol_min = m->playback_vol_max; } } - if (snd_mixer_selem_get_playback_dB_range(elem, &m->playback_db_min, &m->playback_db_max) < 0) { - LOG_WARN("%s,%s: failed to get playback dB range, " - "will use raw volume values instead", - m->card, m->mixer); + if (snd_mixer_selem_get_playback_dB_range( + elem, &m->playback_db_min, &m->playback_db_max) < 0) + { + LOG_WARN( + "%s,%s: failed to get playback dB range, " + "will use raw volume values instead", m->card, m->mixer); m->has_playback_db = false; } else m->has_playback_db = true; @@ -340,24 +363,30 @@ run_while_online(struct module *mod) /* Get capture volume range */ m->has_capture_volume = snd_mixer_selem_has_capture_volume(elem) > 0; if (m->has_capture_volume) { - if (snd_mixer_selem_get_capture_volume_range(elem, &m->capture_vol_min, &m->capture_vol_max) < 0) { - LOG_ERR("%s,%s: failed to get capture volume range", m->card, m->mixer); + if (snd_mixer_selem_get_capture_volume_range( + elem, &m->capture_vol_min, &m->capture_vol_max) < 0) + { + LOG_ERR("%s,%s: failed to get capture volume range", + m->card, m->mixer); assert(m->capture_vol_min == 0); assert(m->capture_vol_max == 0); } if (m->capture_vol_min > m->capture_vol_max) { - LOG_WARN("%s,%s: indicated minimum capture volume is greater than the " - "maximum: %ld > %ld", - m->card, m->mixer, m->capture_vol_min, m->capture_vol_max); + LOG_WARN( + "%s,%s: indicated minimum capture volume is greater than the " + "maximum: %ld > %ld", + m->card, m->mixer, m->capture_vol_min, m->capture_vol_max); m->capture_vol_min = m->capture_vol_max; } } - if (snd_mixer_selem_get_capture_dB_range(elem, &m->capture_db_min, &m->capture_db_max) < 0) { - LOG_WARN("%s,%s: failed to get capture dB range, " - "will use raw volume values instead", - m->card, m->mixer); + if (snd_mixer_selem_get_capture_dB_range( + elem, &m->capture_db_min, &m->capture_db_max) < 0) + { + LOG_WARN( + "%s,%s: failed to get capture dB range, " + "will use raw volume values instead", m->card, m->mixer); m->has_capture_db = false; } else m->has_capture_db = true; @@ -371,7 +400,7 @@ run_while_online(struct module *mod) struct channel chan = { .id = i, .type = is_playback ? CHANNEL_PLAYBACK : CHANNEL_CAPTURE, - .name = strdup(snd_mixer_selem_channel_name(i)), + .name = strdup(snd_mixer_selem_channel_name( i)), }; tll_push_back(m->channels, chan); } @@ -384,13 +413,13 @@ run_while_online(struct module *mod) char channels_str[1024]; int channels_idx = 0; - tll_foreach(m->channels, it) - { + tll_foreach(m->channels, it) { const struct channel *chan = &it->item; - channels_idx += snprintf(&channels_str[channels_idx], sizeof(channels_str) - channels_idx, - channels_idx == 0 ? "%s (%s)" : ", %s (%s)", chan->name, - chan->type == CHANNEL_PLAYBACK ? "🔊" : "🎤"); + channels_idx += snprintf( + &channels_str[channels_idx], sizeof(channels_str) - channels_idx, + channels_idx == 0 ? "%s (%s)" : ", %s (%s)", + chan->name, chan->type == CHANNEL_PLAYBACK ? "🔊" : "🎤"); assert(channels_idx <= sizeof(channels_str)); } @@ -400,8 +429,7 @@ run_while_online(struct module *mod) bool volume_channel_is_valid = m->volume_name == NULL; bool muted_channel_is_valid = m->muted_name == NULL; - tll_foreach(m->channels, it) - { + tll_foreach(m->channels, it) { const struct channel *chan = &it->item; if (m->volume_name != NULL && strcmp(chan->name, m->volume_name) == 0) { m->volume_chan = chan; @@ -434,14 +462,26 @@ run_while_online(struct module *mod) update_state(mod, elem); LOG_INFO( - "%s,%s: %s range=%ld-%ld, current=%ld%s (sources: volume=%s, muted=%s)", m->card, m->mixer, + "%s,%s: %s range=%ld-%ld, current=%ld%s (sources: volume=%s, muted=%s)", + m->card, m->mixer, m->volume_chan->use_db ? "dB" : "volume", - (m->volume_chan->type == CHANNEL_PLAYBACK ? (m->volume_chan->use_db ? m->playback_db_min : m->playback_vol_min) - : (m->volume_chan->use_db ? m->capture_db_min : m->capture_vol_min)), - (m->volume_chan->type == CHANNEL_PLAYBACK ? (m->volume_chan->use_db ? m->playback_db_max : m->playback_vol_max) - : (m->volume_chan->use_db ? m->capture_db_max : m->capture_vol_max)), + (m->volume_chan->type == CHANNEL_PLAYBACK + ? (m->volume_chan->use_db + ? m->playback_db_min + : m->playback_vol_min) + : (m->volume_chan->use_db + ? m->capture_db_min + : m->capture_vol_min)), + (m->volume_chan->type == CHANNEL_PLAYBACK + ? (m->volume_chan->use_db + ? m->playback_db_max + : m->playback_vol_max) + : (m->volume_chan->use_db + ? m->capture_db_max + : m->capture_vol_max)), m->volume_chan->use_db ? m->volume_chan->db_cur : m->volume_chan->vol_cur, - m->muted_chan->muted ? " (muted)" : "", m->volume_chan->name, m->muted_chan->name); + m->muted_chan->muted ? " (muted)" : "", + m->volume_chan->name, m->muted_chan->name); mod->bar->refresh(mod->bar); @@ -555,7 +595,8 @@ run(struct module *mod) bool have_create_event = false; while (!have_create_event) { - struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = ifd, .events = POLLIN}}; + struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, + {.fd = ifd, .events = POLLIN}}; int r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1); if (r < 0) { @@ -597,7 +638,7 @@ run(struct module *mod) break; /* Consume inotify data */ - for (const char *ptr = buf; ptr < buf + len;) { + for (const char *ptr = buf; ptr < buf + len; ) { const struct inotify_event *e = (const struct inotify_event *)ptr; if (e->mask & IN_CREATE) { @@ -615,20 +656,23 @@ out: if (wd >= 0) inotify_rm_watch(ifd, wd); if (ifd >= 0) - close(ifd); + close (ifd); return ret; } static struct module * -alsa_new(const char *card, const char *mixer, const char *volume_channel_name, const char *muted_channel_name, +alsa_new(const char *card, const char *mixer, + const char *volume_channel_name, const char *muted_channel_name, struct particle *label) { struct private *priv = calloc(1, sizeof(*priv)); priv->label = label; priv->card = strdup(card); priv->mixer = strdup(mixer); - priv->volume_name = volume_channel_name != NULL ? strdup(volume_channel_name) : NULL; - priv->muted_name = muted_channel_name != NULL ? strdup(muted_channel_name) : NULL; + priv->volume_name = + volume_channel_name != NULL ? strdup(volume_channel_name) : NULL; + priv->muted_name = + muted_channel_name != NULL ? strdup(muted_channel_name) : NULL; struct module *mod = module_common_new(); mod->private = priv; @@ -648,9 +692,12 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *muted = yml_get_value(node, "muted"); const struct yml_node *content = yml_get_value(node, "content"); - return alsa_new(yml_value_as_string(card), yml_value_as_string(mixer), - volume != NULL ? yml_value_as_string(volume) : NULL, - muted != NULL ? yml_value_as_string(muted) : NULL, conf_to_particle(content, inherited)); + return alsa_new( + yml_value_as_string(card), + yml_value_as_string(mixer), + volume != NULL ? yml_value_as_string(volume) : NULL, + muted != NULL ? yml_value_as_string(muted) : NULL, + conf_to_particle(content, inherited)); } static bool diff --git a/modules/backlight.c b/modules/backlight.c index 1495c5c..9f26a14 100644 --- a/modules/backlight.c +++ b/modules/backlight.c @@ -1,26 +1,25 @@ -#include -#include -#include -#include #include #include #include +#include +#include #include +#include +#include -#include #include +#include #include #define LOG_MODULE "backlight" -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../plugin.h" -struct private -{ +struct private { struct particle *label; char *device; @@ -112,13 +111,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 +125,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 +135,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) { @@ -146,7 +145,8 @@ initialize(struct private *m) m->current_brightness = readint_from_fd(current_fd); - LOG_INFO("%s: brightness: %ld (max: %ld)", m->device, m->current_brightness, m->max_brightness); + LOG_INFO("%s: brightness: %ld (max: %ld)", m->device, m->current_brightness, + m->max_brightness); return current_fd; } @@ -244,7 +244,8 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *name = yml_get_value(node, "name"); const struct yml_node *c = yml_get_value(node, "content"); - return backlight_new(yml_value_as_string(name), conf_to_particle(c, inherited)); + return backlight_new( + yml_value_as_string(name), conf_to_particle(c, inherited)); } static bool diff --git a/modules/battery.c b/modules/battery.c index 34b98c8..c4f949c 100644 --- a/modules/battery.c +++ b/modules/battery.c @@ -1,49 +1,31 @@ -#include -#include -#include #include #include #include -#include #include +#include +#include #include -#include #include +#include #include -#include #define LOG_MODULE "battery" #define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../plugin.h" -#define max(x, y) ((x) > (y) ? (x) : (y)) - -static const long min_poll_interval = 250; -static const long default_poll_interval = 60 * 1000; -static const long one_sec_in_ns = 1000000000; - enum state { STATE_FULL, STATE_NOTCHARGING, STATE_CHARGING, STATE_DISCHARGING, STATE_UNKNOWN }; -struct current_state { - long ema; - long current; - struct timespec time; -}; - -struct private -{ +struct private { struct particle *label; - long poll_interval; - int battery_scale; - long smoothing_scale; + int poll_interval; char *battery; char *manufacturer; char *model; @@ -57,64 +39,10 @@ struct private long energy; long power; long charge; - struct current_state ema_current; + long current; long time_to_empty; - long time_to_full; }; -static int64_t -difftimespec_ns(const struct timespec after, const struct timespec before) -{ - return ((int64_t)after.tv_sec - (int64_t)before.tv_sec) * (int64_t)one_sec_in_ns - + ((int64_t)after.tv_nsec - (int64_t)before.tv_nsec); -} - -// Linear Exponential Moving Average (unevenly spaced time series) -// http://www.eckner.com/papers/Algorithms%20for%20Unevenly%20Spaced%20Time%20Series.pdf -// Adapted from: https://github.com/andreas50/utsAlgorithms/blob/master/ema.c -static void -ema_linear(struct current_state *state, struct current_state curr, long tau) -{ - double w, w2, tmp; - - if (state->current == -1) { - *state = curr; - return; - } - - long time = difftimespec_ns(curr.time, state->time); - tmp = time / (double)tau; - w = exp(-tmp); - if (tmp > 1e-6) { - w2 = (1 - w) / tmp; - } else { - // Use taylor expansion for numerical stability - w2 = 1 - tmp / 2 + tmp * tmp / 6 - tmp * tmp * tmp / 24; - } - - double ema = state->ema * w + curr.current * (1 - w2) + state->current * (w2 - w); - - state->ema = ema; - state->current = curr.current; - state->time = curr.time; - - LOG_DBG("ema current: %ld", (long)ema); -} - -static void -timespec_sub(const struct timespec *a, const struct timespec *b, struct timespec *res) -{ - - res->tv_sec = a->tv_sec - b->tv_sec; - res->tv_nsec = a->tv_nsec - b->tv_nsec; - - /* tv_nsec may be negative */ - if (res->tv_nsec < 0) { - res->tv_sec--; - res->tv_nsec += one_sec_in_ns; - } -} - static void destroy(struct module *mod) { @@ -145,22 +73,21 @@ content(struct module *mod) mtx_lock(&mod->lock); - assert(m->state == STATE_FULL || m->state == STATE_NOTCHARGING || m->state == STATE_CHARGING - || m->state == STATE_DISCHARGING || m->state == STATE_UNKNOWN); + assert(m->state == STATE_FULL || + m->state == STATE_NOTCHARGING || + m->state == STATE_CHARGING || + m->state == STATE_DISCHARGING || + m->state == STATE_UNKNOWN); unsigned long hours; unsigned long minutes; - if (m->time_to_empty > 0) { - minutes = m->time_to_empty / 60; - hours = minutes / 60; - minutes = minutes % 60; - } else if (m->time_to_full > 0) { - minutes = m->time_to_full / 60; - hours = minutes / 60; - minutes = minutes % 60; - } else if (m->energy_full >= 0 && m->charge && m->power >= 0) { - unsigned long energy = m->state == STATE_CHARGING ? m->energy_full - m->energy : m->energy; + if (m->time_to_empty >= 0) { + hours = m->time_to_empty / 60; + minutes = m->time_to_empty % 60; + } else if (m->energy_full >= 0 && m->charge && m->power >= 0) { + unsigned long energy = m->state == STATE_CHARGING + ? m->energy_full - m->energy : m->energy; double hours_as_float; if (m->state == STATE_FULL || m->state == STATE_NOTCHARGING) @@ -172,14 +99,15 @@ content(struct module *mod) hours = hours_as_float; minutes = (hours_as_float - (double)hours) * 60; - } else if (m->charge_full >= 0 && m->charge >= 0 && m->ema_current.current >= 0) { - unsigned long charge = m->state == STATE_CHARGING ? m->charge_full - m->charge : m->charge; + } else if (m->charge_full >= 0 && m->charge >= 0 && m->current >= 0) { + unsigned long charge = m->state == STATE_CHARGING + ? m->charge_full - m->charge : m->charge; double hours_as_float; if (m->state == STATE_FULL || m->state == STATE_NOTCHARGING) hours_as_float = 0.0; - else if (m->ema_current.current > 0) - hours_as_float = (double)charge / m->ema_current.current; + else if (m->current > 0) + hours_as_float = (double)charge / m->current; else hours_as_float = 99.0; @@ -219,18 +147,20 @@ content(struct module *mod) } static const char * -readline_from_fd(int fd, size_t sz, char buf[static sz]) +readline_from_fd(int fd) { - ssize_t bytes = read(fd, buf, sz - 1); + static char buf[4096]; + + ssize_t sz = read(fd, buf, sizeof(buf) - 1); lseek(fd, 0, SEEK_SET); - if (bytes < 0) { + if (sz < 0) { LOG_WARN("failed to read from FD=%d", fd); return NULL; } - buf[bytes] = '\0'; - for (ssize_t i = bytes - 1; i >= 0 && buf[i] == '\n'; bytes--) + buf[sz] = '\0'; + for (ssize_t i = sz - 1; i >= 0 && buf[i] == '\n'; sz--) buf[i] = '\0'; return buf; @@ -239,8 +169,7 @@ readline_from_fd(int fd, size_t sz, char buf[static sz]) static long readint_from_fd(int fd) { - char buf[512]; - const char *s = readline_from_fd(fd, sizeof(buf), buf); + const char *s = readline_from_fd(fd); if (s == NULL) return 0; @@ -257,15 +186,13 @@ readint_from_fd(int fd) static bool 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,31 +201,34 @@ 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)); + LOG_WARN("/sys/class/power_supply/%s/manufacturer: %s", + m->battery, strerror(errno)); m->manufacturer = NULL; } else { - m->manufacturer = strdup(readline_from_fd(fd, sizeof(line_buf), line_buf)); + m->manufacturer = strdup(readline_from_fd(fd)); close(fd); } } { - 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)); + LOG_WARN("/sys/class/power_supply/%s/model_name: %s", + m->battery, strerror(errno)); m->model = NULL; } else { - m->model = strdup(readline_from_fd(fd, sizeof(line_buf), line_buf)); + m->model = strdup(readline_from_fd(fd)); close(fd); } } - if (faccessat(base_dir_fd, "energy_full_design", O_RDONLY, 0) == 0 - && faccessat(base_dir_fd, "energy_full", O_RDONLY, 0) == 0) { + 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 +239,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; @@ -322,27 +252,28 @@ initialize(struct private *m) m->energy_full = m->energy_full_design = -1; } - if (faccessat(base_dir_fd, "charge_full_design", O_RDONLY, 0) == 0 - && faccessat(base_dir_fd, "charge_full", O_RDONLY, 0) == 0) { + 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; } - m->charge_full_design = readint_from_fd(fd) / m->battery_scale; + m->charge_full_design = readint_from_fd(fd); close(fd); } { - 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; } - m->charge_full = readint_from_fd(fd) / m->battery_scale; + m->charge_full = readint_from_fd(fd); close(fd); } } else { @@ -362,13 +293,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 +307,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 +322,11 @@ 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); long capacity = readint_from_fd(capacity_fd); long energy = energy_fd >= 0 ? readint_from_fd(energy_fd) : -1; @@ -404,14 +334,8 @@ update_status(struct module *mod) long charge = charge_fd >= 0 ? readint_from_fd(charge_fd) : -1; long current = current_fd >= 0 ? readint_from_fd(current_fd) : -1; long time_to_empty = time_to_empty_fd >= 0 ? readint_from_fd(time_to_empty_fd) : -1; - long time_to_full = time_to_full_fd >= 0 ? readint_from_fd(time_to_full_fd) : -1; - if (charge >= -1) { - charge /= m->battery_scale; - } - - char buf[512]; - const char *status = readline_from_fd(status_fd, sizeof(buf), buf); + const char *status = readline_from_fd(status_fd); if (status_fd >= 0) close(status_fd); @@ -427,8 +351,6 @@ update_status(struct module *mod) close(current_fd); if (time_to_empty_fd >= 0) close(time_to_empty_fd); - if (time_to_full_fd >= 0) - close(time_to_full_fd); if (base_dir_fd >= 0) close(base_dir_fd); @@ -453,25 +375,17 @@ update_status(struct module *mod) } LOG_DBG("capacity: %ld, energy: %ld, power: %ld, charge=%ld, current=%ld, " - "time-to-empty: %ld, time-to-full: %ld", - capacity, energy, power, charge, current, time_to_empty, time_to_full); + "time-to-empty: %ld", capacity, energy, power, charge, current, + time_to_empty); mtx_lock(&mod->lock); - if (m->state != state) { - m->ema_current = (struct current_state){-1, 0, (struct timespec){0, 0}}; - } m->state = state; m->capacity = capacity; m->energy = energy; m->power = power; m->charge = charge; - if (current != -1) { - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - ema_linear(&m->ema_current, (struct current_state){current, current, t}, m->smoothing_scale); - } + m->current = current; m->time_to_empty = time_to_empty; - m->time_to_full = time_to_full; mtx_unlock(&mod->lock); return true; } @@ -485,10 +399,13 @@ run(struct module *mod) if (!initialize(m)) return -1; - LOG_INFO("%s: %s %s (at %.1f%% of original capacity)", m->battery, m->manufacturer, m->model, - (m->energy_full > 0 ? 100.0 * m->energy_full / m->energy_full_design - : m->charge_full > 0 ? 100.0 * m->charge_full / m->charge_full_design - : 0.0)); + LOG_INFO("%s: %s %s (at %.1f%% of original capacity)", + m->battery, m->manufacturer, m->model, + (m->energy_full > 0 + ? 100.0 * m->energy_full / m->energy_full_design + : m->charge_full > 0 + ? 100.0 * m->charge_full / m->charge_full_design + : 0.0)); int ret = 1; @@ -506,25 +423,14 @@ run(struct module *mod) bar->refresh(bar); - int timeout_left_ms = m->poll_interval; - while (true) { struct pollfd fds[] = { {.fd = mod->abort_fd, .events = POLLIN}, {.fd = udev_monitor_get_fd(mon), .events = POLLIN}, }; - - int timeout = m->poll_interval > 0 ? timeout_left_ms : -1; - - struct timespec time_before_poll; - if (clock_gettime(CLOCK_BOOTTIME, &time_before_poll) < 0) { - LOG_ERRNO("failed to get current time"); - break; - } - - const int poll_ret = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout); - - if (poll_ret < 0) { + if (poll(fds, sizeof(fds) / sizeof(fds[0]), + m->poll_interval > 0 ? m->poll_interval * 1000 : -1) < 0) + { if (errno == EINTR) continue; @@ -537,51 +443,21 @@ run(struct module *mod) break; } - bool udev_for_us = false; - if (fds[1].revents & POLLIN) { struct udev_device *dev = udev_monitor_receive_device(mon); - if (dev != NULL) { - const char *sysname = udev_device_get_sysname(dev); - udev_for_us = sysname != NULL && strcmp(sysname, m->battery) == 0; + if (dev == NULL) + continue; - if (!udev_for_us) { - LOG_DBG("udev notification not for us (%s != %s)", m->battery, - sysname != sysname ? sysname : "NULL"); - } else - LOG_DBG("triggering update due to udev notification"); + const char *sysname = udev_device_get_sysname(dev); + bool is_us = sysname != NULL && strcmp(sysname, m->battery) == 0; + udev_device_unref(dev); - udev_device_unref(dev); - } + if (!is_us) + continue; } - if (udev_for_us || poll_ret == 0) { - if (update_status(mod)) - bar->refresh(bar); - } - - if (poll_ret == 0 || udev_for_us) { - LOG_DBG("resetting timeout-left to %ldms", m->poll_interval); - timeout_left_ms = m->poll_interval; - } else { - struct timespec time_after_poll; - if (clock_gettime(CLOCK_BOOTTIME, &time_after_poll) < 0) { - LOG_ERRNO("failed to get current time"); - break; - } - - struct timespec timeout_consumed; - timespec_sub(&time_after_poll, &time_before_poll, &timeout_consumed); - - const int timeout_consumed_ms = timeout_consumed.tv_sec * 1000 + timeout_consumed.tv_nsec / 1000000; - - LOG_DBG("timeout-left before: %dms, consumed: %dms, updated: %dms", timeout_left_ms, timeout_consumed_ms, - max(timeout_left_ms - timeout_consumed_ms, 0)); - - timeout_left_ms -= timeout_consumed_ms; - if (timeout_left_ms < 0) - timeout_left_ms = 0; - } + if (update_status(mod)) + bar->refresh(bar); } out: @@ -593,17 +469,13 @@ out: } static struct module * -battery_new(const char *battery, struct particle *label, long poll_interval_msecs, int battery_scale, - long smoothing_secs) +battery_new(const char *battery, struct particle *label, int poll_interval_secs) { struct private *m = calloc(1, sizeof(*m)); m->label = label; - m->poll_interval = poll_interval_msecs; - m->battery_scale = battery_scale; - m->smoothing_scale = smoothing_secs * one_sec_in_ns; + m->poll_interval = poll_interval_secs; m->battery = strdup(battery); m->state = STATE_UNKNOWN; - m->ema_current = (struct current_state){-1, 0, (struct timespec){0, 0}}; struct module *mod = module_common_new(); mod->private = m; @@ -620,29 +492,11 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *name = yml_get_value(node, "name"); const struct yml_node *poll_interval = yml_get_value(node, "poll-interval"); - const struct yml_node *battery_scale = yml_get_value(node, "battery-scale"); - const struct yml_node *smoothing_secs = yml_get_value(node, "smoothing-secs"); - return battery_new(yml_value_as_string(name), conf_to_particle(c, inherited), - (poll_interval != NULL ? yml_value_as_int(poll_interval) : default_poll_interval), - (battery_scale != NULL ? yml_value_as_int(battery_scale) : 1), - (smoothing_secs != NULL ? yml_value_as_int(smoothing_secs) : 100)); -} - -static bool -conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node) -{ - if (!conf_verify_unsigned(chain, node)) - return false; - - const long value = yml_value_as_int(node); - - if (value != 0 && value < min_poll_interval) { - LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval); - return false; - } - - return true; + return battery_new( + yml_value_as_string(name), + conf_to_particle(c, inherited), + poll_interval != NULL ? yml_value_as_int(poll_interval) : 60); } static bool @@ -650,9 +504,7 @@ verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { {"name", true, &conf_verify_string}, - {"poll-interval", false, &conf_verify_poll_interval}, - {"battery-scale", false, &conf_verify_unsigned}, - {"smoothing-secs", false, &conf_verify_unsigned}, + {"poll-interval", false, &conf_verify_unsigned}, MODULE_COMMON_ATTRS, }; diff --git a/modules/clock.c b/modules/clock.c index 1758c0a..0487a9d 100644 --- a/modules/clock.c +++ b/modules/clock.c @@ -1,22 +1,21 @@ -#include -#include #include #include #include +#include +#include #include #include #define LOG_MODULE "clock" #define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../plugin.h" -struct private -{ +struct private { struct particle *label; enum { UPDATE_GRANULARITY_SECONDS, @@ -58,7 +57,8 @@ content(struct module *mod) strftime(time_str, sizeof(time_str), m->time_format, tm); struct tag_set tags = { - .tags = (struct tag *[]){tag_new_string(mod, "time", time_str), tag_new_string(mod, "date", date_str)}, + .tags = (struct tag *[]){tag_new_string(mod, "time", time_str), + tag_new_string(mod, "date", date_str)}, .count = 2, }; @@ -90,12 +90,15 @@ run(struct module *mod) switch (m->update_granularity) { case UPDATE_GRANULARITY_SECONDS: { - const struct timeval next_second = {.tv_sec = now.tv_sec + 1, .tv_usec = 0}; + const struct timeval next_second = { + .tv_sec = now.tv_sec + 1, + .tv_usec = 0}; struct timeval _timeout; timersub(&next_second, &now, &_timeout); - assert(_timeout.tv_sec == 0 || (_timeout.tv_sec == 1 && _timeout.tv_usec == 0)); + assert(_timeout.tv_sec == 0 || + (_timeout.tv_sec == 1 && _timeout.tv_usec == 0)); timeout_ms = _timeout.tv_usec / 1000; break; } @@ -115,7 +118,8 @@ run(struct module *mod) /* Add 1ms to account for rounding errors */ timeout_ms++; - LOG_DBG("now: %lds %ldµs -> timeout: %dms", now.tv_sec, now.tv_usec, timeout_ms); + LOG_DBG("now: %lds %ldµs -> timeout: %dms", + now.tv_sec, now.tv_usec, timeout_ms); struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}}; if (poll(fds, 1, timeout_ms) < 0) { @@ -138,7 +142,8 @@ run(struct module *mod) } static struct module * -clock_new(struct particle *label, const char *date_format, const char *time_format, bool utc) +clock_new(struct particle *label, const char *date_format, + const char *time_format, bool utc) { struct private *m = calloc(1, sizeof(*m)); m->label = label; @@ -147,12 +152,20 @@ clock_new(struct particle *label, const char *date_format, const char *time_form m->utc = utc; static const char *const seconds_formatters[] = { - "%c", "%s", "%S", "%T", "%r", "%X", + "%c", + "%s", + "%S", + "%T", + "%r", + "%X", }; m->update_granularity = UPDATE_GRANULARITY_MINUTES; - for (size_t i = 0; i < sizeof(seconds_formatters) / sizeof(seconds_formatters[0]); i++) { + for (size_t i = 0; + i < sizeof(seconds_formatters) / sizeof(seconds_formatters[0]); + i++) + { if (strstr(time_format, seconds_formatters[i]) != NULL) { m->update_granularity = UPDATE_GRANULARITY_SECONDS; break; @@ -160,7 +173,8 @@ clock_new(struct particle *label, const char *date_format, const char *time_form } LOG_DBG("using %s update granularity", - (m->update_granularity == UPDATE_GRANULARITY_MINUTES ? "minutes" : "seconds")); + (m->update_granularity == UPDATE_GRANULARITY_MINUTES + ? "minutes" : "seconds")); struct module *mod = module_common_new(); mod->private = m; @@ -179,9 +193,11 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *time_format = yml_get_value(node, "time-format"); const struct yml_node *utc = yml_get_value(node, "utc"); - return clock_new(conf_to_particle(c, inherited), date_format != NULL ? yml_value_as_string(date_format) : "%x", - time_format != NULL ? yml_value_as_string(time_format) : "%H:%M", - utc != NULL ? yml_value_as_bool(utc) : false); + return clock_new( + conf_to_particle(c, inherited), + date_format != NULL ? yml_value_as_string(date_format) : "%x", + time_format != NULL ? yml_value_as_string(time_format) : "%H:%M", + utc != NULL ? yml_value_as_bool(utc) : false); } static bool diff --git a/modules/cpu.c b/modules/cpu.c index 118361e..b63e926 100644 --- a/modules/cpu.c +++ b/modules/cpu.c @@ -13,6 +13,7 @@ #define LOG_MODULE "cpu" #define LOG_ENABLE_DBG 0 +#define SMALLEST_INTERVAL 500 #include "../log.h" #include "../bar/bar.h" @@ -21,8 +22,6 @@ #include "../particles/dynlist.h" #include "../plugin.h" -static const long min_poll_interval = 250; - struct cpu_stats { uint32_t *prev_cores_idle; uint32_t *prev_cores_nidle; @@ -31,8 +30,7 @@ struct cpu_stats { uint32_t *cur_cores_nidle; }; -struct private -{ +struct private { struct particle *template; uint16_t interval; size_t core_count; @@ -70,22 +68,28 @@ get_cpu_nb_cores() } static bool -parse_proc_stat_line(const char *line, uint32_t *user, uint32_t *nice, uint32_t *system, uint32_t *idle, - uint32_t *iowait, uint32_t *irq, uint32_t *softirq, uint32_t *steal, uint32_t *guest, - uint32_t *guestnice) +parse_proc_stat_line(const char *line, uint32_t *user, uint32_t *nice, + uint32_t *system, uint32_t *idle, uint32_t *iowait, + uint32_t *irq, uint32_t *softirq, uint32_t *steal, + uint32_t *guest, uint32_t *guestnice) { int32_t core_id; if (line[sizeof("cpu") - 1] == ' ') { - int read = sscanf(line, - "cpu %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 - " %" SCNu32 " %" SCNu32 " %" SCNu32, - user, nice, system, idle, iowait, irq, softirq, steal, guest, guestnice); + int read = sscanf( + line, + "cpu %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 + " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32, + user, nice, system, idle, iowait, irq, softirq, steal, guest, + guestnice); return read == 10; } else { - int read = sscanf(line, - "cpu%" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 - " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32, - &core_id, user, nice, system, idle, iowait, irq, softirq, steal, guest, guestnice); + int read = sscanf( + line, + "cpu%" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 + " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 + " %" SCNu32, + &core_id, user, nice, system, idle, iowait, irq, softirq, steal, + guest, guestnice); return read == 11; } } @@ -93,12 +97,18 @@ parse_proc_stat_line(const char *line, uint32_t *user, uint32_t *nice, uint32_t static uint8_t get_cpu_usage_percent(const struct cpu_stats *cpu_stats, int8_t core_idx) { - uint32_t prev_total = cpu_stats->prev_cores_idle[core_idx + 1] + cpu_stats->prev_cores_nidle[core_idx + 1]; + uint32_t prev_total = + cpu_stats->prev_cores_idle[core_idx + 1] + + cpu_stats->prev_cores_nidle[core_idx + 1]; - uint32_t cur_total = cpu_stats->cur_cores_idle[core_idx + 1] + cpu_stats->cur_cores_nidle[core_idx + 1]; + uint32_t cur_total = + cpu_stats->cur_cores_idle[core_idx + 1] + + cpu_stats->cur_cores_nidle[core_idx + 1]; double totald = cur_total - prev_total; - double nidled = cpu_stats->cur_cores_nidle[core_idx + 1] - cpu_stats->prev_cores_nidle[core_idx + 1]; + double nidled = + cpu_stats->cur_cores_nidle[core_idx + 1] - + cpu_stats->prev_cores_nidle[core_idx + 1]; double percent = (nidled * 100) / (totald + 1); return round(percent); @@ -124,7 +134,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; @@ -132,8 +142,10 @@ refresh_cpu_stats(struct cpu_stats *cpu_stats, size_t core_count) while ((read = getline(&line, &len, fp)) != -1 && core <= core_count) { if (strncmp(line, "cpu", sizeof("cpu") - 1) == 0) { - if (!parse_proc_stat_line(line, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, - &guestnice)) { + if (!parse_proc_stat_line( + line, &user, &nice, &system, &idle, &iowait, &irq, &softirq, + &steal, &guest, &guestnice)) + { LOG_ERR("unable to parse /proc/stat line"); goto exit; } @@ -238,11 +250,15 @@ cpu_new(uint16_t interval, struct particle *template) p->interval = interval; p->core_count = nb_cores; - p->cpu_stats.prev_cores_nidle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_nidle)); - p->cpu_stats.prev_cores_idle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_idle)); + p->cpu_stats.prev_cores_nidle = calloc( + nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_nidle)); + p->cpu_stats.prev_cores_idle = calloc( + nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_idle)); - p->cpu_stats.cur_cores_nidle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_nidle)); - p->cpu_stats.cur_cores_idle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_idle)); + p->cpu_stats.cur_cores_nidle = calloc( + nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_nidle)); + p->cpu_stats.cur_cores_idle = calloc( + nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_idle)); struct module *mod = module_common_new(); mod->private = p; @@ -259,17 +275,20 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *interval = yml_get_value(node, "poll-interval"); const struct yml_node *c = yml_get_value(node, "content"); - return cpu_new(interval == NULL ? min_poll_interval : yml_value_as_int(interval), conf_to_particle(c, inherited)); + return cpu_new( + interval == NULL ? SMALLEST_INTERVAL : yml_value_as_int(interval), + conf_to_particle(c, inherited)); } static bool -conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node) +conf_verify_interval(keychain_t *chain, const struct yml_node *node) { if (!conf_verify_unsigned(chain, node)) return false; - if (yml_value_as_int(node) < min_poll_interval) { - LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval); + if (yml_value_as_int(node) < SMALLEST_INTERVAL) { + LOG_ERR("%s: interval value cannot be less than %d ms", + conf_err_prefix(chain, node), SMALLEST_INTERVAL); return false; } @@ -280,7 +299,7 @@ static bool verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { - {"poll-interval", false, &conf_verify_poll_interval}, + {"poll-interval", false, &conf_verify_interval}, MODULE_COMMON_ATTRS, }; diff --git a/modules/dbus.h b/modules/dbus.h deleted file mode 100644 index 6517cef..0000000 --- a/modules/dbus.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// This header provides an generic interface for different versions of -// systemd-sdbus. - -#if defined(HAVE_LIBSYSTEMD) -#include -#elif defined(HAVE_LIBELOGIND) -#include -#elif defined(HAVE_BASU) -#include -#endif - diff --git a/modules/disk-io.c b/modules/disk-io.c index c33cbef..4ce665f 100644 --- a/modules/disk-io.c +++ b/modules/disk-io.c @@ -1,23 +1,22 @@ -#include #include #include #include #include #include +#include #include -#define LOG_MODULE "disk-io" -#define LOG_ENABLE_DBG 0 -#include "../log.h" - +#include "../particles/dynlist.h" #include "../bar/bar.h" #include "../config-verify.h" #include "../config.h" -#include "../particles/dynlist.h" +#include "../log.h" #include "../plugin.h" -static const long min_poll_interval = 250; +#define LOG_MODULE "disk-io" +#define LOG_ENABLE_DBG 0 +#define SMALLEST_INTERVAL 500 struct device_stats { char *name; @@ -34,8 +33,7 @@ struct device_stats { bool exists; }; -struct private -{ +struct private { struct particle *label; uint16_t interval; tll(struct device_stats *) devices; @@ -64,7 +62,7 @@ is_disk(char const *name) return found; } -static struct device_stats * +static struct device_stats* new_device_stats(char const *name) { struct device_stats *dev = malloc(sizeof(*dev)); @@ -85,7 +83,9 @@ destroy(struct module *mod) { struct private *m = mod->private; m->label->destroy(m->label); - tll_foreach(m->devices, it) { free_device_stats(it->item); } + tll_foreach(m->devices, it) { + free_device_stats(it->item); + } tll_free(m->devices); free(m); module_default_destroy(mod); @@ -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; @@ -125,11 +125,13 @@ refresh_device_stats(struct private *m) * The 'exists' variable is what keep tracks of whether or not /proc/diskstats * is still reporting the device (i.e., it is still connected). */ - tll_foreach(m->devices, it) { it->item->exists = false; } + tll_foreach(m->devices, it) { + it->item->exists = false; + } 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; @@ -153,23 +155,25 @@ refresh_device_stats(struct private *m) uint32_t completed_flushes = 0; uint32_t flushing_time = 0; if (!sscanf(line, - " %" SCNu8 " %" SCNu8 " %ms %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 " %" SCNu32 " %" SCNu32 - " %" SCNu64 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 - " %" SCNu32 " %" SCNu32 " %" SCNu32, - &major_number, &minor_number, &device_name, &completed_reads, &merged_reads, §ors_read, - &reading_time, &completed_writes, &merged_writes, §ors_written, &writting_time, - &ios_in_progress, &io_time, &io_weighted_time, &completed_discards, &merged_discards, - §ors_discarded, &discarding_time, &completed_flushes, &flushing_time)) { + " %" SCNu8 " %" SCNu8 " %ms %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 + " %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 " %" SCNu32 " %" SCNu32 + " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 + " %" SCNu32, + &major_number, &minor_number, &device_name, &completed_reads, + &merged_reads, §ors_read, &reading_time, &completed_writes, + &merged_writes, §ors_written, &writting_time, &ios_in_progress, + &io_time, &io_weighted_time, &completed_discards, &merged_discards, + §ors_discarded, &discarding_time, &completed_flushes, &flushing_time)) + { LOG_ERR("unable to parse /proc/diskstats line"); free(device_name); goto exit; } bool found = false; - tll_foreach(m->devices, it) - { + tll_foreach(m->devices, it) { struct device_stats *dev = it->item; - if (strcmp(dev->name, device_name) == 0) { + if (strcmp(dev->name, device_name) == 0){ dev->prev_sectors_read = dev->cur_sectors_read; dev->prev_sectors_written = dev->cur_sectors_written; dev->ios_in_progress = ios_in_progress; @@ -195,9 +199,8 @@ refresh_device_stats(struct private *m) free(device_name); } - tll_foreach(m->devices, it) - { - if (!it->item->exists) { + tll_foreach(m->devices, it) { + if (!it->item->exists){ free_device_stats(it->item); tll_remove(m->devices, it); } @@ -217,13 +220,12 @@ content(struct module *mod) mtx_lock(&mod->lock); struct exposable *tag_parts[p->devices.length + 1]; int i = 0; - tll_foreach(p->devices, it) - { + tll_foreach(p->devices, it) { struct device_stats *dev = it->item; uint64_t bytes_read = (dev->cur_sectors_read - dev->prev_sectors_read) * 512; uint64_t bytes_written = (dev->cur_sectors_written - dev->prev_sectors_written) * 512; - if (dev->is_disk) { + if (dev->is_disk){ total_bytes_read += bytes_read; total_bytes_written += bytes_written; total_ios_in_progress += dev->ios_in_progress; @@ -308,21 +310,24 @@ disk_io_new(uint16_t interval, struct particle *label) static struct module * from_conf(const struct yml_node *node, struct conf_inherit inherited) { - const struct yml_node *interval = yml_get_value(node, "poll-interval"); + const struct yml_node *interval = yml_get_value(node, "interval"); const struct yml_node *c = yml_get_value(node, "content"); - return disk_io_new(interval == NULL ? min_poll_interval : yml_value_as_int(interval), - conf_to_particle(c, inherited)); + return disk_io_new( + interval == NULL ? SMALLEST_INTERVAL : yml_value_as_int(interval), + conf_to_particle(c, inherited)); } static bool -conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node) +conf_verify_interval(keychain_t *chain, const struct yml_node *node) { if (!conf_verify_unsigned(chain, node)) return false; - if (yml_value_as_int(node) < min_poll_interval) { - LOG_ERR("%s: poll-interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval); + if (yml_value_as_int(node) < SMALLEST_INTERVAL) { + LOG_ERR( + "%s: interval value cannot be less than %d ms", + conf_err_prefix(chain, node), SMALLEST_INTERVAL); return false; } @@ -333,7 +338,7 @@ static bool verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { - {"poll-interval", false, &conf_verify_poll_interval}, + {"interval", false, &conf_verify_interval}, MODULE_COMMON_ATTRS, }; diff --git a/modules/dwl.c b/modules/dwl.c index 3b1bdcc..00b4cb8 100644 --- a/modules/dwl.c +++ b/modules/dwl.c @@ -18,7 +18,6 @@ struct dwl_tag { int id; - char *name; bool selected; bool empty; bool urgent; @@ -35,7 +34,6 @@ struct private /* dwl data */ char *title; - char *appid; bool fullscreen; bool floating; bool selmon; @@ -46,7 +44,6 @@ struct private enum LINE_MODE { LINE_MODE_0, LINE_MODE_TITLE, - LINE_MODE_APPID, LINE_MODE_FULLSCREEN, LINE_MODE_FLOATING, LINE_MODE_SELMON, @@ -54,20 +51,13 @@ enum LINE_MODE { LINE_MODE_LAYOUT, }; -static void -free_dwl_tag(struct dwl_tag *tag) -{ - free(tag->name); - free(tag); -} - static void destroy(struct module *module) { struct private *private = module->private; private->label->destroy(private->label); - tll_free_and_free(private->tags, free_dwl_tag); + tll_free_and_free(private->tags, free); free(private->dwl_info_filename); free(private->title); free(private->layout); @@ -96,18 +86,16 @@ content(struct module *module) struct tag_set tags = { .tags = (struct tag*[]){ tag_new_string(module, "title", private->title), - tag_new_string(module, "appid", private->appid), tag_new_bool(module, "fullscreen", private->fullscreen), tag_new_bool(module, "floating", private->floating), tag_new_bool(module, "selmon", private->selmon), tag_new_string(module, "layout", private->layout), tag_new_int(module, "id", it->item->id), - tag_new_string(module, "name", it->item->name), tag_new_bool(module, "selected", it->item->selected), tag_new_bool(module, "empty", it->item->empty), tag_new_bool(module, "urgent", it->item->urgent), }, - .count = 11, + .count = 9, }; exposable[i++] = private->label->instantiate(private->label, &tags); tag_set_destroy(&tags); @@ -117,18 +105,16 @@ content(struct module *module) struct tag_set tags = { .tags = (struct tag*[]){ tag_new_string(module, "title", private->title), - tag_new_string(module, "appid", private->appid), tag_new_bool(module, "fullscreen", private->fullscreen), tag_new_bool(module, "floating", private->floating), tag_new_bool(module, "selmon", private->selmon), tag_new_string(module, "layout", private->layout), tag_new_int(module, "id", 0), - tag_new_string(module, "name", "0"), tag_new_bool(module, "selected", false), tag_new_bool(module, "empty", true), tag_new_bool(module, "urgent", false), }, - .count = 11, + .count = 9, }; exposable[i++] = private->label->instantiate(private->label, &tags); tag_set_destroy(&tags); @@ -138,7 +124,7 @@ content(struct module *module) } static struct dwl_tag * -dwl_tag_from_id(struct private *private, uint32_t id) +dwl_tag_find_or_create(struct private *private, uint32_t id) { tll_foreach(private->tags, it) { @@ -146,8 +132,11 @@ dwl_tag_from_id(struct private *private, uint32_t id) return it->item; } - assert(false); /* unreachable */ - return NULL; + /* No need to order the tag, `print_status` from dwl already orders tags */ + struct dwl_tag *dwl_tag = calloc(1, sizeof(struct dwl_tag)); + dwl_tag->id = id; + tll_push_back(private->tags, dwl_tag); + return dwl_tag; } static void @@ -179,21 +168,9 @@ process_line(char *line, struct module *module) } /* action */ else if (index == 2) { - if (strcmp(string, "title") == 0) { + if (strcmp(string, "title") == 0) line_mode = LINE_MODE_TITLE; - /* Update the title here, to avoid allocate and free memory on - * every iteration (the line is separated by spaces, then we - * join it again) a bit suboptimal, isn't it?) */ - free(private->title); - private->title = strdup(save_pointer); - break; - } else if (strcmp(string, "appid") == 0) { - line_mode = LINE_MODE_APPID; - /* Update the appid here, same as the title. */ - free(private->appid); - private->appid = strdup(save_pointer); - break; - } else if (strcmp(string, "fullscreen") == 0) + else if (strcmp(string, "fullscreen") == 0) line_mode = LINE_MODE_FULLSCREEN; else if (strcmp(string, "floating") == 0) line_mode = LINE_MODE_FLOATING; @@ -231,12 +208,12 @@ 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); - struct dwl_tag *dwl_tag = dwl_tag_from_id(private, id); + struct dwl_tag *dwl_tag = dwl_tag_find_or_create(private, id); dwl_tag->selected = mask & selected; dwl_tag->empty = !(mask & occupied); dwl_tag->urgent = mask & urgent; @@ -245,20 +222,17 @@ process_line(char *line, struct module *module) } else switch (line_mode) { case LINE_MODE_TITLE: - case LINE_MODE_APPID: - assert(false); /* unreachable */ + free(private->title); + private->title = strdup(string); break; case LINE_MODE_FULLSCREEN: - private - ->fullscreen = (strcmp(string, "0") != 0); + private->fullscreen = (strcmp(string, "0") != 0); break; case LINE_MODE_FLOATING: - private - ->floating = (strcmp(string, "0") != 0); + private->floating = (strcmp(string, "0") != 0); break; case LINE_MODE_SELMON: - private - ->selmon = (strcmp(string, "0") != 0); + private->selmon = (strcmp(string, "0") != 0); break; case LINE_MODE_LAYOUT: free(private->layout); @@ -330,7 +304,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); @@ -441,29 +415,13 @@ run(struct module *module) } static struct module * -dwl_new(struct particle *label, int number_of_tags, struct yml_node const *name_of_tags, char const *dwl_info_filename) +dwl_new(struct particle *label, int number_of_tags, char const *dwl_info_filename) { struct private *private = calloc(1, sizeof(struct private)); private->label = label; private->number_of_tags = number_of_tags; private->dwl_info_filename = strdup(dwl_info_filename); - struct yml_list_iter list = {0}; - if (name_of_tags) - list = yml_list_iter(name_of_tags); - - for (int i = 1; i <= number_of_tags; i++) { - struct dwl_tag *dwl_tag = calloc(1, sizeof(struct dwl_tag)); - dwl_tag->id = i; - if (list.node) { - dwl_tag->name = strdup(yml_value_as_string(list.node)); - yml_list_next(&list); - } else if (asprintf(&dwl_tag->name, "%d", i) < 0) { - LOG_ERRNO("asprintf"); - } - tll_push_back(private->tags, dwl_tag); - } - struct module *module = module_common_new(); module->private = private; module->run = &run; @@ -479,30 +437,18 @@ from_conf(struct yml_node const *node, struct conf_inherit inherited) { struct yml_node const *content = yml_get_value(node, "content"); struct yml_node const *number_of_tags = yml_get_value(node, "number-of-tags"); - struct yml_node const *name_of_tags = yml_get_value(node, "name-of-tags"); struct yml_node const *dwl_info_filename = yml_get_value(node, "dwl-info-filename"); - return dwl_new(conf_to_particle(content, inherited), yml_value_as_int(number_of_tags), name_of_tags, + return dwl_new(conf_to_particle(content, inherited), yml_value_as_int(number_of_tags), yml_value_as_string(dwl_info_filename)); } -static bool -verify_names(keychain_t *keychain, const struct yml_node *node) -{ - if (!yml_is_list(node)) { - LOG_ERR("%s: %s is not a list", conf_err_prefix(keychain, node), yml_value_as_string(node)); - return false; - } - return conf_verify_list(keychain, node, &conf_verify_string); -} - static bool verify_conf(keychain_t *keychain, struct yml_node const *node) { static struct attr_info const attrs[] = { {"number-of-tags", true, &conf_verify_unsigned}, - {"name-of-tags", false, &verify_names}, {"dwl-info-filename", true, &conf_verify_string}, MODULE_COMMON_ATTRS, }; @@ -512,19 +458,10 @@ verify_conf(keychain_t *keychain, struct yml_node const *node) /* No need to check whether is `number_of_tags` is a int * because `conf_verify_unsigned` already did it */ - struct yml_node const *ntags_key = yml_get_key(node, "number-of-tags"); + struct yml_node const *key = yml_get_key(node, "number-of-tags"); struct yml_node const *value = yml_get_value(node, "number-of-tags"); - int number_of_tags = yml_value_as_int(value); - if (number_of_tags == 0) { - LOG_ERR("%s: %s must not be 0", conf_err_prefix(keychain, ntags_key), yml_value_as_string(ntags_key)); - return false; - } - - struct yml_node const *key = yml_get_key(node, "name-of-tags"); - value = yml_get_value(node, "name-of-tags"); - if (value && yml_list_length(value) != number_of_tags) { - LOG_ERR("%s: %s must have the same number of elements that %s", conf_err_prefix(keychain, key), - yml_value_as_string(key), yml_value_as_string(ntags_key)); + if (yml_value_as_int(value) == 0) { + LOG_ERR("%s: %s must not be 0", conf_err_prefix(keychain, key), yml_value_as_string(key)); return false; } diff --git a/modules/foreign-toplevel.c b/modules/foreign-toplevel.c index ccd6d5b..d454a39 100644 --- a/modules/foreign-toplevel.c +++ b/modules/foreign-toplevel.c @@ -1,7 +1,7 @@ -#include -#include #include #include +#include +#include #include @@ -11,8 +11,8 @@ #define LOG_MODULE "foreign-toplevel" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../particles/dynlist.h" #include "../plugin.h" +#include "../particles/dynlist.h" #include "wlr-foreign-toplevel-management-unstable-v1.h" #include "xdg-output-unstable-v1.h" @@ -46,8 +46,7 @@ struct toplevel { tll(const struct output *) outputs; }; -struct private -{ +struct private { struct particle *template; uint32_t manager_wl_name; struct zwlr_foreign_toplevel_manager_v1 *manager; @@ -111,8 +110,7 @@ content(struct module *mod) const char *current_output = mod->bar->output_name(mod->bar); - tll_foreach(m->toplevels, it) - { + tll_foreach(m->toplevels, it) { const struct toplevel *top = &it->item; bool show = false; @@ -120,10 +118,11 @@ content(struct module *mod) if (m->all_monitors) show = true; else if (current_output != NULL) { - tll_foreach(top->outputs, it2) - { + tll_foreach(top->outputs, it2) { const struct output *output = it2->item; - if (output->name != NULL && strcmp(output->name, current_output) == 0) { + if (output->name != NULL && + strcmp(output->name, current_output) == 0) + { show = true; break; } @@ -159,18 +158,22 @@ verify_iface_version(const char *iface, uint32_t version, uint32_t wanted) if (version >= wanted) return true; - LOG_ERR("%s: need interface version %u, but compositor only implements %u", iface, wanted, version); + LOG_ERR("%s: need interface version %u, but compositor only implements %u", + iface, wanted, version); return false; } static void -xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) +xdg_output_handle_logical_position(void *data, + struct zxdg_output_v1 *xdg_output, + int32_t x, int32_t y) { } static void -xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) +xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, + int32_t width, int32_t height) { } @@ -180,7 +183,8 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) } static void -xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name) +xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, + const char *name) { struct output *output = data; struct module *mod = output->mod; @@ -194,7 +198,8 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char } static void -xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description) +xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, + const char *description) { } @@ -233,7 +238,8 @@ app_id(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, const char *a } static void -output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *wl_output) +output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, + struct wl_output *wl_output) { struct toplevel *top = data; struct module *mod = top->mod; @@ -242,8 +248,7 @@ output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct mtx_lock(&mod->lock); const struct output *output = NULL; - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { if (it->item.wl_output == wl_output) { output = &it->item; break; @@ -255,8 +260,7 @@ output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct goto out; } - tll_foreach(top->outputs, it) - { + tll_foreach(top->outputs, it) { if (it->item == output) { LOG_ERR("output-enter event on output we're already on"); goto out; @@ -271,7 +275,8 @@ out: } static void -output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *wl_output) +output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, + struct wl_output *wl_output) { struct toplevel *top = data; struct module *mod = top->mod; @@ -280,8 +285,7 @@ output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct mtx_lock(&mod->lock); const struct output *output = NULL; - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { if (it->item.wl_output == wl_output) { output = &it->item; break; @@ -294,10 +298,10 @@ output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct } bool output_removed = false; - tll_foreach(top->outputs, it) - { + tll_foreach(top->outputs, it) { if (it->item == output) { - LOG_DBG("unmapped: %s:%s from %s", top->app_id, top->title, output->name); + LOG_DBG("unmapped: %s:%s from %s", + top->app_id, top->title, output->name); tll_remove(top->outputs, it); output_removed = true; break; @@ -314,7 +318,8 @@ out: } static void -state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_array *states) +state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, + struct wl_array *states) { struct toplevel *top = data; @@ -324,21 +329,12 @@ state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_arra bool fullscreen = false; enum zwlr_foreign_toplevel_handle_v1_state *state; - wl_array_for_each(state, states) - { + wl_array_for_each(state, states) { switch (*state) { - case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED: - maximized = true; - break; - case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED: - minimized = true; - break; - case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED: - activated = true; - break; - case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN: - fullscreen = true; - break; + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED: maximized = true; break; + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED: minimized = true; break; + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED: activated = true; break; + case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN: fullscreen = true; break; } } @@ -368,8 +364,7 @@ closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) struct private *m = mod->private; mtx_lock(&mod->lock); - tll_foreach(m->toplevels, it) - { + tll_foreach(m->toplevels, it) { if (it->item.handle == handle) { toplevel_free(top); tll_remove(m->toplevels, it); @@ -383,7 +378,9 @@ closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle) } static void -parent(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct zwlr_foreign_toplevel_handle_v1 *parent) +parent(void *data, + struct zwlr_foreign_toplevel_handle_v1 *handle, + struct zwlr_foreign_toplevel_handle_v1 *parent) { } @@ -399,7 +396,9 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener toplevel_listener = }; static void -toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager, struct zwlr_foreign_toplevel_handle_v1 *handle) +toplevel(void *data, + struct zwlr_foreign_toplevel_manager_v1 *manager, + struct zwlr_foreign_toplevel_handle_v1 *handle) { struct module *mod = data; struct private *m = mod->private; @@ -413,13 +412,15 @@ toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager, struct zw { tll_push_back(m->toplevels, toplevel); - zwlr_foreign_toplevel_handle_v1_add_listener(handle, &toplevel_listener, &tll_back(m->toplevels)); + zwlr_foreign_toplevel_handle_v1_add_listener( + handle, &toplevel_listener, &tll_back(m->toplevels)); } mtx_unlock(&mod->lock); } static void -finished(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager) +finished(void *data, + struct zwlr_foreign_toplevel_manager_v1 *manager) { struct module *mod = data; struct private *m = mod->private; @@ -444,12 +445,15 @@ output_xdg_output(struct output *output) if (output->xdg_output != NULL) return; - output->xdg_output = zxdg_output_manager_v1_get_xdg_output(m->xdg_output_manager, output->wl_output); - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + output->xdg_output = zxdg_output_manager_v1_get_xdg_output( + m->xdg_output_manager, output->wl_output); + zxdg_output_v1_add_listener( + output->xdg_output, &xdg_output_listener, output); } static void -handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) +handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { struct module *mod = data; struct private *m = mod->private; @@ -469,7 +473,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha struct output output = { .mod = mod, .wl_name = name, - .wl_output = wl_registry_bind(registry, name, &wl_output_interface, required), + .wl_output = wl_registry_bind( + registry, name, &wl_output_interface, required), }; mtx_lock(&mod->lock); @@ -483,10 +488,12 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - m->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, required); + m->xdg_output_manager = wl_registry_bind( + registry, name, &zxdg_output_manager_v1_interface, required); mtx_lock(&mod->lock); - tll_foreach(m->outputs, it) output_xdg_output(&it->item); + tll_foreach(m->outputs, it) + output_xdg_output(&it->item); mtx_unlock(&mod->lock); } } @@ -499,19 +506,16 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) mtx_lock(&mod->lock); - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { const struct output *output = &it->item; if (output->wl_name == name) { /* Loop all toplevels */ - tll_foreach(m->toplevels, it2) - { + tll_foreach(m->toplevels, it2) { /* And remove this output from their list of tracked * outputs */ - tll_foreach(it2->item.outputs, it3) - { + tll_foreach(it2->item.outputs, it3) { if (it3->item == output) { tll_remove(it2->item.outputs, it3); break; @@ -547,8 +551,9 @@ run(struct module *mod) goto out; } - if ((registry = wl_display_get_registry(display)) == NULL - || wl_registry_add_listener(registry, ®istry_listener, mod) != 0) { + if ((registry = wl_display_get_registry(display)) == NULL || + wl_registry_add_listener(registry, ®istry_listener, mod) != 0) + { LOG_ERR("failed to get Wayland registry"); goto out; } @@ -556,14 +561,18 @@ run(struct module *mod) wl_display_roundtrip(display); if (m->manager_wl_name == 0) { - LOG_ERR("compositor does not implement the foreign-toplevel-manager interface"); + LOG_ERR( + "compositor does not implement the foreign-toplevel-manager interface"); goto out; } - m->manager = wl_registry_bind(registry, m->manager_wl_name, &zwlr_foreign_toplevel_manager_v1_interface, - required_manager_interface_version); + m->manager = wl_registry_bind( + registry, m->manager_wl_name, + &zwlr_foreign_toplevel_manager_v1_interface, + required_manager_interface_version); - zwlr_foreign_toplevel_manager_v1_add_listener(m->manager, &manager_listener, mod); + zwlr_foreign_toplevel_manager_v1_add_listener( + m->manager, &manager_listener, mod); while (true) { wl_display_flush(display); @@ -597,14 +606,12 @@ run(struct module *mod) } out: - tll_foreach(m->toplevels, it) - { + tll_foreach(m->toplevels, it) { toplevel_free(&it->item); tll_remove(m->toplevels, it); } - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { output_free(&it->item); tll_remove(m->outputs, it); } @@ -642,7 +649,9 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *all_monitors = yml_get_value(node, "all-monitors"); - return ftop_new(conf_to_particle(c, inherited), all_monitors != NULL ? yml_value_as_bool(all_monitors) : false); + return ftop_new( + conf_to_particle(c, inherited), + all_monitors != NULL ? yml_value_as_bool(all_monitors) : false); } static bool diff --git a/modules/i3-common.c b/modules/i3-common.c index 957a4d2..a0769f2 100644 --- a/modules/i3-common.c +++ b/modules/i3-common.c @@ -1,15 +1,15 @@ #include "i3-common.h" -#include #include #include #include +#include #include #if defined(ENABLE_X11) -#include -#include + #include + #include #endif #include @@ -19,7 +19,7 @@ #include "../log.h" #if defined(ENABLE_X11) -#include "../xcb.h" + #include "../xcb.h" #endif #include "i3-ipc.h" @@ -41,11 +41,14 @@ get_socket_address_x11(struct sockaddr_un *addr) xcb_atom_t atom = get_atom(conn, "I3_SOCKET_PATH"); assert(atom != XCB_ATOM_NONE); - xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(conn, false, screen->root, atom, - XCB_GET_PROPERTY_TYPE_ANY, 0, sizeof(addr->sun_path)); + xcb_get_property_cookie_t cookie + = xcb_get_property_unchecked( + conn, false, screen->root, atom, + XCB_GET_PROPERTY_TYPE_ANY, 0, sizeof(addr->sun_path)); xcb_generic_error_t *err = NULL; - xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, &err); + xcb_get_property_reply_t *reply = + xcb_get_property_reply(conn, cookie, &err); bool ret = false; if (err != NULL) { @@ -99,7 +102,11 @@ bool i3_send_pkg(int sock, int cmd, char *data) { const size_t size = data != NULL ? strlen(data) : 0; - const i3_ipc_header_t hdr = {.magic = I3_IPC_MAGIC, .size = size, .type = cmd}; + const i3_ipc_header_t hdr = { + .magic = I3_IPC_MAGIC, + .size = size, + .type = cmd + }; if (write(sock, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) return false; @@ -113,7 +120,8 @@ i3_send_pkg(int sock, int cmd, char *data) } bool -i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void *data) +i3_receive_loop(int abort_fd, int sock, + const struct i3_ipc_callbacks *cbs, void *data) { /* Initial reply typically requires a couple of KB. But we often * need more later. For example, switching workspaces can result @@ -125,7 +133,10 @@ i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void bool err = false; while (!err) { - struct pollfd fds[] = {{.fd = abort_fd, .events = POLLIN}, {.fd = sock, .events = POLLIN}}; + struct pollfd fds[] = { + {.fd = abort_fd, .events = POLLIN}, + {.fd = sock, .events = POLLIN} + }; int res = poll(fds, 2, -1); if (res <= 0) { @@ -148,11 +159,13 @@ i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void /* Grow receive buffer, if necessary */ if (buf_idx == reply_buf_size) { - LOG_DBG("growing reply buffer: %zu -> %zu", reply_buf_size, reply_buf_size * 2); + LOG_DBG("growing reply buffer: %zu -> %zu", + reply_buf_size, reply_buf_size * 2); char *new_buf = realloc(buf, reply_buf_size * 2); if (new_buf == NULL) { - LOG_ERR("failed to grow reply buffer from %zu to %zu bytes", reply_buf_size, reply_buf_size * 2); + LOG_ERR("failed to grow reply buffer from %zu to %zu bytes", + reply_buf_size, reply_buf_size * 2); err = true; break; } @@ -175,8 +188,10 @@ i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void while (!err && buf_idx >= sizeof(i3_ipc_header_t)) { const i3_ipc_header_t *hdr = (const i3_ipc_header_t *)buf; if (strncmp(hdr->magic, I3_IPC_MAGIC, sizeof(hdr->magic)) != 0) { - LOG_ERR("i3 IPC header magic mismatch: expected \"%.*s\", got \"%.*s\"", (int)sizeof(hdr->magic), - I3_IPC_MAGIC, (int)sizeof(hdr->magic), hdr->magic); + LOG_ERR( + "i3 IPC header magic mismatch: expected \"%.*s\", got \"%.*s\"", + (int)sizeof(hdr->magic), I3_IPC_MAGIC, + (int)sizeof(hdr->magic), hdr->magic); err = true; break; @@ -195,10 +210,10 @@ i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void char json_str[hdr->size + 1]; memcpy(json_str, &buf[sizeof(*hdr)], hdr->size); json_str[hdr->size] = '\0'; - // printf("raw: %s\n", json_str); + //printf("raw: %s\n", json_str); LOG_DBG("raw: %s\n", json_str); - // json_tokener *tokener = json_tokener_new(); + //json_tokener *tokener = json_tokener_new(); struct json_object *json = json_tokener_parse(json_str); if (json == NULL) { LOG_ERR("failed to parse json"); @@ -247,13 +262,13 @@ i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void break; #endif /* Sway extensions */ - case 100: /* IPC_GET_INPUTS */ + case 100: /* IPC_GET_INPUTS */ pkt_handler = cbs->reply_inputs; break; - /* - * Events - */ + /* + * Events + */ case I3_IPC_EVENT_WORKSPACE: pkt_handler = cbs->event_workspace; @@ -280,7 +295,7 @@ i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void pkt_handler = cbs->event_tick; break; - /* Sway extensions */ + /* Sway extensions */ #define SWAY_IPC_EVENT_INPUT ((1u << 31) | 21) case SWAY_IPC_EVENT_INPUT: pkt_handler = cbs->event_input; diff --git a/modules/i3-common.h b/modules/i3-common.h index 6ba6721..0cbfa3e 100644 --- a/modules/i3-common.h +++ b/modules/i3-common.h @@ -2,8 +2,8 @@ #include -#include #include +#include #include #include @@ -43,4 +43,6 @@ struct i3_ipc_callbacks { i3_ipc_callback_t event_input; }; -bool i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *callbacks, void *data); +bool i3_receive_loop( + int abort_fd, int sock, + const struct i3_ipc_callbacks *callbacks, void *data); diff --git a/modules/i3.c b/modules/i3.c index cbdafaf..f0aa137 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -1,27 +1,27 @@ -#include #include #include -#include #include +#include +#include -#include #include +#include #include #define LOG_MODULE "i3" #define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../particles/dynlist.h" #include "../plugin.h" -#include "i3-common.h" #include "i3-ipc.h" +#include "i3-common.h" -enum sort_mode { SORT_NONE, SORT_NATIVE, SORT_ASCENDING, SORT_DESCENDING }; +enum sort_mode {SORT_NONE, SORT_ASCENDING, SORT_DESCENDING}; struct ws_content { char *name; @@ -48,8 +48,7 @@ struct workspace { } window; }; -struct private -{ +struct private { int left_spacing; int right_spacing; @@ -106,8 +105,10 @@ workspace_from_json(const struct json_object *json, struct workspace *ws) { /* Always present */ struct json_object *id, *name, *output; - if (!json_object_object_get_ex(json, "id", &id) || !json_object_object_get_ex(json, "name", &name) - || !json_object_object_get_ex(json, "output", &output)) { + if (!json_object_object_get_ex(json, "id", &id) || + !json_object_object_get_ex(json, "name", &name) || + !json_object_object_get_ex(json, "output", &output)) + { LOG_ERR("workspace reply/event without 'name' and/or 'output' " "properties"); return false; @@ -125,12 +126,14 @@ workspace_from_json(const struct json_object *json, struct workspace *ws) const char *name_as_string = json_object_get_string(name); - const size_t node_count = focus != NULL ? json_object_array_length(focus) : 0; + const size_t node_count = focus != NULL + ? json_object_array_length(focus) + : 0; const bool is_empty = node_count == 0; int name_as_int = workspace_name_as_int(name_as_string); - *ws = (struct workspace){ + *ws = (struct workspace) { .id = json_object_get_int(id), .name = strdup(name_as_string), .name_as_int = name_as_int, @@ -146,31 +149,19 @@ workspace_from_json(const struct json_object *json, struct workspace *ws) return true; } -static void -workspace_free_persistent(struct workspace *ws) -{ - free(ws->output); - ws->output = NULL; - free(ws->window.title); - ws->window.title = NULL; - free(ws->window.application); - ws->window.application = NULL; - ws->id = -1; -} - static void workspace_free(struct workspace *ws) { - workspace_free_persistent(ws); - free(ws->name); - ws->name = NULL; + free(ws->name); ws->name = NULL; + free(ws->output); ws->output = NULL; + free(ws->window.title); ws->window.title = NULL; + free(ws->window.application); ws->window.application = NULL; } static void workspaces_free(struct private *m, bool free_persistent) { - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { if (free_persistent || !it->item.persistent) { workspace_free(&it->item); tll_remove(m->workspaces, it); @@ -178,6 +169,7 @@ workspaces_free(struct private *m, bool free_persistent) } } + static void workspace_add(struct private *m, struct workspace ws) { @@ -186,26 +178,9 @@ workspace_add(struct private *m, struct workspace ws) tll_push_back(m->workspaces, ws); return; - case SORT_NATIVE: - if (ws.name_as_int >= 0) { - tll_foreach(m->workspaces, it) - { - if (it->item.name_as_int < 0) - continue; - if (it->item.name_as_int > ws.name_as_int) { - tll_insert_before(m->workspaces, it, ws); - return; - } - } - }; - - tll_push_back(m->workspaces, ws); - return; - case SORT_ASCENDING: if (ws.name_as_int >= 0) { - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { if (it->item.name_as_int < 0) continue; if (it->item.name_as_int > ws.name_as_int) { @@ -214,9 +189,10 @@ workspace_add(struct private *m, struct workspace ws) } } } else { - tll_foreach(m->workspaces, it) - { - if (strcoll(it->item.name, ws.name) > 0 || it->item.name_as_int >= 0) { + tll_foreach(m->workspaces, it) { + if (strcoll(it->item.name, ws.name) > 0 || + it->item.name_as_int >= 0) + { tll_insert_before(m->workspaces, it, ws); return; } @@ -227,16 +203,14 @@ workspace_add(struct private *m, struct workspace ws) case SORT_DESCENDING: if (ws.name_as_int >= 0) { - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { if (it->item.name_as_int < ws.name_as_int) { tll_insert_before(m->workspaces, it, ws); return; } } } else { - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { if (it->item.name_as_int >= 0) continue; if (strcoll(it->item.name, ws.name) < 0) { @@ -253,8 +227,7 @@ workspace_add(struct private *m, struct workspace ws) static void workspace_del(struct private *m, int id) { - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { struct workspace *ws = &it->item; if (ws->id != id) @@ -269,8 +242,7 @@ workspace_del(struct private *m, int id) static struct workspace * workspace_lookup(struct private *m, int id) { - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { struct workspace *ws = &it->item; if (ws->id == id) return ws; @@ -278,18 +250,6 @@ workspace_lookup(struct private *m, int id) return NULL; } -static struct workspace * -workspace_lookup_by_name(struct private *m, const char *name) -{ - tll_foreach(m->workspaces, it) - { - struct workspace *ws = &it->item; - if (strcmp(ws->name, name) == 0) - return ws; - } - return NULL; -} - static bool handle_get_version_reply(int sock, int type, const struct json_object *json, void *_m) { @@ -330,31 +290,6 @@ workspace_update_or_add(struct private *m, const struct json_object *ws_json) const int id = json_object_get_int(_id); struct workspace *already_exists = workspace_lookup(m, id); - if (already_exists == NULL) { - /* - * No workspace with this ID. - * - * Try looking it up again, but this time using the name. If - * we get a match, check if it’s an empty, persistent - * workspace, and if so, use it. - * - * This is necessary, since empty, persistent workspaces don’t - * exist in the i3/Sway server, and thus we don’t _have_ an - * ID. - */ - struct json_object *_name; - if (json_object_object_get_ex(ws_json, "name", &_name)) { - const char *name = json_object_get_string(_name); - if (name != NULL) { - struct workspace *maybe_persistent = workspace_lookup_by_name(m, name); - - if (maybe_persistent != NULL && maybe_persistent->persistent && maybe_persistent->id < 0) { - already_exists = maybe_persistent; - } - } - } - } - if (already_exists != NULL) { bool persistent = already_exists->persistent; assert(persistent); @@ -421,12 +356,11 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void bool is_rename = strcmp(change_str, "rename") == 0; bool is_move = strcmp(change_str, "move") == 0; bool is_urgent = strcmp(change_str, "urgent") == 0; - bool is_reload = strcmp(change_str, "reload") == 0; struct json_object *current, *_current_id; - if ((!json_object_object_get_ex(json, "current", ¤t) - || !json_object_object_get_ex(current, "id", &_current_id)) - && !is_reload) { + if (!json_object_object_get_ex(json, "current", ¤t) || + !json_object_object_get_ex(current, "id", &_current_id)) + { LOG_ERR("workspace event without 'current' and/or 'id' properties"); return false; } @@ -447,15 +381,18 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void if (!ws->persistent) workspace_del(m, current_id); else { - workspace_free_persistent(ws); + workspace_free(ws); ws->empty = true; + assert(ws->persistent); } } else if (is_focused) { struct json_object *old, *_old_id, *urgent; - if (!json_object_object_get_ex(json, "old", &old) || !json_object_object_get_ex(old, "id", &_old_id) - || !json_object_object_get_ex(current, "urgent", &urgent)) { + if (!json_object_object_get_ex(json, "old", &old) || + !json_object_object_get_ex(old, "id", &_old_id) || + !json_object_object_get_ex(current, "urgent", &urgent)) + { LOG_ERR("workspace 'focused' event without 'old', 'name' and/or 'urgent' property"); mtx_unlock(&mod->lock); return false; @@ -467,8 +404,7 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void LOG_DBG("w: %s", w->name); /* Mark all workspaces on current's output invisible */ - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { struct workspace *ws = &it->item; if (ws->output != NULL && strcmp(ws->output, w->output) == 0) ws->visible = false; @@ -502,8 +438,7 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void /* Re-add the workspace to ensure correct sorting */ struct workspace ws = *w; - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { if (it->item.id == current_id) { tll_remove(m->workspaces, it); break; @@ -514,6 +449,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 +457,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); } } @@ -552,12 +482,6 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void w->urgent = json_object_get_boolean(urgent); } - else if (is_reload) { - /* Schedule full update to check if anything was changed - * during reload */ - i3_send_pkg(sock, I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); - } - else { LOG_WARN("unimplemented workspace event '%s'", change_str); } @@ -584,19 +508,19 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m } const char *change_str = json_object_get_string(change); + bool is_new = strcmp(change_str, "new") == 0; bool is_focus = strcmp(change_str, "focus") == 0; bool is_close = strcmp(change_str, "close") == 0; bool is_title = strcmp(change_str, "title") == 0; - if (!is_focus && !is_close && !is_title) + if (!is_new && !is_focus && !is_close && !is_title) return true; mtx_lock(&mod->lock); struct workspace *ws = NULL; - __attribute__((unused)) size_t focused = 0; - tll_foreach(m->workspaces, it) - { + size_t focused = 0; + tll_foreach(m->workspaces, it) { if (it->item.focused) { ws = &it->item; focused++; @@ -606,20 +530,6 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m assert(focused == 1); assert(ws != NULL); - struct json_object *container, *id, *name; - if (!json_object_object_get_ex(json, "container", &container) || !json_object_object_get_ex(container, "id", &id) - || !json_object_object_get_ex(container, "name", &name)) { - mtx_unlock(&mod->lock); - LOG_ERR("window event without 'container' with 'id' and 'name'"); - return false; - } - - if ((is_close || is_title) && ws->window.id != json_object_get_int(id)) { - /* Ignore close event and title changed event if it's not current window */ - mtx_unlock(&mod->lock); - return true; - } - if (is_close) { free(ws->window.title); free(ws->window.application); @@ -628,9 +538,33 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m ws->window.title = ws->window.application = NULL; ws->window.pid = -1; + /* May not be true, but e.g. a subsequent “focus” event will + * reset it... */ + ws->empty = true; + m->dirty = true; mtx_unlock(&mod->lock); return true; + + } + + /* Non-close event - thus workspace cannot be empty */ + ws->empty = false; + + struct json_object *container, *id, *name; + if (!json_object_object_get_ex(json, "container", &container) || + !json_object_object_get_ex(container, "id", &id) || + !json_object_object_get_ex(container, "name", &name)) + { + mtx_unlock(&mod->lock); + LOG_ERR("window event without 'container' with 'id' and 'name'"); + return false; + } + + if (is_title && ws->window.id != json_object_get_int(id)) { + /* Ignore title changed event if it's not current window */ + mtx_unlock(&mod->lock); + return true; } free(ws->window.title); @@ -651,24 +585,27 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m struct json_object *app_id; struct json_object *pid; - if (json_object_object_get_ex(container, "app_id", &app_id) && json_object_get_string(app_id) != NULL) { + if (json_object_object_get_ex(container, "app_id", &app_id) && + json_object_get_string(app_id) != NULL) + { free(ws->window.application); ws->window.application = strdup(json_object_get_string(app_id)); LOG_DBG("application: \"%s\", via 'app_id'", ws->window.application); } /* If PID has changed, update application name from /proc//comm */ - else if (json_object_object_get_ex(container, "pid", &pid) && ws->window.pid != json_object_get_int(pid)) { + else if (json_object_object_get_ex(container, "pid", &pid) && + ws->window.pid != json_object_get_int(pid)) + { ws->window.pid = json_object_get_int(pid); 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); - ws->window.application = NULL; + free(ws->window.application); ws->window.application = NULL; ws->window.pid = -1; m->dirty = true; @@ -760,7 +697,6 @@ run(struct module *mod) } struct workspace ws = { - .id = -1, .name = strdup(name_as_string), .name_as_int = name_as_int, .persistent = true, @@ -840,29 +776,34 @@ content(struct module *mod) struct exposable *particles[tll_length(m->workspaces) + 1]; struct exposable *current = NULL; - tll_foreach(m->workspaces, it) - { + tll_foreach(m->workspaces, it) { struct workspace *ws = &it->item; const struct ws_content *template = NULL; /* Lookup content template for workspace. Fall back to default * template if this workspace doesn't have a specific * template */ - if (ws->name == NULL) { - LOG_ERR("%d %d", ws->name_as_int, ws->id); - } template = ws_content_for_name(m, ws->name); if (template == NULL) { LOG_DBG("no ws template for %s, using default template", ws->name); template = ws_content_for_name(m, ""); } - const char *state = ws->urgent ? "urgent" : ws->visible ? ws->focused ? "focused" : "unfocused" : "invisible"; + const char *state = + ws->urgent ? "urgent" : + ws->visible ? ws->focused ? "focused" : "unfocused" : + "invisible"; - LOG_DBG("name=%s (name-as-int=%d): visible=%s, focused=%s, urgent=%s, empty=%s, state=%s, " + LOG_DBG("%s: visible=%s, focused=%s, urgent=%s, empty=%s, state=%s, " "application=%s, title=%s, mode=%s", - ws->name, ws->name_as_int, ws->visible ? "yes" : "no", ws->focused ? "yes" : "no", - ws->urgent ? "yes" : "no", ws->empty ? "yes" : "no", state, ws->window.application, ws->window.title, + ws->name, + ws->visible ? "yes" : "no", + ws->focused ? "yes" : "no", + ws->urgent ? "yes" : "no", + ws->empty ? "yes" : "no", + state, + ws->window.application, + ws->window.title, m->mode); const char *name = ws->name; @@ -876,7 +817,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 +828,7 @@ content(struct module *mod) tag_new_string(mod, "mode", m->mode), }, - .count = 10, + .count = 9, }; if (ws->focused) { @@ -898,9 +838,12 @@ content(struct module *mod) } if (template == NULL) { - LOG_WARN("no ws template for %s, and no default template available", ws->name); + LOG_WARN( + "no ws template for %s, and no default template available", + ws->name); } else { - particles[particle_count++] = template->content->instantiate(template->content, &tags); + particles[particle_count++] = template->content->instantiate( + template->content, &tags); } tag_set_destroy(&tags); @@ -910,7 +853,8 @@ content(struct module *mod) particles[particle_count++] = current; mtx_unlock(&mod->lock); - return dynlist_exposable_new(particles, particle_count, m->left_spacing, m->right_spacing); + return dynlist_exposable_new( + particles, particle_count, m->left_spacing, m->right_spacing); } /* Maps workspace name to a content particle. */ @@ -920,8 +864,10 @@ struct i3_workspaces { }; static struct module * -i3_new(struct i3_workspaces workspaces[], size_t workspace_count, int left_spacing, int right_spacing, - enum sort_mode sort_mode, size_t persistent_count, const char *persistent_workspaces[static persistent_count], +i3_new(struct i3_workspaces workspaces[], size_t workspace_count, + int left_spacing, int right_spacing, enum sort_mode sort_mode, + size_t persistent_count, + const char *persistent_workspaces[static persistent_count], bool strip_workspace_numbers) { struct private *m = calloc(1, sizeof(*m)); @@ -942,7 +888,8 @@ i3_new(struct i3_workspaces workspaces[], size_t workspace_count, int left_spaci m->sort_mode = sort_mode; m->persistent_count = persistent_count; - m->persistent_workspaces = calloc(persistent_count, sizeof(m->persistent_workspaces[0])); + m->persistent_workspaces = calloc( + persistent_count, sizeof(m->persistent_workspaces[0])); for (size_t i = 0; i < persistent_count; i++) m->persistent_workspaces[i] = strdup(persistent_workspaces[i]); @@ -965,26 +912,30 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *sort = yml_get_value(node, "sort"); const struct yml_node *persistent = yml_get_value(node, "persistent"); - const struct yml_node *strip_workspace_number = yml_get_value(node, "strip-workspace-numbers"); + const struct yml_node *strip_workspace_number = yml_get_value( + node, "strip-workspace-numbers"); - int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; - int right = spacing != NULL ? yml_value_as_int(spacing) - : right_spacing != NULL ? yml_value_as_int(right_spacing) - : 0; + int left = spacing != NULL ? yml_value_as_int(spacing) : + left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; + int right = spacing != NULL ? yml_value_as_int(spacing) : + right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; const char *sort_value = sort != NULL ? yml_value_as_string(sort) : NULL; - enum sort_mode sort_mode = sort_value == NULL ? SORT_NONE - : strcmp(sort_value, "none") == 0 ? SORT_NONE - : strcmp(sort_value, "native") == 0 ? SORT_NATIVE - : strcmp(sort_value, "ascending") == 0 ? SORT_ASCENDING - : SORT_DESCENDING; + enum sort_mode sort_mode = + sort_value == NULL ? SORT_NONE : + strcmp(sort_value, "none") == 0 ? SORT_NONE : + strcmp(sort_value, "ascending") == 0 ? SORT_ASCENDING : SORT_DESCENDING; - const size_t persistent_count = persistent != NULL ? yml_list_length(persistent) : 0; + const size_t persistent_count = + persistent != NULL ? yml_list_length(persistent) : 0; const char *persistent_workspaces[persistent_count]; if (persistent != NULL) { size_t idx = 0; - for (struct yml_list_iter it = yml_list_iter(persistent); it.node != NULL; yml_list_next(&it), idx++) { + for (struct yml_list_iter it = yml_list_iter(persistent); + it.node != NULL; + yml_list_next(&it), idx++) + { persistent_workspaces[idx] = yml_value_as_string(it.node); } } @@ -992,27 +943,38 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) struct i3_workspaces workspaces[yml_dict_length(c)]; size_t idx = 0; - for (struct yml_dict_iter it = yml_dict_iter(c); it.key != NULL; yml_dict_next(&it), idx++) { + for (struct yml_dict_iter it = yml_dict_iter(c); + it.key != NULL; + yml_dict_next(&it), idx++) + { workspaces[idx].name = yml_value_as_string(it.key); workspaces[idx].content = conf_to_particle(it.value, inherited); } - return i3_new(workspaces, yml_dict_length(c), left, right, sort_mode, persistent_count, persistent_workspaces, - (strip_workspace_number != NULL ? yml_value_as_bool(strip_workspace_number) : false)); + return i3_new(workspaces, yml_dict_length(c), left, right, sort_mode, + persistent_count, persistent_workspaces, + (strip_workspace_number != NULL + ? yml_value_as_bool(strip_workspace_number) : false)); } static bool verify_content(keychain_t *chain, const struct yml_node *node) { if (!yml_is_dict(node)) { - LOG_ERR("%s: must be a dictionary of workspace-name: particle mappings", conf_err_prefix(chain, node)); + LOG_ERR( + "%s: must be a dictionary of workspace-name: particle mappings", + conf_err_prefix(chain, node)); return false; } - for (struct yml_dict_iter it = yml_dict_iter(node); it.key != NULL; yml_dict_next(&it)) { + for (struct yml_dict_iter it = yml_dict_iter(node); + it.key != NULL; + yml_dict_next(&it)) + { const char *key = yml_value_as_string(it.key); if (key == NULL) { - LOG_ERR("%s: key must be a string (a i3 workspace name)", conf_err_prefix(chain, it.key)); + LOG_ERR("%s: key must be a string (a i3 workspace name)", + conf_err_prefix(chain, it.key)); return false; } @@ -1028,7 +990,8 @@ verify_content(keychain_t *chain, const struct yml_node *node) static bool verify_sort(keychain_t *chain, const struct yml_node *node) { - return conf_verify_enum(chain, node, (const char *[]){"none", "native", "ascending", "descending"}, 4); + return conf_verify_enum( + chain, node, (const char *[]){"none", "ascending", "descending"}, 3); } static bool @@ -1061,5 +1024,5 @@ const struct module_iface module_i3_iface = { }; #if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) -extern const struct module_iface iface __attribute__((weak, alias("module_i3_iface"))); +extern const struct module_iface iface __attribute__((weak, alias("module_i3_iface"))) ; #endif diff --git a/modules/label.c b/modules/label.c index 5f1f158..7e8ee09 100644 --- a/modules/label.c +++ b/modules/label.c @@ -1,14 +1,16 @@ -#include #include +#include #include -#include "../config-verify.h" #include "../config.h" +#include "../config-verify.h" #include "../module.h" #include "../plugin.h" -struct private { struct particle *label; }; +struct private { + struct particle *label; +}; static void destroy(struct module *mod) diff --git a/modules/mem.c b/modules/mem.c index de4e133..339501b 100644 --- a/modules/mem.c +++ b/modules/mem.c @@ -12,20 +12,17 @@ #define LOG_MODULE "mem" #define LOG_ENABLE_DBG 0 +#define SMALLEST_INTERVAL 500 #include "../bar/bar.h" #include "../config-verify.h" #include "../config.h" #include "../log.h" #include "../plugin.h" -static const long min_poll_interval = 250; - struct private { struct particle *label; uint16_t interval; - uint64_t mem_free; - uint64_t mem_total; }; static void @@ -54,7 +51,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; @@ -81,12 +78,15 @@ static struct exposable * content(struct module *mod) { const struct private *p = mod->private; + uint64_t mem_free = 0; + uint64_t mem_used = 0; + uint64_t mem_total = 0; - mtx_lock(&mod->lock); + if (!get_mem_stats(&mem_free, &mem_total)) { + LOG_ERR("unable to retrieve the memory stats"); + } - const uint64_t mem_free = p->mem_free; - const uint64_t mem_total = p->mem_total; - const uint64_t mem_used = mem_total - mem_free; + mem_used = mem_total - mem_free; double percent_used = ((double)mem_used * 100) / (mem_total + 1); double percent_free = ((double)mem_free * 100) / (mem_total + 1); @@ -101,7 +101,6 @@ content(struct module *mod) struct exposable *exposable = p->label->instantiate(p->label, &tags); tag_set_destroy(&tags); - mtx_unlock(&mod->lock); return exposable; } @@ -127,13 +126,6 @@ run(struct module *mod) if (fds[0].revents & POLLIN) break; - mtx_lock(&mod->lock); - p->mem_free = 0; - p->mem_total = 0; - if (!get_mem_stats(&p->mem_free, &p->mem_total)) { - LOG_ERR("unable to retrieve the memory stats"); - } - mtx_unlock(&mod->lock); bar->refresh(bar); } @@ -159,20 +151,20 @@ mem_new(uint16_t interval, struct particle *label) static struct module * from_conf(const struct yml_node *node, struct conf_inherit inherited) { - const struct yml_node *interval = yml_get_value(node, "poll-interval"); + const struct yml_node *interval = yml_get_value(node, "interval"); const struct yml_node *c = yml_get_value(node, "content"); - return mem_new(interval == NULL ? min_poll_interval : yml_value_as_int(interval), conf_to_particle(c, inherited)); + return mem_new(interval == NULL ? SMALLEST_INTERVAL : yml_value_as_int(interval), conf_to_particle(c, inherited)); } static bool -conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node) +conf_verify_interval(keychain_t *chain, const struct yml_node *node) { if (!conf_verify_unsigned(chain, node)) return false; - if (yml_value_as_int(node) < min_poll_interval) { - LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval); + if (yml_value_as_int(node) < SMALLEST_INTERVAL) { + LOG_ERR("%s: interval value cannot be less than %d ms", conf_err_prefix(chain, node), SMALLEST_INTERVAL); return false; } @@ -183,7 +175,7 @@ static bool verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { - {"poll-interval", false, &conf_verify_poll_interval}, + {"interval", false, &conf_verify_interval}, MODULE_COMMON_ATTRS, }; diff --git a/modules/meson.build b/modules/meson.build index f6d53d8..49aba6d 100644 --- a/modules/meson.build +++ b/modules/meson.build @@ -22,10 +22,6 @@ plugin_mem_enabled = get_option('plugin-mem').allowed() mpd = dependency('libmpdclient', required: get_option('plugin-mpd')) plugin_mpd_enabled = mpd.found() -# DBus dependency. Used by 'mpris' -sdbus_library = dependency('libsystemd', 'libelogind', 'basu', required: get_option('plugin-mpris')) -plugin_mpris_enabled = sdbus_library.found() - json_i3 = dependency('json-c', required: get_option('plugin-i3')) plugin_i3_enabled = json_i3.found() @@ -49,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() @@ -80,7 +70,7 @@ if plugin_clock_enabled endif if plugin_cpu_enabled - mod_data += {'cpu': [[], [m, dynlist]]} + mod_data += {'cpu': [[], [dynlist]]} endif if plugin_disk_io_enabled @@ -92,18 +82,13 @@ if plugin_dwl_enabled endif if plugin_mem_enabled - mod_data += {'mem': [[], [m]]} + mod_data += {'mem': [[], []]} endif if plugin_mpd_enabled mod_data += {'mpd': [[], [mpd]]} endif -if plugin_mpris_enabled - sdbus = declare_dependency(compile_args: ['-DHAVE_' + sdbus_library.name().to_upper()], dependencies:[sdbus_library]) - mod_data += {'mpris': [[], [sdbus]]} -endif - if plugin_i3_enabled mod_data += {'i3': [['i3-common.c', 'i3-common.h'], [dynlist, json_i3]]} endif @@ -113,15 +98,15 @@ if plugin_label_enabled endif if plugin_network_enabled - mod_data += {'network': [[], [dynlist]]} + mod_data += {'network': [[], []]} endif if plugin_pipewire_enabled - mod_data += {'pipewire': [[], [m, pipewire, dynlist, json_pipewire]]} + mod_data += {'pipewire': [[], [pipewire, dynlist, json_pipewire]]} endif if plugin_pulse_enabled - mod_data += {'pulse': [[], [m, pulse]]} + mod_data += {'pulse': [[], [pulse]]} endif if plugin_removables_enabled @@ -136,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 @@ -193,7 +170,7 @@ if plugin_foreign_toplevel_enabled command: [wscanner_prog, 'private-code', '@INPUT@', '@OUTPUT@']) endforeach - mod_data += {'foreign-toplevel': [[wl_proto_src + wl_proto_headers + ftop_proto_headers + ftop_proto_src], [m, dynlist, wayland_client]]} + mod_data += {'foreign-toplevel': [[wl_proto_src + wl_proto_headers + ftop_proto_headers + ftop_proto_src], [dynlist, wayland_client]]} endif foreach mod, data : mod_data diff --git a/modules/mpd.c b/modules/mpd.c index e70e41f..604bf88 100644 --- a/modules/mpd.c +++ b/modules/mpd.c @@ -1,34 +1,33 @@ +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include #include -#include -#include -#include #include #define LOG_MODULE "mpd" #define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../plugin.h" -struct private -{ +struct private { char *host; uint16_t port; struct particle *label; @@ -39,8 +38,7 @@ struct private bool repeat; bool random; bool consume; - bool single; - int volume; + int volume; char *album; char *artist; char *title; @@ -62,9 +60,11 @@ destroy(struct module *mod) struct private *m = mod->private; if (m->refresh_thread_id != 0) { assert(m->refresh_abort_fd != -1); - if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) { + if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) + != sizeof(uint64_t)) + { LOG_ERRNO("failed to signal abort to refresher thread"); - } else { + } else{ int res; thrd_join(m->refresh_thread_id, &res); } @@ -132,11 +132,12 @@ content(struct module *mod) if (m->state == MPD_STATE_PLAY) { elapsed += timespec_diff_milli_seconds(&now, &m->elapsed.when); if (elapsed > m->duration) { - LOG_DBG("dynamic update of elapsed overflowed: " - "elapsed=%" PRIu64 ", duration=%" PRIu64, - elapsed, m->duration); + LOG_DBG( + "dynamic update of elapsed overflowed: " + "elapsed=%"PRIu64", duration=%"PRIu64, elapsed, m->duration); elapsed = m->duration; } + } unsigned elapsed_secs = elapsed / 1000; @@ -153,23 +154,16 @@ content(struct module *mod) state_str = "offline"; else { switch (m->state) { - case MPD_STATE_UNKNOWN: - state_str = "unknown"; - break; - case MPD_STATE_STOP: - state_str = "stopped"; - break; - case MPD_STATE_PAUSE: - state_str = "paused"; - break; - case MPD_STATE_PLAY: - state_str = "playing"; - break; + case MPD_STATE_UNKNOWN: state_str = "unknown"; break; + case MPD_STATE_STOP: state_str = "stopped"; break; + case MPD_STATE_PAUSE: state_str = "paused"; break; + case MPD_STATE_PLAY: state_str = "playing"; break; } } /* Tell particle to real-time track? */ - enum tag_realtime_unit realtime = m->state == MPD_STATE_PLAY ? TAG_REALTIME_MSECS : TAG_REALTIME_NONE; + enum tag_realtime_unit realtime = m->state == MPD_STATE_PLAY + ? TAG_REALTIME_MSECS : TAG_REALTIME_NONE; struct tag_set tags = { .tags = (struct tag *[]){ @@ -177,7 +171,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 +182,7 @@ content(struct module *mod) tag_new_int_realtime( mod, "elapsed", elapsed, 0, m->duration, realtime), }, - .count = 14, + .count = 13, }; mtx_unlock(&mod->lock); @@ -244,7 +237,8 @@ wait_for_socket_create(const struct module *mod) LOG_DBG("%s: already exists, and is connectable", m->host); have_mpd_socket = true; } else { - LOG_DBG("%s: already exists, but isn't connectable: %s", m->host, strerror(errno)); + LOG_DBG("%s: already exists, but isn't connectable: %s", + m->host, strerror(errno)); } close(s); @@ -255,7 +249,10 @@ wait_for_socket_create(const struct module *mod) bool ret = false; while (!have_mpd_socket) { - struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = fd, .events = POLLIN}}; + struct pollfd fds[] = { + {.fd = mod->abort_fd, .events = POLLIN}, + {.fd = fd, .events = POLLIN} + }; if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) < 0) { if (errno == EINTR) @@ -275,7 +272,7 @@ wait_for_socket_create(const struct module *mod) char buf[1024]; ssize_t len = read(fd, buf, sizeof(buf)); - for (const char *ptr = buf; ptr < buf + len;) { + for (const char *ptr = buf; ptr < buf + len; ) { const struct inotify_event *e = (const struct inotify_event *)ptr; LOG_DBG("inotify: CREATED: %s/%.*s", directory, e->len, e->name); @@ -285,7 +282,7 @@ wait_for_socket_create(const struct module *mod) break; } - ptr += sizeof(*e) + e->len; + ptr += sizeof(*e) + e->len; } } @@ -308,7 +305,8 @@ connect_to_mpd(const struct module *mod) enum mpd_error merr = mpd_connection_get_error(conn); if (merr != MPD_ERROR_SUCCESS) { - LOG_WARN("failed to connect to MPD: %s", mpd_connection_get_error_message(conn)); + LOG_WARN("failed to connect to MPD: %s", + mpd_connection_get_error_message(conn)); mpd_connection_free(conn); return NULL; } @@ -326,7 +324,8 @@ update_status(struct module *mod) struct mpd_status *status = mpd_run_status(m->conn); if (status == NULL) { - LOG_ERR("failed to get status: %s", mpd_connection_get_error_message(m->conn)); + LOG_ERR("failed to get status: %s", + mpd_connection_get_error_message(m->conn)); return false; } @@ -338,7 +337,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); @@ -349,20 +347,17 @@ update_status(struct module *mod) struct mpd_song *song = mpd_run_current_song(m->conn); if (song == NULL && mpd_connection_get_error(m->conn) != MPD_ERROR_SUCCESS) { - LOG_ERR("failed to get current song: %s", mpd_connection_get_error_message(m->conn)); + LOG_ERR("failed to get current song: %s", + mpd_connection_get_error_message(m->conn)); return false; } if (song == NULL) { mtx_lock(&mod->lock); - free(m->album); - m->album = NULL; - free(m->artist); - m->artist = NULL; - free(m->title); - m->title = NULL; - free(m->file); - m->file = NULL; + free(m->album); m->album = NULL; + free(m->artist); m->artist = NULL; + free(m->title); m->title = NULL; + free(m->file); m->file = NULL; mtx_unlock(&mod->lock); } else { const char *album = mpd_song_get_tag(song, MPD_TAG_ALBUM, 0); @@ -406,14 +401,10 @@ run(struct module *mod) /* Reset state */ mtx_lock(&mod->lock); - free(m->album); - m->album = NULL; - free(m->artist); - m->artist = NULL; - free(m->title); - m->title = NULL; - free(m->file); - m->file = NULL; + free(m->album); m->album = NULL; + free(m->artist); m->artist = NULL; + free(m->title); m->title = NULL; + free(m->file); m->file = NULL; m->state = MPD_STATE_UNKNOWN; m->elapsed.value = m->duration = 0; m->elapsed.when.tv_sec = m->elapsed.when.tv_nsec = 0; @@ -440,7 +431,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 +442,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; } - } } @@ -482,7 +467,8 @@ run(struct module *mod) }; if (!mpd_send_idle(m->conn)) { - LOG_ERR("failed to send IDLE command: %s", mpd_connection_get_error_message(m->conn)); + LOG_ERR("failed to send IDLE command: %s", + mpd_connection_get_error_message(m->conn)); break; } @@ -506,7 +492,8 @@ run(struct module *mod) } if (fds[1].revents & POLLIN) { - enum mpd_idle idle __attribute__((unused)) = mpd_recv_idle(m->conn, true); + enum mpd_idle idle __attribute__ ((unused)) = + mpd_recv_idle(m->conn, true); LOG_DBG("IDLE mask: %d", idle); @@ -578,7 +565,9 @@ refresh_in(struct module *mod, long milli_seconds) /* Signal abort to thread */ assert(m->refresh_abort_fd != -1); - if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) { + if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) + != sizeof(uint64_t)) + { LOG_ERRNO("failed to signal abort to refresher thread"); return false; } @@ -618,7 +607,7 @@ refresh_in(struct module *mod, long milli_seconds) } /* Detach - we don't want to have to thrd_join() it */ - // thrd_detach(tid); + //thrd_detach(tid); return r == 0; } @@ -649,8 +638,10 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *port = yml_get_value(node, "port"); const struct yml_node *c = yml_get_value(node, "content"); - return mpd_new(yml_value_as_string(host), port != NULL ? yml_value_as_int(port) : 0, - conf_to_particle(c, inherited)); + return mpd_new( + yml_value_as_string(host), + port != NULL ? yml_value_as_int(port) : 0, + conf_to_particle(c, inherited)); } static bool diff --git a/modules/mpris.c b/modules/mpris.c deleted file mode 100644 index 5ddf6e0..0000000 --- a/modules/mpris.c +++ /dev/null @@ -1,1100 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#define LOG_MODULE "mpris" -#define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" -#include "../log.h" -#include "../plugin.h" - -#include "dbus.h" -#include "yml.h" - -#define is_empty_string(str) ((str) == NULL || (str)[0] == '\0') - -#define DEFAULT_QUERY_TIMEOUT_MS (500 * 1000) - -#define MPRIS_PATH "/org/mpris/MediaPlayer2" -#define MPRIS_BUS_NAME "org.mpris.MediaPlayer2" -#define MPRIS_SERVICE "org.mpris.MediaPlayer2" -#define MPRIS_INTERFACE_PLAYER "org.mpris.MediaPlayer2.Player" - -#define DBUS_PATH "/org/freedesktop/DBus" -#define DBUS_BUS_NAME "org.freedesktop.DBus" -#define DBUS_SERVICE "org.freedesktop.DBus" -#define DBUS_INTERFACE_MONITORING "org.freedesktop.DBus.Monitoring" -#define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" - -enum status { - STATUS_OFFLINE, - STATUS_PLAYING, - STATUS_PAUSED, - STATUS_STOPPED, - STATUS_ERROR, -}; - -typedef tll(char *) string_array; - -struct metadata { - uint64_t length_us; - char *trackid; - string_array artists; - char *album; - char *title; -}; - -struct property { - struct metadata metadata; - char *playback_status; - char *loop_status; - uint64_t position_us; - double rate; - double volume; - bool shuffle; -}; - -struct client { - bool has_seeked_support; - enum status status; - const char *bus_name; - const char *bus_unique_name; - - struct property property; - - /* The unix timestamp of the last position change (ie. - * seeking, pausing) */ - struct timespec seeked_when; -}; - -struct context { - const struct private *mpd_config; - - sd_bus *monitor_connection; - sd_bus_message *update_message; - - tll(struct client *) clients; - struct client *current_client; - - bool has_update; -}; - -struct private -{ - thrd_t refresh_thread_id; - int refresh_abort_fd; - - size_t timeout_ms; - string_array identity_list; - struct context context; - struct particle *label; -}; - -#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG -static void __attribute__((unused)) -debug_print_argument_type(sd_bus_message *message) -{ - char type; - const char *content; - sd_bus_message_peek_type(message, &type, &content); - LOG_DBG("argument type: %c -> %s", type, content); -} -#endif - -static void -metadata_clear(struct metadata *metadata) -{ - tll_free_and_free(metadata->artists, free); - - if (metadata->album != NULL) { - free(metadata->album); - metadata->album = NULL; - } - - if (metadata->title != NULL) { - free(metadata->title); - metadata->title = NULL; - } - - if (metadata->trackid != NULL) { - free(metadata->trackid); - metadata->trackid = NULL; - } -} - -static void -client_free(struct client *client) -{ - free((void *)client->bus_name); - free((void *)client->bus_unique_name); - free(client); -} - -static void -client_free_by_unique_name(struct context *context, const char *unique_name) -{ - tll_foreach(context->clients, it) - { - struct client *client = it->item; - if (strcmp(client->bus_unique_name, unique_name) == 0) { - LOG_DBG("client_remove: Removing client %s", client->bus_name); - - client_free(client); - tll_remove(context->clients, it); - } - } -} - -static void -client_add(struct context *context, const char *name, const char *unique_name) -{ - struct client *client = malloc(sizeof(*client)); - (*client) = (struct client){ - .bus_name = strdup(name), - .bus_unique_name = strdup(unique_name), - }; - - tll_push_back(context->clients, client); - LOG_DBG("client_add: name='%s' unique_name='%s'", name, unique_name); -} - -static struct client * -client_lookup_by_unique_name(struct context *context, const char *unique_name) -{ - tll_foreach(context->clients, it) - { - struct client *client = it->item; - if (strcmp(client->bus_unique_name, unique_name) == 0) { - LOG_DBG("client_lookup: name: %s", client->bus_name); - return client; - } - } - - return NULL; -} - -static void -client_change_unique_name(struct client *client, const char *new_name) -{ - if (client->bus_unique_name != NULL) { - free((void *)client->bus_unique_name); - } - - client->bus_unique_name = strdup(new_name); -} - -static bool -verify_bus_name(const string_array *identity_list, const char *name) -{ - tll_foreach(*identity_list, it) - { - const char *ident = it->item; - - if (strlen(name) < strlen(MPRIS_BUS_NAME ".") + strlen(ident)) { - continue; - } - - const char *cmp = name + strlen(MPRIS_BUS_NAME "."); - if (strncmp(cmp, ident, strlen(ident)) != 0) { - continue; - } - - return true; - } - - return false; -} - -static bool -read_string_array(sd_bus_message *message, string_array *list) -{ - int status = 0; - - /* message argument layout: 'vas' */ - /* enter variant */ - status = sd_bus_message_enter_container(message, SD_BUS_TYPE_VARIANT, "as"); - if (status <= 0) { - LOG_DBG("unexpected layout: errno=%d (%s)", status, strerror(-status)); - return false; - } - - /* enter array */ - status = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "s"); - assert(status >= 0); - - const char *string; - while ((status = sd_bus_message_read_basic(message, SD_BUS_TYPE_STRING, &string)) > 0) { - if (!is_empty_string(string)) { - tll_push_back(*list, strdup(string)); - } - } - - if (status < 0) { - LOG_ERR("metadata: unexpected layout: errno=%d (%s)", status, strerror(-status)); - return false; - } - - /* close array */ - sd_bus_message_exit_container(message); - /* close variant */ - sd_bus_message_exit_container(message); - - return true; -} - -static bool -metadata_parse_property(const char *property_name, sd_bus_message *message, struct metadata *buffer) -{ - int status = 0; - const char *string = NULL; - - char argument_type = 0; - const char *argument_layout = NULL; - sd_bus_message_peek_type(message, &argument_type, &argument_layout); - assert(argument_type == SD_BUS_TYPE_VARIANT); - assert(!is_empty_string(argument_layout)); - - if (strcmp(property_name, "mpris:trackid") == 0) { - if (argument_layout[0] != SD_BUS_TYPE_STRING && argument_layout[0] != SD_BUS_TYPE_OBJECT_PATH) - goto unexpected_type; - - status = sd_bus_message_read(message, "v", argument_layout, &string); - if (status > 0 && !is_empty_string(string)) - buffer->trackid = strdup(string); - - /* FIXME: "strcmp matches both 'album' as well as 'albumArtist'" */ - } else if (strcmp(property_name, "xesam:album") == 0) { - status = sd_bus_message_read(message, "v", argument_layout, &string); - if (status > 0 && !is_empty_string(string)) - buffer->album = strdup(string); - - } else if (strcmp(property_name, "xesam:artist") == 0) { - status = read_string_array(message, &buffer->artists); - - } else if (strcmp(property_name, "xesam:title") == 0) { - status = sd_bus_message_read(message, "v", "s", &string); - if (status > 0 && !is_empty_string(string)) - buffer->title = strdup(string); - - } else if (strcmp(property_name, "mpris:length") == 0) { - /* MPRIS requires 'mpris:length' to be an i64 (the wording is a bit ambiguous), however some client - * use a u64 instead. */ - if (argument_layout[0] != SD_BUS_TYPE_INT64 && argument_layout[0] != SD_BUS_TYPE_UINT64) - goto unexpected_type; - - status = sd_bus_message_read(message, "v", argument_layout, &buffer->length_us); - - } else { - LOG_DBG("metadata: ignoring property: %s", property_name); - sd_bus_message_skip(message, NULL); - return true; - } - - if (status < 0) { - LOG_ERR("metadata: failed to read property: arg_type='%c' arg_layout='%s' errno=%d (%s)", argument_type, - argument_layout, status, strerror(-status)); - return false; - } - - return true; -unexpected_type: - LOG_ERR("metadata: unexpected type for '%s'", property_name); - return false; -} - -static bool -metadata_parse_array(struct metadata *metadata, sd_bus_message *message) -{ - int status = sd_bus_message_enter_container(message, SD_BUS_TYPE_VARIANT, "a{sv}"); - if (status <= 0) { - LOG_DBG("unexpected layout: errno=%d (%s)", status, strerror(-status)); - return false; - } - status = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{sv}"); - assert(status >= 0); - - while ((status = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { - const char *property_name = NULL; - status = sd_bus_message_read_basic(message, SD_BUS_TYPE_STRING, &property_name); - if (status <= 0) { - LOG_DBG("unexpected layout: errno=%d (%s)", status, strerror(-status)); - return false; - } - - status = metadata_parse_property(property_name, message, metadata); - if (status == 0) { - return false; - } - - status = sd_bus_message_exit_container(message); - assert(status >= 0); - } - - /* close array */ - sd_bus_message_exit_container(message); - /* close variant */ - sd_bus_message_exit_container(message); - - return status >= 0; -} - -static bool -property_parse(struct property *prop, const char *property_name, sd_bus_message *message) -{ - /* This function is called in two different ways: - * 1. update_status(): The property is passed directly - * 2. update_status_from_message(): The property is passed wrapped - * inside a variant and has to be unpacked */ - const char *argument_layout = NULL; - char argument_type = 0; - int status = sd_bus_message_peek_type(message, &argument_type, &argument_layout); - - assert(status > 0); - assert(argument_type == SD_BUS_TYPE_VARIANT); - assert(!is_empty_string(argument_layout)); - - const char *string; - if (strcmp(property_name, "PlaybackStatus") == 0) { - status = sd_bus_message_read(message, "v", "s", &string); - if (status && !is_empty_string(string)) - prop->playback_status = strdup(string); - - } else if (strcmp(property_name, "LoopStatus") == 0) { - status = sd_bus_message_read(message, "v", "s", &string); - if (status && !is_empty_string(string)) - prop->loop_status = strdup(string); - - } else if (strcmp(property_name, "Position") == 0) { - /* MPRIS requires 'Position' to be a i64, however some client - * use a u64 instead. */ - if (argument_layout[0] != SD_BUS_TYPE_INT64 && argument_layout[0] != SD_BUS_TYPE_UINT64) { - LOG_ERR("property: unexpected type for '%s'", property_name); - return false; - } - status = sd_bus_message_read(message, "v", argument_layout[0], &prop->position_us); - - } else if (strcmp(property_name, "Shuffle") == 0) { - status = sd_bus_message_read(message, "v", "b", &prop->shuffle); - - } else if (strcmp(property_name, "Metadata") == 0) { - metadata_clear(&prop->metadata); - status = metadata_parse_array(&prop->metadata, message); - - } else { - LOG_DBG("property: ignoring property: %s", property_name); - sd_bus_message_skip(message, NULL); - return true; - } - - return status > 0; -} - -/* ------------- */ - -static void -format_usec_timestamp(unsigned usec, char *s, size_t sz) -{ - uint32_t secs = usec / 1000 / 1000; - uint32_t hours = secs / (60 * 60); - uint32_t minutes = secs % (60 * 60) / 60; - secs %= 60; - - if (hours > 0) - snprintf(s, sz, "%02u:%02u:%02u", hours, minutes, secs); - else - snprintf(s, sz, "%02u:%02u", minutes, secs); -} - -static void -destroy(struct module *mod) -{ - struct private *m = mod->private; - - tll_free_and_free(m->context.clients, client_free); - sd_bus_close(m->context.monitor_connection); - - tll_free_and_free(m->identity_list, free); - m->label->destroy(m->label); - free(m); - - module_default_destroy(mod); -} - -static void -context_event_handle_name_owner_changed(sd_bus_message *message, struct context *context) -{ - /* NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner) */ - /* This signal indicates that the owner of a name has changed, ie. - * it was acquired, lost or changed */ - - const char *bus_name = NULL, *old_owner = NULL, *new_owner = NULL; - int status __attribute__((unused)) = sd_bus_message_read(message, "sss", &bus_name, &old_owner, &new_owner); - assert(status > 0); - - LOG_DBG("event_handler: 'NameOwnerChanged': bus_name: '%s' old_owner: '%s' new_ower: '%s'", bus_name, old_owner, - new_owner); - - if (is_empty_string(new_owner) && !is_empty_string(old_owner)) { - /* Target bus has been lost */ - struct client *client = client_lookup_by_unique_name(context, old_owner); - - if (client == NULL) - return; - - LOG_DBG("event_handler: 'NameOwnerChanged': Target bus disappeared: %s", client->bus_name); - client_free_by_unique_name(context, client->bus_unique_name); - - if (context->current_client == client) - context->current_client = NULL; - - return; - } else if (is_empty_string(old_owner) && !is_empty_string(new_owner)) { - /* New unique name registered. Not used */ - return; - } - - /* Name changed */ - assert(!is_empty_string(new_owner)); - assert(!is_empty_string(old_owner)); - - struct client *client = client_lookup_by_unique_name(context, old_owner); - LOG_DBG("'NameOwnerChanged': Name changed from '%s' to '%s' for client '%s'", old_owner, new_owner, - client->bus_name); - client_change_unique_name(client, new_owner); -} - -static void -context_event_handle_name_acquired(sd_bus_message *message, struct context *context) -{ - /* Spy on applications that requested an "MPRIS style" bus name */ - - /* NameAcquired (STRING name) */ - /* " This signal is sent to a specific application when it gains ownership of a name. " */ - const char *name = NULL; - int status __attribute__((unused)) = sd_bus_message_read_basic(message, SD_BUS_TYPE_STRING, &name); - assert(status > 0); - - LOG_DBG("event_handler: 'NameAcquired': name: '%s'", name); - - if (strncmp(name, MPRIS_BUS_NAME, strlen(MPRIS_BUS_NAME)) != 0) { - return; - } - - if (verify_bus_name(&context->mpd_config->identity_list, name)) { - const char *unique_name = sd_bus_message_get_destination(message); - LOG_DBG("'NameAcquired': Acquired new client: %s unique: %s", name, unique_name); - client_add(context, name, unique_name); - } -} - -static int -context_event_handler(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) -{ - struct context *context = userdata; - - const char *member = sd_bus_message_get_member(message); - const char *sender = sd_bus_message_get_sender(message); - const char *path_name = sd_bus_message_get_path(message); - -#if 0 - const char *destination = sd_bus_message_get_destination(message); - const char *self = sd_bus_message_get_sender(message); - LOG_DBG("member: '%s' self: '%s' dest: '%s' sender: '%s'", member, self, - destination, sender); -#endif - - if (tll_length(context->clients) == 0 && strcmp(member, "NameAcquired") != 0) { - return 1; - } - - /* TODO: Allow multiple clients to connect */ - if (strcmp(path_name, DBUS_PATH) == 0 && strcmp(member, "NameAcquired") == 0) { - context_event_handle_name_acquired(message, context); - } - - if (strcmp(path_name, DBUS_PATH) == 0 && strcmp(member, "NameOwnerChanged") == 0) { - context_event_handle_name_owner_changed(message, context); - return 1; - } - - /* Copy the 'PropertiesChanged/Seeked' message, so it can be parsed - * later on */ - if (strcmp(path_name, MPRIS_PATH) == 0 - && (strcmp(member, "PropertiesChanged") == 0 || strcmp(member, "Seeked") == 0)) { - struct client *client = client_lookup_by_unique_name(context, sender); - if (client == NULL) - return 1; - - LOG_DBG("event_handler: '%s': name: '%s' unique_name: '%s'", member, client->bus_name, client->bus_unique_name); - - context->has_update = true; - context->current_client = client; - context->update_message = sd_bus_message_ref(message); - - assert(context->update_message != NULL); - } - - return 1; -} - -static bool -context_process_events(struct context *context, uint32_t timeout_ms) -{ - int status = -1; - - status = sd_bus_wait(context->monitor_connection, timeout_ms); - if (status < 0) { - if (status == -ENOTCONN) - LOG_DBG("Disconnect signal has been processed"); - else - LOG_ERR("Failed to query monitor connection: errno=%d", status); - - return false; - } - - /* 'sd_bus_process' processes one 'action' per call. - * This includes: connection, authentication, message processing */ - status = sd_bus_process(context->monitor_connection, NULL); - - if (status < 0) { - if (status == -ENOTCONN) - LOG_DBG("Disconnect signal has been processed"); - else - LOG_ERR("Failed to query monitor connection: errno=%d", status); - - return false; - } - - return true; -} - -static bool -context_setup(struct context *context) -{ - int status = true; - sd_bus *connection; - if ((status = sd_bus_default_user(&connection)) < 0) { - LOG_ERR("Failed to connect to the desktop bus. errno: %d", status); - return false; - } - - context->monitor_connection = connection; - - /* Turn this connection into a monitor */ - sd_bus_message *message; - status = sd_bus_message_new_method_call(connection, &message, DBUS_SERVICE, DBUS_PATH, DBUS_INTERFACE_MONITORING, - "BecomeMonitor"); - - const char *matching_rules[] = { - /* Listen for... */ - /* ... new MPRIS clients */ - "type='signal',interface='org.freedesktop.DBus',member='NameAcquired',path='/org/freedesktop/" - "DBus',arg0namespace='org.mpris.MediaPlayer2'", - /* ... name changes */ - "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'," - "path='/org/freedesktop/DBus'", - /* ... property changes */ - "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged', " - "path='/org/mpris/MediaPlayer2'", - /* ... changes in playback position */ - "type='signal',interface='org.mpris.MediaPlayer2.Player',member='Seeked', " - "path='/org/mpris/MediaPlayer2'", - }; - - /* TODO: Error handling */ - /* "BecomeMonitor" ('asu'): (Rules: String[], Flags: UINT32) */ - /* https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-become-monitor */ - status = sd_bus_message_open_container(message, SD_BUS_TYPE_ARRAY, "s"); - for (uint32_t i = 0; i < sizeof(matching_rules) / sizeof(matching_rules[0]); i++) { - status = sd_bus_message_append(message, "s", matching_rules[i]); - } - status = sd_bus_message_close_container(message); - status = sd_bus_message_append_basic(message, SD_BUS_TYPE_UINT32, &(uint32_t){0}); - - sd_bus_message *reply = NULL; - sd_bus_error error = {}; - status = sd_bus_call(NULL, message, context->mpd_config->timeout_ms, &error, &reply); - - if (status < 0 && sd_bus_error_is_set(&error)) { - LOG_ERR("context_setup: got error: %s: %s (%d)", error.name, error.message, sd_bus_error_get_errno(&error)); - return false; - } - - sd_bus_message_unref(message); - sd_bus_message_unref(reply); - - sd_bus_add_filter(connection, NULL, context_event_handler, context); - - return status >= 0; -} - -static uint64_t -timespec_diff_us(const struct timespec *a, const struct timespec *b) -{ - uint64_t nsecs_a = a->tv_sec * 1000000000 + a->tv_nsec; - uint64_t nsecs_b = b->tv_sec * 1000000000 + b->tv_nsec; - - assert(nsecs_a >= nsecs_b); - uint64_t nsec_diff = nsecs_a - nsecs_b; - return nsec_diff / 1000; -} - -static bool -update_status_from_message(struct module *mod, sd_bus_message *message) -{ - struct private *m = mod->private; - mtx_lock(&mod->lock); - - struct client *client = m->context.current_client; - int status = 1; - - /* Player.Seeked (UINT64 position)*/ - if (strcmp(sd_bus_message_get_member(message), "Seeked") == 0) { - client->has_seeked_support = true; - - status = sd_bus_message_read_basic(message, SD_BUS_TYPE_INT64, &client->property.position_us); - if (status <= 0) - return status; - - clock_gettime(CLOCK_MONOTONIC, &client->seeked_when); - return true; - } - - /* Properties.PropertiesChanged (STRING interface_name, - * ARRAY of DICT_ENTRY changed_properties, - * ARRAY invalidated_properties); */ - assert(strcmp(sd_bus_message_get_member(message), "PropertiesChanged") == 0); - assert(strcmp(sd_bus_message_get_signature(message, 1), "sa{sv}as") == 0); - - /* argument: 'interface_name' layout: 's' */ - const char *interface_name = NULL; - sd_bus_message_read_basic(message, SD_BUS_TYPE_STRING, &interface_name); - - if (strcmp(interface_name, MPRIS_INTERFACE_PLAYER) != 0) { - LOG_DBG("Ignoring interface: %s", interface_name); - mtx_unlock(&mod->lock); - return true; - } - - /* argument: 'changed_properties' layout: 'a{sv}' */ - - /* Make sure we reset the position on metadata change unless the - * update contains its own position value */ - bool should_reset_position = true; - bool has_entries = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{sv}"); - - while ((has_entries = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { - const char *property_name = NULL; - int status __attribute__((unused)) = sd_bus_message_read_basic(message, SD_BUS_TYPE_STRING, &property_name); - assert(status > 0); - - if (!property_parse(&client->property, property_name, message)) { - return false; - } - - status = sd_bus_message_exit_container(message); - assert(status >= 0); - - if (strcmp(property_name, "PlaybackStatus") == 0) { - if (strcmp(client->property.playback_status, "Stopped") == 0) { - client->status = STATUS_STOPPED; - - } else if (strcmp(client->property.playback_status, "Playing") == 0) { - clock_gettime(CLOCK_MONOTONIC, &client->seeked_when); - client->status = STATUS_PLAYING; - - } else if (strcmp(client->property.playback_status, "Paused") == 0) { - /* Update our position to include the elapsed time */ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - client->status = STATUS_PAUSED; - client->property.position_us += timespec_diff_us(&now, &client->seeked_when); - } - } - - /* Make sure to reset the position upon metadata/song changes */ - if (should_reset_position && strcmp(property_name, "Metadata") == 0) { - client->property.position_us = 0; - - if (client->property.playback_status == NULL) { - client->property.playback_status = "Paused"; - client->status = STATUS_PAUSED; - } - } - - if (strcmp(property_name, "Position") == 0) { - should_reset_position = false; - } - } - - status = sd_bus_message_exit_container(message); - assert(status > 0); - - mtx_unlock(&mod->lock); - return true; -} - -static struct exposable * -content_empty(struct module *mod) -{ - struct private *m = mod->private; - mtx_lock(&mod->lock); - - struct tag_set tags = { - .tags = (struct tag *[]){ - tag_new_bool(mod, "has-seeked-support", "false"), - tag_new_string(mod, "state", "offline"), - tag_new_bool(mod, "shuffle", "false"), - tag_new_string(mod, "loop", "None"), - tag_new_int_range(mod, "volume", 0, 0, 100), - tag_new_string(mod, "album", ""), - tag_new_string(mod, "artist", ""), - tag_new_string(mod, "title", ""), - tag_new_string(mod, "pos", ""), - tag_new_string(mod, "end", ""), - tag_new_int_realtime( - mod, "elapsed", 0, 0, 0, TAG_REALTIME_NONE), - }, - .count = 10, - }; - - struct exposable *exposable = m->label->instantiate(m->label, &tags); - tag_set_destroy(&tags); - mtx_unlock(&mod->lock); - - return exposable; -} - -static struct exposable * -content(struct module *mod) -{ - const struct private *m = mod->private; - const struct client *client = m->context.current_client; - - if (client == NULL) { - return content_empty(mod); - } - - const struct metadata *metadata = &client->property.metadata; - const struct property *property = &client->property; - - /* Calculate the current playback position */ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - - uint64_t elapsed_us = client->property.position_us; - uint64_t length_us = metadata->length_us; - - if (client->has_seeked_support && client->status == STATUS_PLAYING) { - elapsed_us += timespec_diff_us(&now, &client->seeked_when); - if (elapsed_us > length_us) { - LOG_DBG("dynamic update of elapsed overflowed: " - "elapsed=%" PRIu64 ", duration=%" PRIu64, - elapsed_us, length_us); - elapsed_us = length_us; - } - } - - /* Some clients can report misleading or incomplete updates to the - * playback position, potentially causing the position to exceed - * the length */ - if (elapsed_us > length_us) - elapsed_us = length_us = 0; - - char tag_pos_value[16] = {0}, tag_end_value[16] = {0}; - if (length_us > 0) { - format_usec_timestamp(elapsed_us, tag_pos_value, sizeof(tag_pos_value)); - format_usec_timestamp(length_us, tag_end_value, sizeof(tag_end_value)); - } - - char *tag_state_value = NULL; - switch (client->status) { - case STATUS_ERROR: - tag_state_value = "error"; - break; - case STATUS_OFFLINE: - tag_state_value = "offline"; - break; - case STATUS_PLAYING: - tag_state_value = "playing"; - break; - case STATUS_PAUSED: - tag_state_value = "paused"; - break; - case STATUS_STOPPED: - tag_state_value = "stopped"; - break; - } - - const char *tag_loop_value = (property->loop_status == NULL) ? "" : property->loop_status; - const char *tag_album_value = (metadata->album == NULL) ? "" : metadata->album; - const char *tag_artists_value = (tll_length(metadata->artists) <= 0) ? "" : tll_front(metadata->artists); - const char *tag_title_value = (metadata->title == NULL) ? "" : metadata->title; - const uint32_t tag_volume_value = (property->volume >= 0.995) ? 100 : 100 * property->volume; - const bool tag_shuffle_value = property->shuffle; - const enum tag_realtime_unit realtime_unit - = (client->has_seeked_support && client->status == STATUS_PLAYING) ? TAG_REALTIME_MSECS : TAG_REALTIME_NONE; - - mtx_lock(&mod->lock); - struct tag_set tags = { - .tags = (struct tag *[]){ - tag_new_bool(mod, "has_seeked_support", client->has_seeked_support), - tag_new_bool(mod, "shuffle", tag_shuffle_value), - tag_new_int_range(mod, "volume", tag_volume_value, 0, 100), - tag_new_string(mod, "album", tag_album_value), - tag_new_string(mod, "artist", tag_artists_value), - tag_new_string(mod, "end", tag_end_value), - tag_new_string(mod, "loop", tag_loop_value), - tag_new_string(mod, "pos", tag_pos_value), - tag_new_string(mod, "state", tag_state_value), - tag_new_string(mod, "title", tag_title_value), - tag_new_int_realtime( - mod, "elapsed", elapsed_us, 0, length_us, realtime_unit), - }, - .count = 11, - }; - - struct exposable *exposable = m->label->instantiate(m->label, &tags); - tag_set_destroy(&tags); - mtx_unlock(&mod->lock); - - return exposable; -} - -struct refresh_context { - struct module *mod; - int abort_fd; - long milli_seconds; -}; - -static int -refresh_in_thread(void *arg) -{ - struct refresh_context *ctx = arg; - struct module *mod = ctx->mod; - - /* Extract data from context so that we can free it */ - int abort_fd = ctx->abort_fd; - long milli_seconds = ctx->milli_seconds; - free(ctx); - - /*LOG_DBG("going to sleep for %ldms", milli_seconds);*/ - - /* Wait for timeout, or abort signal */ - struct pollfd fds[] = {{.fd = abort_fd, .events = POLLIN}}; - int r = poll(fds, 1, milli_seconds); - - if (r < 0) { - LOG_ERRNO("failed to poll() in refresh thread"); - return 1; - } - - /* Aborted? */ - if (r == 1) { - assert(fds[0].revents & POLLIN); - /*LOG_DBG("refresh thread aborted");*/ - return 0; - } - - LOG_DBG("timed refresh"); - mod->bar->refresh(mod->bar); - - return 0; -} - -static bool -refresh_in(struct module *mod, long milli_seconds) -{ - struct private *m = mod->private; - - /* Abort currently running refresh thread */ - if (m->refresh_thread_id != 0) { - /*LOG_DBG("aborting current refresh thread");*/ - - /* Signal abort to thread */ - assert(m->refresh_abort_fd != -1); - if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) { - LOG_ERRNO("failed to signal abort to refresher thread"); - return false; - } - - /* Wait for it to finish */ - int res; - thrd_join(m->refresh_thread_id, &res); - - /* Close and cleanup */ - close(m->refresh_abort_fd); - m->refresh_abort_fd = -1; - m->refresh_thread_id = 0; - } - - /* Create a new eventfd, to be able to signal abort to the thread */ - int abort_fd = eventfd(0, EFD_CLOEXEC); - if (abort_fd == -1) { - LOG_ERRNO("failed to create eventfd"); - return false; - } - - /* Thread context */ - struct refresh_context *ctx = malloc(sizeof(*ctx)); - ctx->mod = mod; - ctx->abort_fd = m->refresh_abort_fd = abort_fd; - ctx->milli_seconds = milli_seconds; - - /* Create thread */ - int r = thrd_create(&m->refresh_thread_id, &refresh_in_thread, ctx); - - if (r != thrd_success) { - LOG_ERR("failed to create refresh thread"); - close(m->refresh_abort_fd); - m->refresh_abort_fd = -1; - m->refresh_thread_id = 0; - free(ctx); - } - - /* Detach - we don't want to have to thrd_join() it */ - // thrd_detach(tid); - return r == 0; -} - -static int -run(struct module *mod) -{ - const struct bar *bar = mod->bar; - struct private *m = mod->private; - - if (!context_setup(&m->context)) { - LOG_ERR("Failed to setup context"); - return -1; - } - - struct context *context = &m->context; - - int ret = 0; - bool aborted = false; - while (ret == 0 && !aborted) { - const uint32_t timeout_ms = 50; - struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}}; - - /* Check for abort event */ - if (poll(fds, 1, timeout_ms) < 0) { - if (errno == EINTR) - continue; - - LOG_ERRNO("failed to poll"); - break; - } - - if (fds[0].revents & POLLIN) { - aborted = true; - break; - } - - if (!context_process_events(context, m->timeout_ms)) { - aborted = true; - break; - } - - /* Process dynamic updates, received through the contexts - * monitor connection. The 'upate_message' attribute is set - * inside the contexts event callback, if there are any - * updates to be processed. */ - if (context->has_update) { - assert(context->current_client != NULL); - assert(context->update_message != NULL); - - context->has_update = false; - aborted = !update_status_from_message(mod, context->update_message); - context->update_message = sd_bus_message_unref(context->update_message); - } - - bar->refresh(bar); - } - - LOG_DBG("exiting"); - return ret; -} - -static const char * -description(const struct module *mod) -{ - return "mpris"; -} - -static struct module * -mpris_new(const struct yml_node *ident_list, size_t timeout_ms, struct particle *label) -{ - struct private *priv = calloc(1, sizeof(*priv)); - priv->label = label; - priv->timeout_ms = timeout_ms; - priv->context.mpd_config = priv; - - size_t i = 0; - for (struct yml_list_iter iter = yml_list_iter(ident_list); iter.node != NULL; yml_list_next(&iter), i++) { - char *string = strdup(yml_value_as_string(iter.node)); - tll_push_back(priv->identity_list, string); - } - - struct module *mod = module_common_new(); - mod->private = priv; - mod->run = &run; - mod->destroy = &destroy; - mod->content = &content; - mod->description = &description; - mod->refresh_in = &refresh_in; - return mod; -} - -static struct module * -from_conf(const struct yml_node *node, struct conf_inherit inherited) -{ - const struct yml_node *ident_list = yml_get_value(node, "identities"); - const struct yml_node *query_timeout = yml_get_value(node, "query_timeout"); - const struct yml_node *c = yml_get_value(node, "content"); - - size_t timeout_ms = DEFAULT_QUERY_TIMEOUT_MS; - if (query_timeout != NULL) - timeout_ms = yml_value_as_int(query_timeout) * 1000; - - return mpris_new(ident_list, timeout_ms, conf_to_particle(c, inherited)); -} - -static bool -conf_verify_indentities(keychain_t *chain, const struct yml_node *node) -{ - return conf_verify_list(chain, node, &conf_verify_string); -} - -static bool -verify_conf(keychain_t *chain, const struct yml_node *node) -{ - static const struct attr_info attrs[] = { - {"identities", true, &conf_verify_indentities}, - {"query_timeout", false, &conf_verify_unsigned}, - MODULE_COMMON_ATTRS, - }; - - return conf_verify_dict(chain, node, attrs); -} - -const struct module_iface module_mpris_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_mpris_iface"))); -#endif diff --git a/modules/network.c b/modules/network.c index 46a3148..17358a6 100644 --- a/modules/network.c +++ b/modules/network.c @@ -1,42 +1,38 @@ -#include -#include -#include #include #include +#include #include #include +#include #include +#include +#include #include #include -#include -#include #include +#include #include -#include #include -#include #include -#include +#include #include +#include #include #define LOG_MODULE "network" -#define LOG_ENABLE_DBG 1 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" +#define LOG_ENABLE_DBG 0 #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../module.h" -#include "../particles/dynlist.h" #include "../plugin.h" -#define max(x, y) ((x) > (y) ? (x) : (y)) - -static const long min_poll_interval = 250; +#define UNUSED __attribute__((unused)) struct rt_stats_msg { struct rtmsg rth; @@ -51,17 +47,28 @@ struct af_addr { } addr; }; -struct iface { - char *name; - char *type; /* ARPHRD_NNN */ - char *kind; /* IFLA_LINKINFO::IFLA_INFO_KIND */ +struct private { + char *iface; + struct particle *label; + int poll_interval; - uint32_t get_stats_seq_nr; + int genl_sock; + int rt_sock; + int urandom_fd; - int index; + struct { + uint16_t family_id; + uint32_t get_interface_seq_nr; + uint32_t get_station_seq_nr; + uint32_t get_scan_seq_nr; + } nl80211; + + bool get_addresses; + + int ifindex; uint8_t mac[6]; bool carrier; - uint8_t state; /* IFLA_OPERSTATE */ + uint8_t state; /* IFLA_OPERSTATE */ /* IPv4 and IPv6 addresses */ tll(struct af_addr) addrs; @@ -72,46 +79,13 @@ struct iface { uint32_t rx_bitrate; uint32_t tx_bitrate; - double ul_speed; + uint64_t ul_speed; uint64_t ul_bits; - double dl_speed; + uint64_t dl_speed; uint64_t dl_bits; }; -struct private -{ - struct particle *label; - int poll_interval; - - int left_spacing; - int right_spacing; - - bool get_addresses; - - int genl_sock; - int rt_sock; - int urandom_fd; - - struct { - uint16_t family_id; - uint32_t get_interface_seq_nr; - uint32_t get_scan_seq_nr; - } nl80211; - - tll(struct iface) ifaces; -}; - -static void -free_iface(struct iface iface) -{ - tll_free(iface.addrs); - free(iface.ssid); - free(iface.kind); - free(iface.type); - free(iface.name); -} - static void destroy(struct module *mod) { @@ -124,19 +98,22 @@ 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_free(m->addrs); + free(m->ssid); + free(m->iface); free(m); + module_default_destroy(mod); } static const char * description(const struct module *mod) { - return "network"; + static char desc[32]; + const struct private *m = mod->private; + + snprintf(desc, sizeof(desc), "net(%s)", m->iface); + return desc; } static struct exposable * @@ -146,97 +123,58 @@ content(struct module *mod) mtx_lock(&mod->lock); - struct exposable *exposables[max(tll_length(m->ifaces), 1)]; - size_t idx = 0; - - tll_foreach(m->ifaces, it) - { - struct iface *iface = &it->item; - - const char *state = NULL; - switch (iface->state) { - case IF_OPER_UNKNOWN: - state = "unknown"; - break; - case IF_OPER_NOTPRESENT: - state = "not present"; - break; - case IF_OPER_DOWN: - state = "down"; - break; - case IF_OPER_LOWERLAYERDOWN: - state = "lower layers down"; - break; - case IF_OPER_TESTING: - state = "testing"; - break; - case IF_OPER_DORMANT: - state = "dormant"; - break; - case IF_OPER_UP: - state = "up"; - break; - default: - state = "unknown"; - break; - } - - char mac_str[6 * 2 + 5 + 1]; - char ipv4_str[INET_ADDRSTRLEN] = {0}; - char ipv6_str[INET6_ADDRSTRLEN] = {0}; - - snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", iface->mac[0], iface->mac[1], iface->mac[2], - iface->mac[3], iface->mac[4], iface->mac[5]); - - /* TODO: this exposes the *last* added address of each kind. Can - * we expose all in some way? */ - tll_foreach(iface->addrs, it) - { - if (it->item.family == AF_INET) - inet_ntop(AF_INET, &it->item.addr.ipv4, ipv4_str, sizeof(ipv4_str)); - else if (it->item.family == AF_INET6) - if (!IN6_IS_ADDR_LINKLOCAL(&it->item.addr.ipv6)) - inet_ntop(AF_INET6, &it->item.addr.ipv6, ipv6_str, sizeof(ipv6_str)); - } - - int quality = 0; - if (iface->signal_strength_dbm != 0) { - if (iface->signal_strength_dbm <= -100) - quality = 0; - else if (iface->signal_strength_dbm >= -50) - quality = 100; - else - quality = 2 * (iface->signal_strength_dbm + 100); - } - - 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), - tag_new_string(mod, "mac", mac_str), - tag_new_string(mod, "ipv4", ipv4_str), - tag_new_string(mod, "ipv6", ipv6_str), - tag_new_string(mod, "ssid", iface->ssid), - tag_new_int(mod, "signal", iface->signal_strength_dbm), - tag_new_int_range(mod, "quality", quality, 0, 100), - tag_new_int(mod, "rx-bitrate", iface->rx_bitrate), - tag_new_int(mod, "tx-bitrate", iface->tx_bitrate), - tag_new_float(mod, "dl-speed", iface->dl_speed), - tag_new_float(mod, "ul-speed", iface->ul_speed), - }, - .count = 16, - }; - exposables[idx++] = m->label->instantiate(m->label, &tags); - tag_set_destroy(&tags); + const char *state = NULL; + switch (m->state) { + case IF_OPER_UNKNOWN: state = "unknown"; break; + case IF_OPER_NOTPRESENT: state = "not present"; break; + case IF_OPER_DOWN: state = "down"; break; + case IF_OPER_LOWERLAYERDOWN: state = "lower layers down"; break; + case IF_OPER_TESTING: state = "testing"; break; + case IF_OPER_DORMANT: state = "dormant"; break; + case IF_OPER_UP: state = "up"; break; + default: state = "unknown"; break; } + char mac_str[6 * 2 + 5 + 1]; + char ipv4_str[INET_ADDRSTRLEN] = {0}; + char ipv6_str[INET6_ADDRSTRLEN] = {0}; + + snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", + m->mac[0], m->mac[1], m->mac[2], m->mac[3], m->mac[4], m->mac[5]); + + /* TODO: this exposes the *last* added address of each kind. Can + * we expose all in some way? */ + tll_foreach(m->addrs, it) { + if (it->item.family == AF_INET) + inet_ntop(AF_INET, &it->item.addr.ipv4, ipv4_str, sizeof(ipv4_str)); + else if (it->item.family == AF_INET6) + inet_ntop(AF_INET6, &it->item.addr.ipv6, ipv6_str, sizeof(ipv6_str)); + } + + struct tag_set tags = { + .tags = (struct tag *[]){ + tag_new_string(mod, "name", m->iface), + tag_new_int(mod, "index", m->ifindex), + tag_new_bool(mod, "carrier", m->carrier), + tag_new_string(mod, "state", state), + tag_new_string(mod, "mac", mac_str), + tag_new_string(mod, "ipv4", ipv4_str), + tag_new_string(mod, "ipv6", ipv6_str), + tag_new_string(mod, "ssid", m->ssid), + tag_new_int(mod, "signal", m->signal_strength_dbm), + tag_new_int(mod, "rx-bitrate", m->rx_bitrate), + tag_new_int(mod, "tx-bitrate", m->tx_bitrate), + tag_new_float(mod, "dl-speed", m->dl_speed), + tag_new_float(mod, "ul-speed", m->ul_speed), + }, + .count = 13, + }; + mtx_unlock(&mod->lock); - return dynlist_exposable_new(exposables, idx, m->left_spacing, m->right_spacing); + struct exposable *exposable = m->label->instantiate(m->label, &tags); + tag_set_destroy(&tags); + return exposable; } /* Returns a value suitable for nl_pid/nlmsg_pid */ @@ -281,7 +219,8 @@ netlink_connect_genl(void) } const struct sockaddr_nl addr = { - .nl_family = AF_NETLINK, .nl_pid = nl_pid_value(), + .nl_family = AF_NETLINK, + .nl_pid = nl_pid_value(), /* no multicast notifications by default, will be added later */ }; @@ -297,8 +236,10 @@ netlink_connect_genl(void) static bool send_nlmsg(int sock, const void *nlmsg, size_t len) { - int r = sendto(sock, nlmsg, len, 0, (struct sockaddr *)&(struct sockaddr_nl){.nl_family = AF_NETLINK}, - sizeof(struct sockaddr_nl)); + int r = sendto( + sock, nlmsg, len, 0, + (struct sockaddr *)&(struct sockaddr_nl){.nl_family = AF_NETLINK}, + sizeof(struct sockaddr_nl)); return r == len; } @@ -324,7 +265,8 @@ send_rt_request(struct private *m, int request) }; if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) { - LOG_ERRNO("failed to send netlink RT request (%d)", request); + LOG_ERRNO("%s: failed to send netlink RT request (%d)", + m->iface, request); return false; } @@ -332,21 +274,8 @@ send_rt_request(struct private *m, int request) } static bool -send_rt_getstats_request(struct private *m, struct iface *iface) +send_rt_getstats_request(struct private *m) { - if (iface->get_stats_seq_nr > 0) { - LOG_DBG("%s: RT get-stats request already in progress", iface->name); - return true; - } - - LOG_DBG("%s: sending RT get-stats request", iface->name); - - uint32_t seq; - if (read(m->urandom_fd, &seq, sizeof(seq)) != sizeof(seq)) { - LOG_ERRNO("failed to read from /dev/urandom"); - return false; - } - struct { struct nlmsghdr hdr; struct if_stats_msg rt; @@ -355,22 +284,22 @@ send_rt_getstats_request(struct private *m, struct iface *iface) .nlmsg_len = NLMSG_LENGTH(sizeof(req.rt)), .nlmsg_type = RTM_GETSTATS, .nlmsg_flags = NLM_F_REQUEST, - .nlmsg_seq = seq, + .nlmsg_seq = 1, .nlmsg_pid = nl_pid_value(), }, .rt = { - .ifindex = iface->index, + .ifindex = m->ifindex, .filter_mask = IFLA_STATS_LINK_64, .family = AF_UNSPEC, }, }; if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) { - LOG_ERRNO("%s: failed to send netlink RT getstats request (%d)", iface->name, RTM_GETSTATS); + LOG_ERRNO("%s: failed to send netlink RT getstats request (%d)", + m->iface, RTM_GETSTATS); return false; } - iface->get_stats_seq_nr = seq; return true; } @@ -412,11 +341,14 @@ send_ctrl_get_family_request(struct private *m) }, }; - _Static_assert(sizeof(req.msg.family_name_attr) == NLA_HDRLEN + NLA_ALIGN(sizeof(req.msg.family_name_attr.data)), - ""); + _Static_assert( + sizeof(req.msg.family_name_attr) == + NLA_HDRLEN + NLA_ALIGN(sizeof(req.msg.family_name_attr.data)), + ""); if (!send_nlmsg(m->genl_sock, &req, req.hdr.nlmsg_len)) { - LOG_ERRNO("failed to send netlink ctrl-get-family request"); + LOG_ERRNO("%s: failed to send netlink ctrl-get-family request", + m->iface); return false; } @@ -424,69 +356,11 @@ send_ctrl_get_family_request(struct private *m) } static bool -send_nl80211_request(struct private *m, uint8_t cmd, uint32_t seq) +send_nl80211_request(struct private *m, uint8_t cmd, uint16_t flags, uint32_t seq) { - if (m->nl80211.family_id == (uint16_t)-1) + if (m->ifindex < 0) return false; - const struct { - struct nlmsghdr hdr; - struct { - struct genlmsghdr genl; - } msg __attribute__((aligned(NLMSG_ALIGNTO))); - } req = { - .hdr = { - .nlmsg_len = NLMSG_LENGTH(sizeof(req.msg)), - .nlmsg_type = m->nl80211.family_id, - .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, - .nlmsg_seq = seq, - .nlmsg_pid = nl_pid_value(), - }, - - .msg = { - .genl = { - .cmd = cmd, - .version = 1, - }, - }, - }; - - if (!send_nlmsg(m->genl_sock, &req, req.hdr.nlmsg_len)) { - LOG_ERRNO("failed to send netlink nl80211 get-inteface request"); - return false; - } - - return true; -} - -static bool -send_nl80211_get_interface(struct private *m) -{ - if (m->nl80211.get_interface_seq_nr > 0) { - LOG_DBG("nl80211 get-interface request already in progress"); - return true; - } - - uint32_t seq; - if (read(m->urandom_fd, &seq, sizeof(seq)) != sizeof(seq)) { - LOG_ERRNO("failed to read from /dev/urandom"); - return false; - } - - LOG_DBG("sending nl80211 get-interface request %d", seq); - - if (!send_nl80211_request(m, NL80211_CMD_GET_INTERFACE, seq)) - return false; - - m->nl80211.get_interface_seq_nr = seq; - return true; -} - -static bool -send_nl80211_get_station(struct private *m, struct iface *iface) -{ - LOG_DBG("sending nl80211 get-station request"); - if (m->nl80211.family_id == (uint16_t)-1) return false; @@ -503,14 +377,14 @@ send_nl80211_get_station(struct private *m, struct iface *iface) .hdr = { .nlmsg_len = NLMSG_LENGTH(sizeof(req.msg)), .nlmsg_type = m->nl80211.family_id, - .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, - .nlmsg_seq = 1, + .nlmsg_flags = flags, + .nlmsg_seq = seq, .nlmsg_pid = nl_pid_value(), }, .msg = { .genl = { - .cmd = NL80211_CMD_GET_STATION, + .cmd = cmd, .version = 1, }, @@ -520,13 +394,14 @@ send_nl80211_get_station(struct private *m, struct iface *iface) .nla_len = sizeof(req.msg.ifindex), }, - .index = iface->index, + .index = m->ifindex, }, }, }; if (!send_nlmsg(m->genl_sock, &req, req.hdr.nlmsg_len)) { - LOG_ERRNO("failed to send netlink nl80211 get-inteface request"); + LOG_ERRNO("%s: failed to send netlink nl80211 get-inteface request", + m->iface); return false; } @@ -534,197 +409,167 @@ send_nl80211_get_station(struct private *m, struct iface *iface) } static bool -send_nl80211_get_scan(struct private *m) +send_nl80211_get_interface(struct private *m) { - if (m->nl80211.get_scan_seq_nr > 0) { - LOG_ERR("nl80211 get-scan request already in progress"); + if (m->nl80211.get_interface_seq_nr > 0) { + LOG_DBG( + "%s: nl80211 get-interface request already in progress", m->iface); return true; } + LOG_DBG("%s: sending nl80211 get-interface request", m->iface); + uint32_t seq; if (read(m->urandom_fd, &seq, sizeof(seq)) != sizeof(seq)) { LOG_ERRNO("failed to read from /dev/urandom"); return false; } - LOG_DBG("sending nl80211 get-scan request %d", seq); - - if (!send_nl80211_request(m, NL80211_CMD_GET_SCAN, seq)) + if (send_nl80211_request(m, NL80211_CMD_GET_INTERFACE, NLM_F_REQUEST, seq)) { + m->nl80211.get_interface_seq_nr = seq; + return true; + } else return false; - - m->nl80211.get_scan_seq_nr = seq; - 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) +send_nl80211_get_station(struct private *m) { - const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN; - const uint8_t *end = (const uint8_t *)genl + len; + if (m->nl80211.get_station_seq_nr > 0) { + LOG_DBG( + "%s: nl80211 get-station request already in progress", m->iface); + return true; + } - 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; + LOG_DBG("%s: sending nl80211 get-station request", m->iface); + + uint32_t seq; + if (read(m->urandom_fd, &seq, sizeof(seq)) != sizeof(seq)) { + LOG_ERRNO("failed to read from /dev/urandom"); + return false; + } + + if (send_nl80211_request( + m, NL80211_CMD_GET_STATION, NLM_F_REQUEST | NLM_F_DUMP, seq)) + { + m->nl80211.get_station_seq_nr = seq; + return true; + } else + return false; +} + +static bool +send_nl80211_get_scan(struct private *m) +{ + if (m->nl80211.get_scan_seq_nr > 0) { + LOG_ERR( + "%s: nl80211 get-scan request already in progress", m->iface); + return true; + } + + LOG_DBG("%s: sending nl80211 get-scan request", m->iface); + + uint32_t seq; + if (read(m->urandom_fd, &seq, sizeof(seq)) != sizeof(seq)) { + LOG_ERRNO("failed to read from /dev/urandom"); + return false; + } + + if (send_nl80211_request( + m, NL80211_CMD_GET_SCAN, NLM_F_REQUEST | NLM_F_DUMP, seq)) + { + m->nl80211.get_scan_seq_nr = seq; + return true; + } else + return false; +} + +static bool +find_my_ifindex(struct module *mod, const struct ifinfomsg *msg, size_t len) +{ + struct private *m = mod->private; + + for (const struct rtattr *attr = IFLA_RTA(msg); + RTA_OK(attr, len); + attr = RTA_NEXT(attr, len)) + { + switch (attr->rta_type) { + case IFLA_IFNAME: + if (strcmp((const char *)RTA_DATA(attr), m->iface) == 0) { + LOG_INFO("%s: ifindex=%d", m->iface, msg->ifi_index); + + mtx_lock(&mod->lock); + m->ifindex = msg->ifi_index; + mtx_unlock(&mod->lock); + + send_nl80211_get_interface(m); + send_nl80211_get_station(m); + return true; + } - 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; + return false; } static void -handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size_t len) +handle_link(struct module *mod, uint16_t type, + const struct ifinfomsg *msg, size_t len) { assert(type == RTM_NEWLINK || type == RTM_DELLINK); struct private *m = mod->private; - if (type == RTM_DELLINK) { - tll_foreach(m->ifaces, it) - { - if (msg->ifi_index != it->item.index) - continue; - mtx_lock(&mod->lock); - tll_remove_and_free(m->ifaces, it, free_iface); - mtx_unlock(&mod->lock); - break; + if (m->ifindex == -1) { + /* We don't know our own ifindex yet. Let's see if we can find + * it in the message */ + if (!find_my_ifindex(mod, msg, len)) { + /* Nope, message wasn't for us (IFLA_IFNAME mismatch) */ + return; } + } - mod->bar->refresh(mod->bar); + assert(m->ifindex >= 0); + + if (msg->ifi_index != m->ifindex) { + /* Not for us */ return; } - struct iface *iface = NULL; - tll_foreach(m->ifaces, it) + bool update_bar = false; + + for (const struct rtattr *attr = IFLA_RTA(msg); + RTA_OK(attr, len); + attr = RTA_NEXT(attr, len)) { - if (msg->ifi_index != it->item.index) - continue; - iface = &it->item; - break; - } - - 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(), - })); - mtx_unlock(&mod->lock); - iface = &tll_back(m->ifaces); - } - - for (const struct rtattr *attr = IFLA_RTA(msg); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { switch (attr->rta_type) { - 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); - mtx_unlock(&mod->lock); - break; - case IFLA_OPERSTATE: { uint8_t operstate = *(const uint8_t *)RTA_DATA(attr); - if (iface->state == operstate) + if (m->state == operstate) break; - LOG_DBG("%s: IFLA_OPERSTATE: %hhu -> %hhu", iface->name, iface->state, operstate); + LOG_DBG("%s: IFLA_OPERSTATE: %hhu -> %hhu", m->iface, m->state, operstate); mtx_lock(&mod->lock); - iface->state = operstate; + m->state = operstate; mtx_unlock(&mod->lock); + update_bar = true; break; } case IFLA_CARRIER: { uint8_t carrier = *(const uint8_t *)RTA_DATA(attr); - if (iface->carrier == carrier) + if (m->carrier == carrier) break; - LOG_DBG("%s: IFLA_CARRIER: %hhu -> %hhu", iface->name, iface->carrier, carrier); + LOG_DBG("%s: IFLA_CARRIER: %hhu -> %hhu", m->iface, m->carrier, carrier); mtx_lock(&mod->lock); - iface->carrier = carrier; + m->carrier = carrier; mtx_unlock(&mod->lock); + update_bar = true; break; } @@ -733,62 +578,47 @@ handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size break; const uint8_t *mac = RTA_DATA(attr); - if (memcmp(iface->mac, mac, sizeof(iface->mac)) == 0) + if (memcmp(m->mac, mac, sizeof(m->mac)) == 0) break; 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]); + m->iface, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); mtx_lock(&mod->lock); - memcpy(iface->mac, mac, sizeof(iface->mac)); + memcpy(m->mac, mac, sizeof(m->mac)); mtx_unlock(&mod->lock); - break; - } - - case IFLA_LINKINFO: { - foreach_nlattr_nested( - mod, iface, RTA_DATA(attr), RTA_PAYLOAD(attr), - &parse_linkinfo, NULL); + update_bar = true; break; } } } - assert(iface->name != NULL); - - /* Reset address initialization */ - m->get_addresses = true; - - send_nl80211_get_interface(m); - mod->bar->refresh(mod->bar); + if (update_bar) + mod->bar->refresh(mod->bar); } static void -handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, size_t len) +handle_address(struct module *mod, uint16_t type, + const struct ifaddrmsg *msg, size_t len) { assert(type == RTM_NEWADDR || type == RTM_DELADDR); struct private *m = mod->private; - bool update_bar = false; + assert(m->ifindex >= 0); - struct iface *iface = NULL; - - tll_foreach(m->ifaces, it) - { - if (msg->ifa_index != it->item.index) - continue; - iface = &it->item; - break; - } - - if (iface == NULL) { - LOG_ERR("failed to find network interface with index %d. Probably a yambar bug", msg->ifa_index); + if (msg->ifa_index != m->ifindex) { + /* Not for us */ return; } - for (const struct rtattr *attr = IFA_RTA(msg); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { + bool update_bar = false; + + for (const struct rtattr *attr = IFA_RTA(msg); + RTA_OK(attr, len); + attr = RTA_NEXT(attr, len)) + { switch (attr->rta_type) { case IFA_ADDRESS: { const void *raw_addr = RTA_DATA(attr); @@ -798,21 +628,21 @@ handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, s char s[INET6_ADDRSTRLEN]; inet_ntop(msg->ifa_family, raw_addr, s, sizeof(s)); #endif - LOG_DBG("%s: IFA_ADDRESS (%s): %s", iface->name, type == RTM_NEWADDR ? "add" : "del", s); + LOG_DBG("%s: IFA_ADDRESS (%s): %s", m->iface, + type == RTM_NEWADDR ? "add" : "del", s); mtx_lock(&mod->lock); if (type == RTM_DELADDR) { /* Find address in our list and remove it */ - tll_foreach(iface->addrs, it) - { + tll_foreach(m->addrs, it) { if (it->item.family != msg->ifa_family) continue; if (memcmp(&it->item.addr, raw_addr, addr_len) != 0) continue; - tll_remove(iface->addrs, it); + tll_remove(m->addrs, it); update_bar = true; break; } @@ -820,7 +650,7 @@ handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, s /* Append address to our list */ struct af_addr a = {.family = msg->ifa_family}; memcpy(&a.addr, raw_addr, addr_len); - tll_push_back(iface->addrs, a); + tll_push_back(m->addrs, a); update_bar = true; } @@ -834,15 +664,64 @@ 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, const struct genlmsghdr *genl, size_t len, + bool (*cb)(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len)) +{ + 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, type, nested, payload, attr->nla_len - NLA_HDRLEN)) + return false; + } + + return true; +} + +static bool +foreach_nlattr_nested(struct module *mod, const void *parent_payload, size_t len, + bool (*cb)(struct module *mod, 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, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx)) + return false; + } + + return true; +} + struct mcast_group { uint32_t id; const char *name; }; static bool -parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len, - void *_ctx) +parse_mcast_group(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len, void *_ctx) { + struct private *m = mod->private; struct mcast_group *ctx = _ctx; switch (type) { @@ -857,9 +736,8 @@ parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool n } default: - LOG_WARN("unrecognized GENL MCAST GRP attribute: " - "type=%hu, nested=%d, len=%zu", - type, nested, len); + LOG_WARN("%s: unrecognized GENL MCAST GRP attribute: " + "type=%hu, nested=%d, len=%zu", m->iface, type, nested, len); break; } @@ -867,13 +745,13 @@ parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool n } static bool -parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len, - void *_ctx) +parse_mcast_groups(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len, void *_ctx) { struct private *m = mod->private; struct mcast_group group = {0}; - foreach_nlattr_nested(mod, NULL, payload, len, &parse_mcast_group, &group); + foreach_nlattr_nested(mod, payload, len, &parse_mcast_group, &group); LOG_DBG("MCAST: %s -> %u", group.name, group.id); @@ -883,7 +761,9 @@ parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool * CONNECT/DISCONNECT events. */ - int r = setsockopt(m->genl_sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group.id, sizeof(int)); + int r = setsockopt( + m->genl_sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, + &group.id, sizeof(int)); if (r < 0) LOG_ERRNO("failed to joint the nl80211 MLME mcast group"); @@ -893,8 +773,8 @@ parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool } static bool -handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len, - void *_ctx) +handle_genl_ctrl(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len) { struct private *m = mod->private; @@ -902,21 +782,21 @@ handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool ne case CTRL_ATTR_FAMILY_ID: { m->nl80211.family_id = *(const uint16_t *)payload; send_nl80211_get_interface(m); + send_nl80211_get_station(m); break; } case CTRL_ATTR_FAMILY_NAME: - // LOG_INFO("NAME: %.*s (%zu bytes)", (int)len, (const char *)payload, len); + //LOG_INFO("NAME: %.*s (%zu bytes)", (int)len, (const char *)payload, len); break; case CTRL_ATTR_MCAST_GROUPS: - foreach_nlattr_nested(mod, NULL, payload, len, &parse_mcast_groups, NULL); + foreach_nlattr_nested(mod, payload, len, &parse_mcast_groups, NULL); break; default: - LOG_DBG("unrecognized GENL CTRL attribute: " - "type=%hu, nested=%d, len=%zu", - type, nested, len); + LOG_DBG("%s: unrecognized GENL CTRL attribute: " + "type=%hu, nested=%d, len=%zu", m->iface, type, nested, len); break; } @@ -924,49 +804,46 @@ handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool ne } static bool -find_nl80211_iface(struct module *mod, struct iface *_iface, uint16_t type, bool nested, const void *payload, - size_t len, void *ctx) +check_for_nl80211_ifindex(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len) { struct private *m = mod->private; - struct iface **iface = ctx; switch (type) { case NL80211_ATTR_IFINDEX: - if (*iface != NULL) - if (*(uint32_t *)payload == (*iface)->index) - return false; - tll_foreach(m->ifaces, it) - { - if (*(uint32_t *)payload != it->item.index) - continue; - *iface = &it->item; - return false; - } - LOG_ERR("could not find interface with index %d", *(uint32_t *)payload); - break; + return *(uint32_t *)payload == m->ifindex; } return true; } static bool -handle_nl80211_new_interface(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, - size_t len, void *_ctx) +nl80211_is_for_us(struct module *mod, const struct genlmsghdr *genl, + size_t msg_size) { + return foreach_nlattr(mod, genl, msg_size, &check_for_nl80211_ifindex); +} + +static bool +handle_nl80211_new_interface(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len) +{ + struct private *m = mod->private; + switch (type) { case NL80211_ATTR_IFINDEX: - assert(*(uint32_t *)payload == iface->index); + assert(*(uint32_t *)payload == m->ifindex); break; case NL80211_ATTR_SSID: { const char *ssid = payload; - if (iface->ssid == NULL || strncmp(iface->ssid, ssid, len) != 0) - LOG_INFO("%s: SSID: %.*s", iface->name, (int)len, ssid); + if (m->ssid == NULL || strncmp(m->ssid, ssid, len) != 0) + LOG_INFO("%s: SSID: %.*s", m->iface, (int)len, ssid); mtx_lock(&mod->lock); - free(iface->ssid); - iface->ssid = strndup(ssid, len); + free(m->ssid); + m->ssid = strndup(ssid, len); mtx_unlock(&mod->lock); mod->bar->refresh(mod->bar); @@ -975,8 +852,7 @@ handle_nl80211_new_interface(struct module *mod, struct iface *iface, uint16_t t default: LOG_DBG("%s: unrecognized nl80211 attribute: " - "type=%hu, nested=%d, len=%zu", - iface->name, type, nested, len); + "type=%hu, nested=%d, len=%zu", m->iface, type, nested, len); break; } @@ -988,9 +864,10 @@ struct rate_info_ctx { }; static bool -handle_nl80211_rate_info(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, - size_t len, void *_ctx) +handle_nl80211_rate_info(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len, void *_ctx) { + struct private *m UNUSED = mod->private; struct rate_info_ctx *ctx = _ctx; switch (type) { @@ -1011,8 +888,7 @@ handle_nl80211_rate_info(struct module *mod, struct iface *iface, uint16_t type, default: LOG_DBG("%s: unrecognized nl80211 rate info attribute: " - "type=%hu, nested=%d, len=%zu", - iface->name, type, nested, len); + "type=%hu, nested=%d, len=%zu", m->iface, type, nested, len); break; } @@ -1024,9 +900,10 @@ struct station_info_ctx { }; static bool -handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, - size_t len, void *_ctx) +handle_nl80211_station_info(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len, void *_ctx) { + struct private *m = mod->private; struct station_info_ctx *ctx = _ctx; switch (type) { @@ -1034,21 +911,23 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty LOG_DBG("signal strength (last): %hhd dBm", *(uint8_t *)payload); break; - case NL80211_STA_INFO_SIGNAL_AVG: + case NL80211_STA_INFO_SIGNAL_AVG: { LOG_DBG("signal strength (average): %hhd dBm", *(uint8_t *)payload); mtx_lock(&mod->lock); - iface->signal_strength_dbm = *(int8_t *)payload; + m->signal_strength_dbm = *(int8_t *)payload; mtx_unlock(&mod->lock); ctx->update_bar = true; break; + } case NL80211_STA_INFO_TX_BITRATE: { struct rate_info_ctx rctx = {0}; - foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_rate_info, &rctx); + foreach_nlattr_nested( + mod, payload, len, &handle_nl80211_rate_info, &rctx); LOG_DBG("TX bitrate: %.1f Mbit/s", rctx.bitrate / 1000. / 1000.); mtx_lock(&mod->lock); - iface->tx_bitrate = rctx.bitrate; + m->tx_bitrate = rctx.bitrate; mtx_unlock(&mod->lock); ctx->update_bar = true; break; @@ -1056,11 +935,12 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty case NL80211_STA_INFO_RX_BITRATE: { struct rate_info_ctx rctx = {0}; - foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_rate_info, &rctx); + foreach_nlattr_nested( + mod, payload, len, &handle_nl80211_rate_info, &rctx); LOG_DBG("RX bitrate: %.1f Mbit/s", rctx.bitrate / 1000. / 1000.); mtx_lock(&mod->lock); - iface->rx_bitrate = rctx.bitrate; + m->rx_bitrate = rctx.bitrate; mtx_unlock(&mod->lock); ctx->update_bar = true; break; @@ -1068,8 +948,7 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty default: LOG_DBG("%s: unrecognized nl80211 station info attribute: " - "type=%hu, nested=%d, len=%zu", - iface->name, type, nested, len); + "type=%hu, nested=%d, len=%zu", m->iface, type, nested, len); break; } @@ -1077,16 +956,16 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty } static bool -handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, - size_t len, void *_ctx) +handle_nl80211_new_station(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len) { - switch (type) { - case NL80211_ATTR_IFINDEX: - break; + struct private *m UNUSED = mod->private; + switch (type) { case NL80211_ATTR_STA_INFO: { struct station_info_ctx ctx = {0}; - foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_station_info, &ctx); + foreach_nlattr_nested( + mod, payload, len, &handle_nl80211_station_info, &ctx); if (ctx.update_bar) mod->bar->refresh(mod->bar); @@ -1095,8 +974,7 @@ handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t typ default: LOG_DBG("%s: unrecognized nl80211 attribute: " - "type=%hu, nested=%d, len=%zu", - iface->name, type, nested, len); + "type=%hu, nested=%d, len=%zu", m->iface, type, nested, len); break; } @@ -1104,22 +982,23 @@ handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t typ } static bool -handle_ies(struct module *mod, struct iface *iface, const void *_ies, size_t len) +handle_ies(struct module *mod, const void *_ies, size_t len) { + struct private *m = mod->private; const uint8_t *ies = _ies; while (len >= 2 && len - 2 >= ies[1]) { switch (ies[0]) { - case 0: { /* SSID */ + case 0: { /* SSID */ const char *ssid = (const char *)&ies[2]; const size_t ssid_len = ies[1]; - if (iface->ssid == NULL || strncmp(iface->ssid, ssid, ssid_len) != 0) - LOG_INFO("%s: SSID: %.*s", iface->name, (int)ssid_len, ssid); + if (m->ssid == NULL || strncmp(m->ssid, ssid, ssid_len) != 0) + LOG_INFO("%s: SSID: %.*s", m->iface, (int)ssid_len, ssid); mtx_lock(&mod->lock); - free(iface->ssid); - iface->ssid = strndup(ssid, ssid_len); + free(m->ssid); + m->ssid = strndup(ssid, ssid_len); mtx_unlock(&mod->lock); mod->bar->refresh(mod->bar); @@ -1141,9 +1020,10 @@ struct scan_results_context { }; static bool -handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len, - void *_ctx) +handle_nl80211_bss(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len, void *_ctx) { + struct private *m UNUSED = mod->private; struct scan_results_context *ctx = _ctx; switch (type) { @@ -1155,7 +1035,7 @@ handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool if (ctx->ies != NULL) { /* Deferred handling of BSS_INFORMATION_ELEMENTS */ - return handle_ies(mod, iface, ctx->ies, ctx->ies_size); + return handle_ies(mod, ctx->ies, ctx->ies_size); } } break; @@ -1163,7 +1043,7 @@ handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool case NL80211_BSS_INFORMATION_ELEMENTS: if (ctx->associated) - return handle_ies(mod, iface, payload, len); + return handle_ies(mod, payload, len); else { /* * We’re either not associated, or, we haven’t seen the @@ -1182,14 +1062,16 @@ handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool } static bool -handle_nl80211_scan_results(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, - size_t len, void *_ctx) +handle_nl80211_scan_results(struct module *mod, uint16_t type, bool nested, + const void *payload, size_t len) { + struct private *m UNUSED = mod->private; + struct scan_results_context ctx = {0}; switch (type) { case NL80211_ATTR_BSS: - foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_bss, &ctx); + foreach_nlattr_nested(mod, payload, len, &handle_nl80211_bss, &ctx); break; } @@ -1235,39 +1117,20 @@ netlink_receive_messages(int sock, void **reply, size_t *len) } static void -handle_stats(struct module *mod, uint32_t seq, struct rt_stats_msg *msg) +handle_stats(struct module *mod, struct rt_stats_msg *msg) { struct private *m = mod->private; + uint64_t ul_bits = msg->stats.tx_bytes*8; + uint64_t dl_bits = msg->stats.rx_bytes*8; - struct iface *iface = NULL; - - tll_foreach(m->ifaces, it) - { - if (seq != it->item.get_stats_seq_nr) - continue; - iface = &it->item; - /* Current request is now considered complete */ - iface->get_stats_seq_nr = 0; - break; + if (m->ul_bits != 0) { + m->ul_speed = (ul_bits - m->ul_bits) / m->poll_interval; } - - if (iface == NULL) { - LOG_ERR("Couldn't find iface"); - return; + if (m->dl_bits != 0) { + m->dl_speed = (dl_bits - m->dl_bits) / m->poll_interval; } - - uint64_t ul_bits = msg->stats.tx_bytes * 8; - uint64_t dl_bits = msg->stats.rx_bytes * 8; - - const double poll_interval_secs = (double)m->poll_interval / 1000.; - - if (iface->ul_bits != 0) - iface->ul_speed = (double)(ul_bits - iface->ul_bits) / poll_interval_secs; - if (iface->dl_bits != 0) - iface->dl_speed = (double)(dl_bits - iface->dl_bits) / poll_interval_secs; - - iface->ul_bits = ul_bits; - iface->dl_bits = dl_bits; + m->ul_bits = ul_bits; + m->dl_bits = dl_bits; } static bool @@ -1277,12 +1140,15 @@ parse_rt_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len) /* Process response */ for (; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) { - switch (hdr->nlmsg_type) { case NLMSG_DONE: + if (m->ifindex == -1) { + LOG_ERR("%s: failed to find interface", m->iface); + return false; + } /* Request initial list of IPv4/6 addresses */ - if (m->get_addresses) { + if (m->get_addresses && m->ifindex != -1) { m->get_addresses = false; send_rt_request(m, RTM_GETADDR); } @@ -1307,18 +1173,20 @@ parse_rt_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len) } case RTM_NEWSTATS: { struct rt_stats_msg *msg = NLMSG_DATA(hdr); - handle_stats(mod, hdr->nlmsg_seq, msg); + handle_stats(mod, msg); break; } - case NLMSG_ERROR: { + case NLMSG_ERROR:{ const struct nlmsgerr *err = NLMSG_DATA(hdr); - LOG_ERRNO_P(-err->error, "netlink RT reply"); + LOG_ERRNO_P(-err->error, "%s: netlink RT reply", m->iface); return false; } default: - LOG_WARN("unrecognized netlink message type: 0x%x", hdr->nlmsg_type); + LOG_WARN( + "%s: unrecognized netlink message type: 0x%x", + m->iface, hdr->nlmsg_type); return false; } } @@ -1330,49 +1198,42 @@ static bool parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len) { struct private *m = mod->private; - struct iface *iface = NULL; for (; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) { - if (hdr->nlmsg_type == GENL_ID_CTRL) { - assert(hdr->nlmsg_seq == 1); - const struct genlmsghdr *genl = NLMSG_DATA(hdr); - const size_t msg_size = NLMSG_PAYLOAD(hdr, 0); - foreach_nlattr(mod, NULL, genl, msg_size, &handle_genl_ctrl, NULL); - continue; - } - if (hdr->nlmsg_seq == m->nl80211.get_interface_seq_nr) { /* Current request is now considered complete */ m->nl80211.get_interface_seq_nr = 0; - - /* Can’t issue both get-station and get-scan at the - * same time. So, always run a get-scan when a - * get-station is complete */ - send_nl80211_get_scan(m); } if (hdr->nlmsg_type == NLMSG_DONE) { - if (hdr->nlmsg_seq == m->nl80211.get_scan_seq_nr) { + if (hdr->nlmsg_seq == m->nl80211.get_station_seq_nr) { + /* Current request is now considered complete */ + m->nl80211.get_station_seq_nr = 0; + } + + else if (hdr->nlmsg_seq == m->nl80211.get_scan_seq_nr) { /* Current request is now considered complete */ m->nl80211.get_scan_seq_nr = 0; - - tll_foreach(m->ifaces, it) send_nl80211_get_station(m, &it->item); } } + else if (hdr->nlmsg_type == GENL_ID_CTRL) { + const struct genlmsghdr *genl = NLMSG_DATA(hdr); + const size_t msg_size = NLMSG_PAYLOAD(hdr, 0); + foreach_nlattr(mod, genl, msg_size, &handle_genl_ctrl); + } + else if (hdr->nlmsg_type == m->nl80211.family_id) { const struct genlmsghdr *genl = NLMSG_DATA(hdr); const size_t msg_size = NLMSG_PAYLOAD(hdr, 0); switch (genl->cmd) { case NL80211_CMD_NEW_INTERFACE: - if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) - 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); + if (nl80211_is_for_us(mod, genl, msg_size)) { + LOG_DBG("%s: got interface information", m->iface); + foreach_nlattr( + mod, genl, msg_size, &handle_nl80211_new_interface); + } break; case NL80211_CMD_CONNECT: @@ -1386,41 +1247,49 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len) * * Thus, we need to explicitly request an update. */ - LOG_DBG("connected, requesting interface information"); - send_nl80211_get_interface(m); + if (nl80211_is_for_us(mod, genl, msg_size)) { + LOG_DBG("%s: connected, requesting interface information", + m->iface); + send_nl80211_get_interface(m); + send_nl80211_get_station(m); + } break; case NL80211_CMD_DISCONNECT: - if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) - continue; + if (nl80211_is_for_us(mod, genl, msg_size)) { + LOG_DBG("%s: disconnected, resetting SSID etc", m->iface); - LOG_DBG("%s: disconnected, resetting SSID etc", iface->name); - - mtx_lock(&mod->lock); - free(iface->ssid); - iface->ssid = NULL; - iface->signal_strength_dbm = 0; - iface->rx_bitrate = iface->tx_bitrate = 0; - mtx_unlock(&mod->lock); + mtx_lock(&mod->lock); + free(m->ssid); + m->ssid = NULL; + m->signal_strength_dbm = 0; + m->rx_bitrate = m->tx_bitrate = 0; + mtx_unlock(&mod->lock); + } break; case NL80211_CMD_NEW_STATION: - if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) - continue; + if (nl80211_is_for_us(mod, genl, msg_size)) { + LOG_DBG("%s: got station information", m->iface); + foreach_nlattr(mod, genl, msg_size, &handle_nl80211_new_station); + } - LOG_DBG("%s: got station information", iface->name); - foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_new_station, NULL); + LOG_DBG("%s: signal: %d dBm, RX=%u Mbit/s, TX=%u Mbit/s", + m->iface, m->signal_strength_dbm, + m->rx_bitrate / 1000 / 1000, + m->tx_bitrate / 1000 / 1000); - LOG_DBG("%s: signal: %d dBm, RX=%u Mbit/s, TX=%u Mbit/s", iface->name, iface->signal_strength_dbm, - iface->rx_bitrate / 1000 / 1000, iface->tx_bitrate / 1000 / 1000); + /* Can’t issue both get-station and get-scan at the + * same time. So, always run a get-scan when a + * get-station is complete */ + send_nl80211_get_scan(m); break; case NL80211_CMD_NEW_SCAN_RESULTS: - if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) - continue; - - LOG_DBG("%s: got scan results", iface->name); - foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_scan_results, NULL); + if (nl80211_is_for_us(mod, genl, msg_size)) { + LOG_DBG("%s: got scan results", m->iface); + foreach_nlattr(mod, genl, msg_size, &handle_nl80211_scan_results); + } break; default: @@ -1437,13 +1306,15 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len) ; /* iface is not an nl80211 device */ else if (nl_errno == ENOENT) ; /* iface down? */ - else { - LOG_ERRNO_P(nl_errno, "nl80211 reply (seq-nr: %u)", hdr->nlmsg_seq); - } + else + LOG_ERRNO_P(nl_errno, "%s: nl80211 reply (seq-nr: %u)", + m->iface, hdr->nlmsg_seq); } else { - LOG_WARN("unrecognized netlink message type: 0x%x", hdr->nlmsg_type); + LOG_WARN( + "%s: unrecognized netlink message type: 0x%x", + m->iface, hdr->nlmsg_type); return false; } } @@ -1461,20 +1332,17 @@ run(struct module *mod) if (m->poll_interval > 0) { timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); if (timer_fd < 0) { - LOG_ERRNO("failed to create poll timer FD"); + LOG_ERRNO("%s: failed to create poll timer FD", m->iface); goto out; } - const long secs = m->poll_interval / 1000; - const long msecs = m->poll_interval % 1000; - struct itimerspec poll_time = { - .it_value = {.tv_sec = secs, .tv_nsec = msecs * 1000000}, - .it_interval = {.tv_sec = secs, .tv_nsec = msecs * 1000000}, + .it_value = {.tv_sec = m->poll_interval}, + .it_interval = {.tv_sec = m->poll_interval}, }; if (timerfd_settime(timer_fd, 0, &poll_time, NULL) < 0) { - LOG_ERRNO("failed to arm poll timer"); + LOG_ERRNO("%s: failed to arm poll timer", m->iface); goto out; } } @@ -1485,7 +1353,9 @@ run(struct module *mod) if (m->rt_sock < 0 || m->genl_sock < 0) goto out; - if (!send_rt_request(m, RTM_GETLINK) || !send_ctrl_get_family_request(m)) { + if (!send_rt_request(m, RTM_GETLINK) || + !send_ctrl_get_family_request(m)) + { goto out; } @@ -1503,13 +1373,15 @@ run(struct module *mod) if (fds[0].revents & (POLLIN | POLLHUP)) break; - if ((fds[1].revents & POLLHUP) || (fds[2].revents & POLLHUP)) { - LOG_ERR("disconnected from netlink socket"); + if ((fds[1].revents & POLLHUP) || + (fds[2].revents & POLLHUP)) + { + LOG_ERR("%s: disconnected from netlink socket", m->iface); break; } if (fds[3].revents & POLLHUP) { - LOG_ERR("disconnected from timer FD"); + LOG_ERR("%s: disconnected from timer FD", m->iface); break; } @@ -1552,17 +1424,14 @@ run(struct module *mod) break; } - tll_foreach(m->ifaces, it) - { - send_nl80211_get_station(m, &it->item); - send_rt_getstats_request(m, &it->item); - }; + send_nl80211_get_station(m); + send_rt_getstats_request(m); } } ret = 0; -out: + out: if (m->rt_sock >= 0) close(m->rt_sock); if (m->genl_sock >= 0) @@ -1574,25 +1443,26 @@ out: } static struct module * -network_new(struct particle *label, int poll_interval, int left_spacing, int right_spacing) +network_new(const char *iface, struct particle *label, int poll_interval) { - 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; } struct private *priv = calloc(1, sizeof(*priv)); + priv->iface = strdup(iface); priv->label = label; priv->poll_interval = poll_interval; - priv->left_spacing = left_spacing; - priv->right_spacing = right_spacing; priv->genl_sock = -1; priv->rt_sock = -1; priv->urandom_fd = urandom_fd; - priv->get_addresses = false; priv->nl80211.family_id = -1; + priv->get_addresses = true; + priv->ifindex = -1; + priv->state = IF_OPER_DOWN; struct module *mod = module_common_new(); mod->private = priv; @@ -1606,43 +1476,21 @@ network_new(struct particle *label, int poll_interval, int left_spacing, int rig static struct module * from_conf(const struct yml_node *node, struct conf_inherit inherited) { + const struct yml_node *name = yml_get_value(node, "name"); const struct yml_node *content = yml_get_value(node, "content"); const struct yml_node *poll = yml_get_value(node, "poll-interval"); - const struct yml_node *spacing = yml_get_value(node, "spacing"); - const struct yml_node *left_spacing = yml_get_value(node, "left-spacing"); - const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); - int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; - int right = spacing != NULL ? yml_value_as_int(spacing) - : right_spacing != NULL ? yml_value_as_int(right_spacing) - : 0; - - return network_new(conf_to_particle(content, inherited), poll != NULL ? yml_value_as_int(poll) : 0, left, right); -} - -static bool -conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node) -{ - if (!conf_verify_unsigned(chain, node)) - return false; - - int interval = yml_value_as_int(node); - if (interval > 0 && interval < min_poll_interval) { - LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval); - return false; - } - - return true; + return network_new( + yml_value_as_string(name), conf_to_particle(content, inherited), + poll != NULL ? yml_value_as_int(poll) : 0); } static bool verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { - {"spacing", false, &conf_verify_unsigned}, - {"left-spacing", false, &conf_verify_unsigned}, - {"right-spacing", false, &conf_verify_unsigned}, - {"poll-interval", false, &conf_verify_poll_interval}, + {"name", true, &conf_verify_string}, + {"poll-interval", false, &conf_verify_unsigned}, MODULE_COMMON_ATTRS, }; diff --git a/modules/niri-common.c b/modules/niri-common.c deleted file mode 100644 index ac53921..0000000 --- a/modules/niri-common.c +++ /dev/null @@ -1,377 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/modules/niri-common.h b/modules/niri-common.h deleted file mode 100644 index 18afe38..0000000 --- a/modules/niri-common.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include -#include - -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); diff --git a/modules/niri-language.c b/modules/niri-language.c deleted file mode 100644 index f8138ee..0000000 --- a/modules/niri-language.c +++ /dev/null @@ -1,160 +0,0 @@ -#include -#include -#include -#include -#include - -#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 diff --git a/modules/niri-workspaces.c b/modules/niri-workspaces.c deleted file mode 100644 index bca0150..0000000 --- a/modules/niri-workspaces.c +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include -#include - -#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 diff --git a/modules/pipewire.c b/modules/pipewire.c index 1ff3642..bfbb15b 100644 --- a/modules/pipewire.c +++ b/modules/pipewire.c @@ -12,7 +12,7 @@ #include #define LOG_MODULE "pipewire" -#define LOG_ENABLE_DBG 0 +#define LOG_ENABLE_DBG 1 #include "../config-verify.h" #include "../config.h" #include "../log.h" @@ -33,10 +33,10 @@ 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 */ + uint8_t linear_volume; /* classic volume */ + uint8_t cubic_volume; /* volume a la pulseaudio */ char *name; char *description; char *form_factor; /* headset, headphone, speaker, ..., can be null */ @@ -45,23 +45,11 @@ 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 { struct particle *label; struct data *data; - int left_spacing; - int right_spacing; /* pipewire related */ struct output_informations sink_informations; @@ -225,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) @@ -252,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 @@ -353,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; @@ -370,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; @@ -378,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)); @@ -404,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; @@ -418,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"); @@ -437,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); } @@ -497,8 +478,8 @@ node_events_param(void *userdata, __attribute__((unused)) int seq, __attribute__ total += values[i]; float base_volume = total / n_values; - output_informations->linear_volume = roundf(base_volume * 100); - output_informations->cubic_volume = roundf(cbrtf(base_volume) * 100); + output_informations->linear_volume = ceilf(base_volume * 100); + output_informations->cubic_volume = ceilf(cbrtf(base_volume) * 100); } } @@ -678,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; @@ -758,32 +739,20 @@ pipewire_init(struct module *module) /* Main loop */ data->loop = pw_main_loop_new(NULL); - if (data->loop == NULL) { - LOG_ERR("failed to instantiate main loop"); - goto err; - } + assert(data->loop != NULL); /* Context */ data->context = pw_context_new(pw_main_loop_get_loop(data->loop), NULL, 0); - if (data->context == NULL) { - LOG_ERR("failed to instantiate pipewire context"); - goto err; - } + assert(data->context != NULL); /* Core */ data->core = pw_context_connect(data->context, NULL, 0); - if (data->core == NULL) { - LOG_ERR("failed to connect to pipewire"); - goto err; - } + assert(data->core); pw_core_add_listener(data->core, &data->core_listener, &core_events, data); /* Registry */ data->registry = pw_core_get_registry(data->core, PW_VERSION_REGISTRY, 0); - if (data->registry == NULL) { - LOG_ERR("failed to get core registry"); - goto err; - } + assert(data->registry); pw_registry_add_listener(data->registry, &data->registry_listener, ®istry_events, data); /* Sync */ @@ -798,26 +767,11 @@ pipewire_init(struct module *module) data->node_data_source.is_sink = false; return data; - -err: - if (data->registry != NULL) - pw_proxy_destroy((struct pw_proxy *)data->registry); - if (data->core != NULL) - pw_core_disconnect(data->core); - if (data->context != NULL) - pw_context_destroy(data->context); - if (data->loop != NULL) - pw_main_loop_destroy(data->loop); - free(data); - return NULL; } static void pipewire_deinit(struct data *data) { - if (data == NULL) - return; - struct node *node = NULL; spa_list_consume(node, &data->node_list, link) node_free(node, data); @@ -846,8 +800,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); @@ -864,9 +828,6 @@ content(struct module *module) { struct private *private = module->private; - if (private->data == NULL) - return dynlist_exposable_new(NULL, 0, 0, 0); - mtx_lock(&module->lock); struct exposable *exposables[2]; @@ -920,16 +881,13 @@ content(struct module *module) mtx_unlock(&module->lock); - return dynlist_exposable_new(exposables, exposables_length, private->left_spacing, private->right_spacing); + return dynlist_exposable_new(exposables, exposables_length, 0, 0); } static int run(struct module *module) { struct private *private = module->private; - if (private->data == NULL) - return 1; - struct pw_loop *pw_loop = pw_main_loop_get_loop(private->data->loop); struct pollfd pollfds[] = { /* abort_fd */ @@ -967,13 +925,11 @@ run(struct module *module) } static struct module * -pipewire_new(struct particle *label, int left_spacing, int right_spacing) +pipewire_new(struct particle *label) { struct private *private = calloc(1, sizeof(struct private)); assert(private != NULL); private->label = label; - private->left_spacing = left_spacing; - private->right_spacing = right_spacing; struct module *module = module_common_new(); module->private = private; @@ -991,25 +947,13 @@ static struct module * from_conf(struct yml_node const *node, struct conf_inherit inherited) { struct yml_node const *content = yml_get_value(node, "content"); - struct yml_node const *spacing = yml_get_value(node, "spacing"); - struct yml_node const *left_spacing = yml_get_value(node, "left-spacing"); - struct yml_node const *right_spacing = yml_get_value(node, "right-spacing"); - - int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; - int right = spacing != NULL ? yml_value_as_int(spacing) - : right_spacing != NULL ? yml_value_as_int(right_spacing) - : 0; - - return pipewire_new(conf_to_particle(content, inherited), left, right); + return pipewire_new(conf_to_particle(content, inherited)); } static bool verify_conf(keychain_t *keychain, struct yml_node const *node) { static struct attr_info const attrs[] = { - {"spacing", false, &conf_verify_unsigned}, - {"left-spacing", false, &conf_verify_unsigned}, - {"right-spacing", false, &conf_verify_unsigned}, MODULE_COMMON_ATTRS, }; return conf_verify_dict(keychain, node, attrs); diff --git a/modules/pulse.c b/modules/pulse.c index f6c7f69..9eba3a5 100644 --- a/modules/pulse.c +++ b/modules/pulse.c @@ -4,8 +4,8 @@ #include #include -#include #include +#include #include @@ -17,8 +17,7 @@ #include "../log.h" #include "../plugin.h" -struct private -{ +struct private { char *sink_name; char *source_name; struct particle *label; @@ -70,9 +69,9 @@ content(struct module *mod) mtx_lock(&mod->lock); - pa_volume_t sink_volume_max = pa_cvolume_max(&priv->sink_volume); + pa_volume_t sink_volume_max = pa_cvolume_max(&priv->sink_volume); pa_volume_t source_volume_max = pa_cvolume_max(&priv->source_volume); - int sink_percent = round(100.0 * sink_volume_max / PA_VOLUME_NORM); + int sink_percent = round(100.0 * sink_volume_max / PA_VOLUME_NORM); int source_percent = round(100.0 * source_volume_max / PA_VOLUME_NORM); struct tag_set tags = { @@ -107,7 +106,11 @@ context_error(pa_context *c) } static void -abort_event_cb(pa_mainloop_api *api, pa_io_event *event, int fd, pa_io_event_flags_t flags, void *userdata) +abort_event_cb(pa_mainloop_api *api, + pa_io_event *event, + int fd, + pa_io_event_flags_t flags, + void *userdata) { struct module *mod = userdata; struct private *priv = mod->private; @@ -116,7 +119,11 @@ abort_event_cb(pa_mainloop_api *api, pa_io_event *event, int fd, pa_io_event_fla } static void -refresh_timer_cb(pa_mainloop_api *api, pa_io_event *event, int fd, pa_io_event_flags_t flags, void *userdata) +refresh_timer_cb(pa_mainloop_api *api, + pa_io_event *event, + int fd, + pa_io_event_flags_t flags, + void *userdata) { struct module *mod = userdata; struct private *priv = mod->private; @@ -148,8 +155,8 @@ schedule_refresh(struct module *mod) // Start the refresh timer. struct itimerspec t = { - .it_interval = {.tv_sec = 0, .tv_nsec = 0}, - .it_value = {.tv_sec = 0, .tv_nsec = 50000000}, + .it_interval = { .tv_sec = 0, .tv_nsec = 0 }, + .it_value = { .tv_sec = 0, .tv_nsec = 50000000 }, }; timerfd_settime(priv->refresh_timer_fd, 0, &t, NULL); @@ -193,10 +200,12 @@ set_sink_info(struct module *mod, const pa_sink_info *sink_info) free(priv->sink_port); priv->sink_online = true; - priv->sink_index = sink_info->index; + priv->sink_index = sink_info->index; priv->sink_volume = sink_info->volume; - priv->sink_muted = sink_info->mute; - priv->sink_port = sink_info->active_port != NULL ? strdup(sink_info->active_port->description) : NULL; + priv->sink_muted = sink_info->mute; + priv->sink_port = sink_info->active_port != NULL + ? strdup(sink_info->active_port->description) + : NULL; mtx_unlock(&mod->lock); @@ -225,10 +234,12 @@ set_source_info(struct module *mod, const pa_source_info *source_info) free(priv->source_port); priv->source_online = true; - priv->source_index = source_info->index; + priv->source_index = source_info->index; priv->source_volume = source_info->volume; - priv->source_muted = source_info->mute; - priv->source_port = source_info->active_port != NULL ? strdup(source_info->active_port->description) : NULL; + priv->source_muted = source_info->mute; + priv->source_port = source_info->active_port != NULL + ? strdup(source_info->active_port->description) + : NULL; mtx_unlock(&mod->lock); @@ -282,28 +293,32 @@ server_info_cb(pa_context *c, const pa_server_info *i, void *userdata) static void get_sink_info_by_name(pa_context *c, const char *name, void *userdata) { - pa_operation *o = pa_context_get_sink_info_by_name(c, name, sink_info_cb, userdata); + pa_operation *o = + pa_context_get_sink_info_by_name(c, name, sink_info_cb, userdata); pa_operation_unref(o); } static void get_source_info_by_name(pa_context *c, const char *name, void *userdata) { - pa_operation *o = pa_context_get_source_info_by_name(c, name, source_info_cb, userdata); + pa_operation *o = + pa_context_get_source_info_by_name(c, name, source_info_cb, userdata); pa_operation_unref(o); } static void get_sink_info_by_index(pa_context *c, uint32_t index, void *userdata) { - pa_operation *o = pa_context_get_sink_info_by_index(c, index, sink_info_cb, userdata); + pa_operation *o = + pa_context_get_sink_info_by_index(c, index, sink_info_cb, userdata); pa_operation_unref(o); } static void get_source_info_by_index(pa_context *c, uint32_t index, void *userdata) { - pa_operation *o = pa_context_get_source_info_by_index(c, index, source_info_cb, userdata); + pa_operation *o = + pa_context_get_source_info_by_index(c, index, source_info_cb, userdata); pa_operation_unref(o); } @@ -317,12 +332,15 @@ get_server_info(pa_context *c, void *userdata) static void subscribe(pa_context *c, void *userdata) { - pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SERVER | PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE; + pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SERVER + | PA_SUBSCRIPTION_MASK_SINK + | PA_SUBSCRIPTION_MASK_SOURCE; pa_operation *o = pa_context_subscribe(c, mask, NULL, userdata); pa_operation_unref(o); } -static pa_context *connect_to_server(struct module *mod); +static pa_context * +connect_to_server(struct module *mod); static void context_state_change_cb(pa_context *c, void *userdata) @@ -362,13 +380,16 @@ context_state_change_cb(pa_context *c, void *userdata) } static void -subscription_event_cb(pa_context *c, pa_subscription_event_type_t event_type, uint32_t index, void *userdata) +subscription_event_cb(pa_context *c, + pa_subscription_event_type_t event_type, + uint32_t index, + void *userdata) { struct module *mod = userdata; struct private *priv = mod->private; int facility = event_type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK; - int type = event_type & PA_SUBSCRIPTION_EVENT_TYPE_MASK; + int type = event_type & PA_SUBSCRIPTION_EVENT_TYPE_MASK; switch (facility) { case PA_SUBSCRIPTION_EVENT_SERVER: @@ -414,7 +435,8 @@ connect_to_server(struct module *mod) pa_context_set_subscribe_callback(c, subscription_event_cb, mod); // Connect to server. - pa_context_flags_t flags = PA_CONTEXT_NOFAIL | PA_CONTEXT_NOAUTOSPAWN; + pa_context_flags_t flags = PA_CONTEXT_NOFAIL + | PA_CONTEXT_NOAUTOSPAWN; if (pa_context_connect(c, NULL, flags, NULL) < 0) { LOG_ERR("failed to connect to PulseAudio server: %s", context_error(c)); pa_context_unref(c); @@ -438,7 +460,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); @@ -455,8 +477,10 @@ run(struct module *mod) // Poll refresh timer and abort event. pa_mainloop_api *api = pa_mainloop_get_api(priv->mainloop); - api->io_new(api, priv->refresh_timer_fd, PA_IO_EVENT_INPUT, refresh_timer_cb, mod); - api->io_new(api, mod->abort_fd, PA_IO_EVENT_INPUT | PA_IO_EVENT_HANGUP, abort_event_cb, mod); + api->io_new(api, priv->refresh_timer_fd, PA_IO_EVENT_INPUT, + refresh_timer_cb, mod); + api->io_new(api, mod->abort_fd, PA_IO_EVENT_INPUT | PA_IO_EVENT_HANGUP, + abort_event_cb, mod); // Run main loop. if (pa_mainloop_run(priv->mainloop, &ret) < 0) { @@ -473,7 +497,9 @@ run(struct module *mod) } static struct module * -pulse_new(const char *sink_name, const char *source_name, struct particle *label) +pulse_new(const char *sink_name, + const char *source_name, + struct particle *label) { struct private *priv = calloc(1, sizeof *priv); priv->label = label; @@ -496,9 +522,10 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *source = yml_get_value(node, "source"); const struct yml_node *content = yml_get_value(node, "content"); - return pulse_new(sink != NULL ? yml_value_as_string(sink) : "@DEFAULT_SINK@", - source != NULL ? yml_value_as_string(source) : "@DEFAULT_SOURCE@", - conf_to_particle(content, inherited)); + return pulse_new( + sink != NULL ? yml_value_as_string(sink) : "@DEFAULT_SINK@", + source != NULL ? yml_value_as_string(source) : "@DEFAULT_SOURCE@", + conf_to_particle(content, inherited)); } static bool diff --git a/modules/removables.c b/modules/removables.c index df4ade4..4d1d508 100644 --- a/modules/removables.c +++ b/modules/removables.c @@ -1,15 +1,15 @@ -#include -#include -#include -#include -#include #include +#include +#include +#include #include #include +#include +#include -#include #include #include +#include #include @@ -17,10 +17,10 @@ #define LOG_MODULE "removables" #define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../particles/dynlist.h" #include "../plugin.h" @@ -54,8 +54,7 @@ struct block_device { tll(struct partition) partitions; }; -struct private -{ +struct private { struct particle *label; int left_spacing; int right_spacing; @@ -76,7 +75,8 @@ free_partition(struct partition *p) static void free_device(struct block_device *b) { - tll_foreach(b->partitions, it) free_partition(&it->item); + tll_foreach(b->partitions, it) + free_partition(&it->item); tll_free(b->partitions); free(b->sys_path); @@ -91,7 +91,8 @@ destroy(struct module *mod) struct private *m = mod->private; m->label->destroy(m->label); - tll_foreach(m->devices, it) free_device(&it->item); + tll_foreach(m->devices, it) + free_device(&it->item); tll_free(m->devices); tll_free_and_free(m->ignore, free); @@ -112,23 +113,24 @@ content(struct module *mod) tll(const struct partition *) partitions = tll_init(); - tll_foreach(m->devices, dev) - { - tll_foreach(dev->item.partitions, part) { tll_push_back(partitions, &part->item); } + tll_foreach(m->devices, dev) { + tll_foreach(dev->item.partitions, part) { + tll_push_back(partitions, &part->item); + } } struct exposable *exposables[max(tll_length(partitions), 1)]; size_t idx = 0; - tll_foreach(partitions, it) - { + tll_foreach(partitions, it) { const struct partition *p = it->item; char dummy_label[16]; const char *label = p->label; if (label == NULL) { - snprintf(dummy_label, sizeof(dummy_label), "%.1f GB", (double)p->size / 1024 / 1024 / 1024 * 512); + snprintf(dummy_label, sizeof(dummy_label), + "%.1f GB", (double)p->size / 1024 / 1024 / 1024 * 512); label = dummy_label; } @@ -155,16 +157,20 @@ content(struct module *mod) } tll_free(partitions); - return dynlist_exposable_new(exposables, idx, m->left_spacing, m->right_spacing); + return dynlist_exposable_new( + exposables, idx, m->left_spacing, m->right_spacing); } 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; } @@ -172,7 +178,9 @@ find_mount_points(const char *dev_path, mount_point_list_t *mount_points) while (fgets(line, sizeof(line), f) != NULL) { char *dev = NULL, *path = NULL; - if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-] - %*s %ms %*s", &path, &dev) != 2) { + if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-] - %*s %ms %*s", + &path, &dev) != 2) + { LOG_ERR("failed to parse /proc/self/mountinfo: %s", line); free(dev); free(path); @@ -199,11 +207,9 @@ update_mount_points(struct partition *partition) /* Remove mount points that no longer exists (i.e. old mount * points that aren't in the new list) */ - tll_foreach(partition->mount_points, old) - { + tll_foreach(partition->mount_points, old) { bool gone = true; - tll_foreach(new_mounts, new) - { + tll_foreach(new_mounts, new) { if (strcmp(new->item, old->item) == 0) { /* Remove from new list, as it's already in the * partitions list */ @@ -222,8 +228,7 @@ update_mount_points(struct partition *partition) /* Add new mount points (i.e. mount points in the new list, that * aren't in the old list) */ - tll_foreach(new_mounts, new) - { + tll_foreach(new_mounts, new) { LOG_DBG("%s: mounted on %s", partition->dev_path, new->item); tll_push_back(partition->mount_points, new->item); @@ -237,13 +242,14 @@ update_mount_points(struct partition *partition) } static struct partition * -add_partition(struct module *mod, struct block_device *block, struct udev_device *dev) +add_partition(struct module *mod, struct block_device *block, + struct udev_device *dev) { struct private *m = mod->private; const char *_size = udev_device_get_sysattr_value(dev, "size"); uint64_t size = 0; if (_size != NULL) - sscanf(_size, "%" SCNu64, &size); + sscanf(_size, "%"SCNu64, &size); #if 0 struct udev_list_entry *e = NULL; @@ -254,8 +260,7 @@ add_partition(struct module *mod, struct block_device *block, struct udev_device const char *devname = udev_device_get_property_value(dev, "DEVNAME"); if (devname != NULL) { - tll_foreach(m->ignore, it) - { + tll_foreach(m->ignore, it) { if (strcmp(it->item, devname) == 0) { LOG_DBG("ignoring %s because it is on the ignore list", devname); return NULL; @@ -267,17 +272,21 @@ add_partition(struct module *mod, struct block_device *block, struct udev_device if (label == NULL) label = udev_device_get_property_value(dev, "ID_LABEL"); - LOG_INFO("partition: add: %s: label=%s, size=%" PRIu64, udev_device_get_devnode(dev), label, size); + LOG_INFO("partition: add: %s: label=%s, size=%"PRIu64, + udev_device_get_devnode(dev), label, size); mtx_lock(&mod->lock); - tll_push_back(block->partitions, ((struct partition){.block = block, - .sys_path = strdup(udev_device_get_devpath(dev)), - .dev_path = strdup(udev_device_get_devnode(dev)), - .label = label != NULL ? strdup(label) : NULL, - .size = size, - .audio_cd = false, - .mount_points = tll_init()})); + tll_push_back( + block->partitions, + ((struct partition){ + .block = block, + .sys_path = strdup(udev_device_get_devpath(dev)), + .dev_path = strdup(udev_device_get_devnode(dev)), + .label = label != NULL ? strdup(label) : NULL, + .size = size, + .audio_cd = false, + .mount_points = tll_init()})); struct partition *p = &tll_back(block->partitions); update_mount_points(p); @@ -287,13 +296,14 @@ add_partition(struct module *mod, struct block_device *block, struct udev_device } static struct partition * -add_audio_cd(struct module *mod, struct block_device *block, struct udev_device *dev) +add_audio_cd(struct module *mod, struct block_device *block, + struct udev_device *dev) { struct private *m = mod->private; const char *_size = udev_device_get_sysattr_value(dev, "size"); uint64_t size = 0; if (_size != NULL) - sscanf(_size, "%" SCNu64, &size); + sscanf(_size, "%"SCNu64, &size); #if 0 struct udev_list_entry *e = NULL; @@ -304,8 +314,7 @@ add_audio_cd(struct module *mod, struct block_device *block, struct udev_device const char *devname = udev_device_get_property_value(dev, "DEVNAME"); if (devname != NULL) { - tll_foreach(m->ignore, it) - { + tll_foreach(m->ignore, it) { if (strcmp(it->item, devname) == 0) { LOG_DBG("ignoring %s because it is on the ignore list", devname); return NULL; @@ -313,24 +322,28 @@ add_audio_cd(struct module *mod, struct block_device *block, struct udev_device } } - const char *_track_count = udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); + const char *_track_count = udev_device_get_property_value( + dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); unsigned long track_count = strtoul(_track_count, NULL, 10); char label[64]; snprintf(label, sizeof(label), "Audio CD - %lu tracks", track_count); - LOG_INFO("audio CD: add: %s: tracks=%lu, label=%s, size=%" PRIu64, udev_device_get_devnode(dev), track_count, label, - size); + LOG_INFO("audio CD: add: %s: tracks=%lu, label=%s, size=%"PRIu64, + udev_device_get_devnode(dev), track_count, label, size); mtx_lock(&mod->lock); - tll_push_back(block->partitions, ((struct partition){.block = block, - .sys_path = strdup(udev_device_get_devpath(dev)), - .dev_path = strdup(udev_device_get_devnode(dev)), - .label = label != NULL ? strdup(label) : NULL, - .size = size, - .audio_cd = true, - .mount_points = tll_init()})); + tll_push_back( + block->partitions, + ((struct partition){ + .block = block, + .sys_path = strdup(udev_device_get_devpath(dev)), + .dev_path = strdup(udev_device_get_devnode(dev)), + .label = label != NULL ? strdup(label) : NULL, + .size = size, + .audio_cd = true, + .mount_points = tll_init()})); struct partition *p = &tll_back(block->partitions); update_mount_points(p); @@ -340,15 +353,17 @@ add_audio_cd(struct module *mod, struct block_device *block, struct udev_device } static bool -del_partition(struct module *mod, struct block_device *block, struct udev_device *dev) +del_partition(struct module *mod, struct block_device *block, + struct udev_device *dev) { const char *sys_path = udev_device_get_devpath(dev); mtx_lock(&mod->lock); - tll_foreach(block->partitions, it) - { + tll_foreach(block->partitions, it) { if (strcmp(it->item.sys_path, sys_path) == 0) { - LOG_INFO("%s: del: %s", it->item.audio_cd ? "audio CD" : "partition", it->item.dev_path); + LOG_INFO("%s: del: %s", + it->item.audio_cd ? "audio CD" : "partition", + it->item.dev_path); free_partition(&it->item); tll_remove(block->partitions, it); @@ -377,8 +392,7 @@ add_device(struct module *mod, struct udev_device *dev) const char *devname = udev_device_get_property_value(dev, "DEVNAME"); if (devname != NULL) { - tll_foreach(m->ignore, it) - { + tll_foreach(m->ignore, it) { if (strcmp(it->item, devname) == 0) { LOG_DBG("ignoring %s because it is on the ignore list", devname); return NULL; @@ -389,12 +403,11 @@ add_device(struct module *mod, struct udev_device *dev) const char *_size = udev_device_get_sysattr_value(dev, "size"); uint64_t size = 0; if (_size != NULL) - sscanf(_size, "%" SCNu64, &size); + sscanf(_size, "%"SCNu64, &size); #if 1 struct udev_list_entry *e = NULL; - udev_list_entry_foreach(e, udev_device_get_properties_list_entry(dev)) - { + udev_list_entry_foreach(e, udev_device_get_properties_list_entry(dev)) { LOG_DBG("%s -> %s", udev_list_entry_get_name(e), udev_list_entry_get_value(e)); } #endif @@ -411,22 +424,27 @@ add_device(struct module *mod, struct udev_device *dev) const char *_fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE"); bool have_fs = _fs_usage != NULL && strcmp(_fs_usage, "filesystem") == 0; - const char *_audio_track_count = udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); - unsigned long audio_track_count = _audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0; + const char *_audio_track_count = udev_device_get_property_value( + dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); + unsigned long audio_track_count = + _audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0; - LOG_DBG("device: add: %s: vendor=%s, model=%s, optical=%d, size=%" PRIu64, udev_device_get_devnode(dev), vendor, - model, optical, size); + LOG_DBG("device: add: %s: vendor=%s, model=%s, optical=%d, size=%"PRIu64, + udev_device_get_devnode(dev), vendor, model, optical, size); mtx_lock(&mod->lock); - tll_push_back(m->devices, ((struct block_device){.sys_path = strdup(udev_device_get_devpath(dev)), - .dev_path = strdup(udev_device_get_devnode(dev)), - .size = size, - .vendor = vendor != NULL ? strdup(vendor) : NULL, - .model = model != NULL ? strdup(model) : NULL, - .optical = optical, - .media = media, - .partitions = tll_init()})); + tll_push_back( + m->devices, + ((struct block_device){ + .sys_path = strdup(udev_device_get_devpath(dev)), + .dev_path = strdup(udev_device_get_devnode(dev)), + .size = size, + .vendor = vendor != NULL ? strdup(vendor) : NULL, + .model = model != NULL ? strdup(model) : NULL, + .optical = optical, + .media = media, + .partitions = tll_init()})); mtx_unlock(&mod->lock); @@ -448,8 +466,7 @@ del_device(struct module *mod, struct udev_device *dev) const char *sys_path = udev_device_get_devpath(dev); mtx_lock(&mod->lock); - tll_foreach(m->devices, it) - { + tll_foreach(m->devices, it) { if (strcmp(it->item.sys_path, sys_path) == 0) { LOG_DBG("device: del: %s", it->item.dev_path); @@ -473,8 +490,7 @@ change_device(struct module *mod, struct udev_device *dev) struct block_device *block = NULL; - tll_foreach(m->devices, it) - { + tll_foreach(m->devices, it) { if (strcmp(it->item.sys_path, sys_path) == 0) { block = &it->item; break; @@ -495,8 +511,10 @@ change_device(struct module *mod, struct udev_device *dev) const char *_fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE"); bool have_fs = _fs_usage != NULL && strcmp(_fs_usage, "filesystem") == 0; - const char *_audio_track_count = udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); - unsigned long audio_track_count = _audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0; + const char *_audio_track_count = udev_device_get_property_value( + dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); + unsigned long audio_track_count = + _audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0; bool media_change = media != block->media; @@ -504,7 +522,8 @@ change_device(struct module *mod, struct udev_device *dev) mtx_unlock(&mod->lock); if (media_change) { - LOG_INFO("device: change: %s: media %s", block->dev_path, media ? "inserted" : "removed"); + LOG_INFO("device: change: %s: media %s", + block->dev_path, media ? "inserted" : "removed"); if (media) { if (have_fs) @@ -550,8 +569,7 @@ handle_udev_event(struct module *mod, struct udev_device *dev) struct udev_device *parent = udev_device_get_parent(dev); const char *parent_sys_path = udev_device_get_devpath(parent); - tll_foreach(m->devices, it) - { + tll_foreach(m->devices, it) { if (strcmp(it->item.sys_path, parent_sys_path) != 0) continue; @@ -560,7 +578,8 @@ handle_udev_event(struct module *mod, struct udev_device *dev) else if (del) return del_partition(mod, &it->item, dev); else { - LOG_ERR("unimplemented: 'change' event on partition: %s", udev_device_get_devpath(dev)); + LOG_ERR("unimplemented: 'change' event on partition: %s", + udev_device_get_devpath(dev)); return false; } break; @@ -587,15 +606,15 @@ run(struct module *mod) udev_enumerate_add_match_subsystem(dev_enum, "block"); /* TODO: verify how an optical presents itself */ - // udev_enumerate_add_match_sysattr(dev_enum, "removable", "1"); + //udev_enumerate_add_match_sysattr(dev_enum, "removable", "1"); udev_enumerate_add_match_property(dev_enum, "DEVTYPE", "disk"); udev_enumerate_scan_devices(dev_enum); /* Loop list, and for each device, enumerate its partitions */ struct udev_list_entry *entry = NULL; - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(dev_enum)) - { - struct udev_device *dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(entry)); + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(dev_enum)) { + struct udev_device *dev = udev_device_new_from_syspath( + udev, udev_list_entry_get_name(entry)); struct block_device *block = add_device(mod, dev); if (block == NULL) { @@ -612,9 +631,9 @@ run(struct module *mod) udev_enumerate_scan_devices(part_enum); struct udev_list_entry *sub_entry = NULL; - udev_list_entry_foreach(sub_entry, udev_enumerate_get_list_entry(part_enum)) - { - struct udev_device *partition = udev_device_new_from_syspath(udev, udev_list_entry_get_name(sub_entry)); + udev_list_entry_foreach(sub_entry, udev_enumerate_get_list_entry(part_enum)) { + struct udev_device *partition = udev_device_new_from_syspath( + udev, udev_list_entry_get_name(sub_entry)); add_partition(mod, block, partition); udev_device_unref(partition); } @@ -654,10 +673,8 @@ run(struct module *mod) bool update = false; if (fds[2].revents & POLLPRI) { - tll_foreach(m->devices, dev) - { - tll_foreach(dev->item.partitions, part) - { + tll_foreach(m->devices, dev) { + tll_foreach(dev->item.partitions, part) { if (update_mount_points(&part->item)) update = true; } @@ -686,8 +703,8 @@ run(struct module *mod) } static struct module * -removables_new(struct particle *label, int left_spacing, int right_spacing, size_t ignore_count, - const char *ignore[static ignore_count]) +removables_new(struct particle *label, int left_spacing, int right_spacing, + size_t ignore_count, const char *ignore[static ignore_count]) { struct private *priv = calloc(1, sizeof(*priv)); priv->label = label; @@ -715,22 +732,26 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *ignore_list = yml_get_value(node, "ignore"); - int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; - int right = spacing != NULL ? yml_value_as_int(spacing) - : right_spacing != NULL ? yml_value_as_int(right_spacing) - : 0; + int left = spacing != NULL ? yml_value_as_int(spacing) : + left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; + int right = spacing != NULL ? yml_value_as_int(spacing) : + right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; size_t ignore_count = ignore_list != NULL ? yml_list_length(ignore_list) : 0; const char *ignore[max(ignore_count, 1)]; if (ignore_list != NULL) { size_t i = 0; - for (struct yml_list_iter iter = yml_list_iter(ignore_list); iter.node != NULL; yml_list_next(&iter), i++) { + for (struct yml_list_iter iter = yml_list_iter(ignore_list); + iter.node != NULL; + yml_list_next(&iter), i++) + { ignore[i] = yml_value_as_string(iter.node); } } - return removables_new(conf_to_particle(content, inherited), left, right, ignore_count, ignore); + return removables_new( + conf_to_particle(content, inherited), left, right, ignore_count, ignore); } static bool diff --git a/modules/river.c b/modules/river.c index ec25f9f..059a44e 100644 --- a/modules/river.c +++ b/modules/river.c @@ -1,17 +1,17 @@ -#include -#include -#include #include #include +#include +#include +#include -#include #include +#include #define LOG_MODULE "river" #define LOG_ENABLE_DBG 0 #include "../log.h" -#include "../particles/dynlist.h" #include "../plugin.h" +#include "../particles/dynlist.h" #include "river-status-unstable-v1.h" #include "xdg-output-unstable-v1.h" @@ -32,9 +32,6 @@ struct output { uint32_t occupied; uint32_t focused; uint32_t urgent; - - /* Layout */ - char *layout; }; struct seat { @@ -49,10 +46,8 @@ struct seat { struct output *output; }; -struct private -{ +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,22 +84,18 @@ 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; uint32_t seat_focused = 0; - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { const struct output *output = &it->item; - if (!m->all_monitors && output_bar_is_on != NULL && output->name != NULL - && strcmp(output->name, output_bar_is_on) != 0) { + if (!m->all_monitors && + output_bar_is_on != NULL && output->name != NULL && + strcmp(output->name, output_bar_is_on) != 0) + { continue; } @@ -112,8 +103,7 @@ content(struct module *mod) urgent |= output->urgent; occupied |= output->occupied; - tll_foreach(m->seats, it2) - { + tll_foreach(m->seats, it2) { const struct seat *seat = &it2->item; if (seat->output == output) { seat_focused |= output->focused; @@ -134,7 +124,10 @@ content(struct module *mod) bool is_urgent = urgent & (1u << i); bool is_occupied = occupied & (1u << i); - const char *state = is_urgent ? "urgent" : is_visible ? is_focused ? "focused" : "unfocused" : "invisible"; + const char *state = + is_urgent ? "urgent" : + is_visible ? is_focused ? "focused" : "unfocused" : + "invisible"; #if 0 LOG_DBG("tag: #%u, visible=%d, focused=%d, occupied=%d, state=%s", @@ -159,19 +152,16 @@ content(struct module *mod) if (m->title != NULL) { size_t i = 32; - tll_foreach(m->seats, it) - { + tll_foreach(m->seats, it) { const struct seat *seat = &it->item; - const char *layout = seat->output != NULL && seat->output->layout != NULL ? seat->output->layout : ""; struct tag_set tags = { .tags = (struct tag *[]){ tag_new_string(mod, "seat", seat->name), tag_new_string(mod, "title", seat->title), tag_new_string(mod, "mode", seat->mode), - tag_new_string(mod, "layout", layout), }, - .count = 4, + .count = 3, }; tag_parts[i++] = m->title->instantiate(m->title, &tags); @@ -189,21 +179,20 @@ verify_iface_version(const char *iface, uint32_t version, uint32_t wanted) if (version >= wanted) return true; - LOG_ERR("%s: need interface version %u, but compositor only implements %u", iface, wanted, version); + LOG_ERR("%s: need interface version %u, but compositor only implements %u", + iface, wanted, version); return false; } static void output_destroy(struct output *output) { - tll_foreach(output->m->seats, it) - { + tll_foreach(output->m->seats, it) { struct seat *seat = &it->item; if (seat->output == output) seat->output = NULL; } free(output->name); - free(output->layout); if (output->status != NULL) zriver_output_status_v1_destroy(output->status); if (output->xdg_output != NULL) @@ -225,7 +214,8 @@ seat_destroy(struct seat *seat) } static void -focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, uint32_t tags) +focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, + uint32_t tags) { struct output *output = data; @@ -242,7 +232,8 @@ focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1 } static void -view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, struct wl_array *tags) +view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, + struct wl_array *tags) { struct output *output = data; struct module *mod = output->m->mod; @@ -254,7 +245,9 @@ view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, s /* Each entry in the list is a view, and the value is the tags * associated with that view */ uint32_t *set; - wl_array_for_each(set, tags) { output->occupied |= *set; } + wl_array_for_each(set, tags) { + output->occupied |= *set; + } LOG_DBG("output: %s: occupied tags: 0x%0x", output->name, output->occupied); } @@ -263,7 +256,8 @@ view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, s } static void -urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, uint32_t tags) +urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, + uint32_t tags) { struct output *output = data; struct module *mod = output->m->mod; @@ -276,59 +270,23 @@ urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, mod->bar->refresh(mod->bar); } -#if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_SINCE_VERSION) -static void -layout_name(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, const char *name) -{ - struct output *output = data; - struct module *mod = output->m->mod; - - mtx_lock(&mod->lock); - { - free(output->layout); - output->layout = name != NULL ? strdup(name) : NULL; - } - mtx_unlock(&mod->lock); - mod->bar->refresh(mod->bar); -} -#endif - -#if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_CLEAR_SINCE_VERSION) -static void -layout_name_clear(void *data, struct zriver_output_status_v1 *zriver_output_status_v1) -{ - struct output *output = data; - struct module *mod = output->m->mod; - - mtx_lock(&mod->lock); - { - free(output->layout); - output->layout = NULL; - } - mtx_unlock(&mod->lock); - mod->bar->refresh(mod->bar); -} -#endif static const struct zriver_output_status_v1_listener river_status_output_listener = { .focused_tags = &focused_tags, .view_tags = &view_tags, .urgent_tags = &urgent_tags, -#if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_SINCE_VERSION) - .layout_name = &layout_name, -#endif -#if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_CLEAR_SINCE_VERSION) - .layout_name_clear = &layout_name_clear, -#endif }; static void -xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) +xdg_output_handle_logical_position(void *data, + struct zxdg_output_v1 *xdg_output, + int32_t x, int32_t y) { } static void -xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) +xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, + int32_t width, int32_t height) { } @@ -338,7 +296,8 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) } static void -xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name) +xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, + const char *name) { struct output *output = data; struct module *mod = output->m->mod; @@ -353,7 +312,8 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char } static void -xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description) +xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, + const char *description) { } @@ -380,32 +340,36 @@ update_output(struct output *output) output->status = NULL; } - output->status = zriver_status_manager_v1_get_river_output_status(output->m->status_manager, output->wl_output); + output->status = zriver_status_manager_v1_get_river_output_status( + output->m->status_manager, output->wl_output); if (output->status != NULL) { - zriver_output_status_v1_add_listener(output->status, &river_status_output_listener, output); + zriver_output_status_v1_add_listener( + output->status, &river_status_output_listener, output); } } if (output->m->xdg_output_manager != NULL && output->xdg_output == NULL) { - output->xdg_output = zxdg_output_manager_v1_get_xdg_output(output->m->xdg_output_manager, output->wl_output); + output->xdg_output = zxdg_output_manager_v1_get_xdg_output( + output->m->xdg_output_manager, output->wl_output); if (output->xdg_output != NULL) { - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + zxdg_output_v1_add_listener( + output->xdg_output, &xdg_output_listener, output); } } } static void -focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, struct wl_output *wl_output) +focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, + struct wl_output *wl_output) { struct seat *seat = data; struct private *m = seat->m; struct module *mod = m->mod; struct output *output = NULL; - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { if (it->item.wl_output == wl_output) { output = &it->item; break; @@ -426,7 +390,8 @@ focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, } static void -unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, struct wl_output *wl_output) +unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, + struct wl_output *wl_output) { struct seat *seat = data; struct private *m = seat->m; @@ -435,8 +400,7 @@ unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1 mtx_lock(&mod->lock); { struct output *output = NULL; - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { if (it->item.wl_output == wl_output) { output = &it->item; break; @@ -454,7 +418,8 @@ unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1 } static void -focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, const char *title) +focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, + const char *title) { struct seat *seat = data; struct module *mod = seat->m->mod; @@ -469,9 +434,11 @@ focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, co const char *output_bar_is_on = mod->bar->output_name(mod->bar); - if (seat->m->all_monitors - || (output_bar_is_on != NULL && seat->output != NULL && seat->output->name != NULL - && strcmp(output_bar_is_on, seat->output->name) == 0)) { + if (seat->m->all_monitors || + (output_bar_is_on != NULL && + seat->output != NULL && seat->output->name != NULL && + strcmp(output_bar_is_on, seat->output->name) == 0)) + { mtx_lock(&mod->lock); { free(seat->title); @@ -484,7 +451,8 @@ focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, co #if defined(ZRIVER_SEAT_STATUS_V1_MODE_SINCE_VERSION) static void -mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, const char *name) +mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, + const char *name) { struct seat *seat = data; struct module *mod = seat->m->mod; @@ -512,7 +480,8 @@ static const struct zriver_seat_status_v1_listener river_seat_status_listener = }; static void -seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) +seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { } @@ -549,16 +518,19 @@ update_seat(struct seat *seat) seat->status = NULL; } - seat->status = zriver_status_manager_v1_get_river_seat_status(seat->m->status_manager, seat->wl_seat); + seat->status = zriver_status_manager_v1_get_river_seat_status( + seat->m->status_manager, seat->wl_seat); if (seat->status == NULL) return; - zriver_seat_status_v1_add_listener(seat->status, &river_seat_status_listener, seat); + zriver_seat_status_v1_add_listener( + seat->status, &river_seat_status_listener, seat); } static void -handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) +handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { struct private *m = data; @@ -567,7 +539,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - struct wl_output *wl_output = wl_registry_bind(registry, name, &wl_output_interface, required); + struct wl_output *wl_output = wl_registry_bind( + registry, name, &wl_output_interface, required); if (wl_output == NULL) return; @@ -581,7 +554,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha mtx_lock(&m->mod->lock); tll_push_back(m->outputs, output); update_output(&tll_back(m->outputs)); - tll_foreach(m->seats, it) update_seat(&it->item); + tll_foreach(m->seats, it) + update_seat(&it->item); mtx_unlock(&m->mod->lock); } @@ -590,10 +564,12 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - m->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, required); + m->xdg_output_manager = wl_registry_bind( + registry, name, &zxdg_output_manager_v1_interface, required); mtx_lock(&m->mod->lock); - tll_foreach(m->outputs, it) update_output(&it->item); + tll_foreach(m->outputs, it) + update_output(&it->item); mtx_unlock(&m->mod->lock); } @@ -602,7 +578,8 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - struct wl_seat *wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, required); + struct wl_seat *wl_seat = wl_registry_bind( + registry, name, &wl_seat_interface, required); if (wl_seat == NULL) return; @@ -621,11 +598,14 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name, const cha if (!verify_iface_version(interface, version, required)) return; - m->status_manager = wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, min(version, 4)); + m->status_manager = wl_registry_bind( + registry, name, &zriver_status_manager_v1_interface, min(version, 3)); mtx_lock(&m->mod->lock); - tll_foreach(m->outputs, it) update_output(&it->item); - tll_foreach(m->seats, it) update_seat(&it->item); + tll_foreach(m->outputs, it) + update_output(&it->item); + tll_foreach(m->seats, it) + update_seat(&it->item); mtx_unlock(&m->mod->lock); } } @@ -636,8 +616,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) struct private *m = data; mtx_lock(&m->mod->lock); - tll_foreach(m->outputs, it) - { + tll_foreach(m->outputs, it) { if (it->item.wl_name == name) { output_destroy(&it->item); tll_remove(m->outputs, it); @@ -646,8 +625,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) } } - tll_foreach(m->seats, it) - { + tll_foreach(m->seats, it) { if (it->item.wl_name == name) { seat_destroy(&it->item); tll_remove(m->seats, it); @@ -678,8 +656,9 @@ run(struct module *mod) goto out; } - if ((registry = wl_display_get_registry(display)) == NULL - || wl_registry_add_listener(registry, ®istry_listener, m) != 0) { + if ((registry = wl_display_get_registry(display)) == NULL || + wl_registry_add_listener(registry, ®istry_listener, m) != 0) + { LOG_ERR("failed to get Wayland registry"); goto out; } @@ -691,8 +670,6 @@ run(struct module *mod) goto out; } - m->is_running = true; - wl_display_roundtrip(display); while (true) { @@ -726,9 +703,11 @@ run(struct module *mod) ret = 0; out: - tll_foreach(m->seats, it) seat_destroy(&it->item); + tll_foreach(m->seats, it) + seat_destroy(&it->item); tll_free(m->seats); - tll_foreach(m->outputs, it) output_destroy(&it->item); + tll_foreach(m->outputs, it) + output_destroy(&it->item); tll_free(m->outputs); if (m->xdg_output_manager != NULL) @@ -767,8 +746,10 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *title = yml_get_value(node, "title"); const struct yml_node *all_monitors = yml_get_value(node, "all-monitors"); - return river_new(conf_to_particle(c, inherited), title != NULL ? conf_to_particle(title, inherited) : NULL, - all_monitors != NULL ? yml_value_as_bool(all_monitors) : false); + return river_new( + conf_to_particle(c, inherited), + title != NULL ? conf_to_particle(title, inherited) : NULL, + all_monitors != NULL ? yml_value_as_bool(all_monitors) : false); } static bool diff --git a/modules/script.c b/modules/script.c index 9f9b40a..1c349a1 100644 --- a/modules/script.c +++ b/modules/script.c @@ -1,14 +1,14 @@ -#include +#include +#include +#include #include +#include +#include #include #include -#include -#include -#include -#include -#include #include +#include #include #include @@ -16,16 +16,13 @@ #define LOG_MODULE "script" #define LOG_ENABLE_DBG 0 -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../config.h" +#include "../config-verify.h" #include "../module.h" #include "../plugin.h" -static const long min_poll_interval = 250; - -struct private -{ +struct private { char *path; size_t argc; char **argv; @@ -111,8 +108,9 @@ process_line(struct module *mod, const char *line, size_t len) size_t value_len = line + len - _value; - LOG_DBG("%.*s: name=\"%.*s\", type=\"%.*s\", value=\"%.*s\"", (int)len, line, (int)name_len, _name, (int)type_len, - type, (int)value_len, _value); + LOG_DBG("%.*s: name=\"%.*s\", type=\"%.*s\", value=\"%.*s\"", + (int)len, line, + (int)name_len, _name, (int)type_len, type, (int)value_len, _value); name = malloc(name_len + 1); memcpy(name, _name, name_len); @@ -165,12 +163,16 @@ process_line(struct module *mod, const char *line, size_t len) tag = tag_new_float(mod, name, v); } - else if ((type_len > 6 && memcmp(type, "range:", 6) == 0) || (type_len > 9 && memcmp(type, "realtime:", 9) == 0)) { + else if ((type_len > 6 && memcmp(type, "range:", 6) == 0) || + (type_len > 9 && memcmp(type, "realtime:", 9) == 0)) + { const char *_start = type + 6; const char *split = memchr(_start, '-', type_len - 6); if (split == NULL || split == _start || (split + 1) - type >= type_len) { - LOG_ERR("tag range delimiter ('-') not found in type: %.*s", (int)type_len, type); + LOG_ERR( + "tag range delimiter ('-') not found in type: %.*s", + (int)type_len, type); goto bad_tag; } @@ -182,7 +184,9 @@ process_line(struct module *mod, const char *line, size_t len) long start = 0; for (size_t i = 0; i < start_len; i++) { if (!(_start[i] >= '0' && _start[i] <= '9')) { - LOG_ERR("tag range start is not an integer: %.*s", (int)start_len, _start); + LOG_ERR( + "tag range start is not an integer: %.*s", + (int)start_len, _start); goto bad_tag; } @@ -193,7 +197,9 @@ process_line(struct module *mod, const char *line, size_t len) long end = 0; for (size_t i = 0; i < end_len; i++) { if (!(_end[i] >= '0' && _end[i] <= '9')) { - LOG_ERR("tag range end is not an integer: %.*s", (int)end_len, _end); + LOG_ERR( + "tag range end is not an integer: %.*s", + (int)end_len, _end); goto bad_tag; } @@ -215,7 +221,8 @@ process_line(struct module *mod, const char *line, size_t len) } if (v < start || v > end) { - LOG_ERR("tag value is outside range: %ld <= %ld <= %ld", start, v, end); + LOG_ERR("tag value is outside range: %ld <= %ld <= %ld", + start, v, end); goto bad_tag; } @@ -289,7 +296,7 @@ data_received(struct module *mod, const char *data, size_t len) { struct private *m = mod->private; - while (len > m->recv_buf.sz - m->recv_buf.idx) { + if (len > m->recv_buf.sz - m->recv_buf.idx) { size_t new_sz = m->recv_buf.sz == 0 ? 1024 : m->recv_buf.sz * 2; char *new_buf = realloc(m->recv_buf.data, new_sz); @@ -317,7 +324,9 @@ data_received(struct module *mod, const char *data, size_t len) process_transaction(mod, transaction_size); assert(m->recv_buf.idx >= transaction_size + 1); - memmove(m->recv_buf.data, &m->recv_buf.data[transaction_size + 1], m->recv_buf.idx - (transaction_size + 1)); + memmove(m->recv_buf.data, + &m->recv_buf.data[transaction_size + 1], + m->recv_buf.idx - (transaction_size + 1)); m->recv_buf.idx -= transaction_size + 1; } @@ -421,8 +430,11 @@ execute_script(struct module *mod) sigemptyset(&mask); const struct sigaction sa = {.sa_handler = SIG_DFL}; - if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0 || sigaction(SIGCHLD, &sa, NULL) < 0 - || sigprocmask(SIG_SETMASK, &mask, NULL) < 0) { + if (sigaction(SIGINT, &sa, NULL) < 0 || + sigaction(SIGTERM, &sa, NULL) < 0 || + sigaction(SIGCHLD, &sa, NULL) < 0 || + sigprocmask(SIG_SETMASK, &mask, NULL) < 0) + { goto fail; } @@ -438,7 +450,9 @@ execute_script(struct module *mod) if (dev_null < 0) goto fail; - if (dup2(dev_null, STDIN_FILENO) < 0 || dup2(comm_pipe[1], STDOUT_FILENO) < 0) { + if (dup2(dev_null, STDIN_FILENO) < 0 || + dup2(comm_pipe[1], STDOUT_FILENO) < 0) + { goto fail; } @@ -517,7 +531,9 @@ execute_script(struct module *mod) usleep(10000); pid_t waited_pid; - while ((waited_pid = waitpid(pid, NULL, timeout > 0 ? WNOHANG : 0)) == 0) { + while ((waited_pid = waitpid( + pid, NULL, timeout > 0 ? WNOHANG : 0)) == 0) + { struct timeval now; gettimeofday(&now, NULL); @@ -529,7 +545,7 @@ execute_script(struct module *mod) /* Don't spinning */ thrd_yield(); - usleep(100000); /* 100ms */ + usleep(100000); /* 100ms */ } if (waited_pid == pid) { @@ -558,19 +574,16 @@ run(struct module *mod) break; if (m->aborted) break; - if (m->poll_interval <= 0) + if (m->poll_interval < 0) break; struct timeval now; - if (gettimeofday(&now, NULL) < 0) { + if (gettimeofday(&now, NULL) < 0) { LOG_ERRNO("failed to get current time"); break; } - struct timeval poll_interval = { - .tv_sec = m->poll_interval / 1000, - .tv_usec = (m->poll_interval % 1000) * 1000, - }; + struct timeval poll_interval = {.tv_sec = m->poll_interval}; struct timeval timeout; timeradd(&now, &poll_interval, &timeout); @@ -613,10 +626,11 @@ run(struct module *mod) } static struct module * -script_new(char *path, size_t argc, const char *const argv[static argc], int poll_interval, struct particle *_content) +script_new(const char *path, size_t argc, const char *const argv[static argc], + int poll_interval, struct particle *_content) { struct private *m = calloc(1, sizeof(*m)); - m->path = path; + m->path = strdup(path); m->content = _content; m->argc = argc; m->argv = malloc(argc * sizeof(m->argv[0])); @@ -636,7 +650,7 @@ script_new(char *path, size_t argc, const char *const argv[static argc], int pol static struct module * from_conf(const struct yml_node *node, struct conf_inherit inherited) { - const struct yml_node *path_node = yml_get_value(node, "path"); + const struct yml_node *path = yml_get_value(node, "path"); const struct yml_node *args = yml_get_value(node, "args"); const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *poll_interval = yml_get_value(node, "poll-interval"); @@ -646,31 +660,18 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) if (args != NULL) { size_t i = 0; - for (struct yml_list_iter iter = yml_list_iter(args); iter.node != NULL; yml_list_next(&iter), i++) { + for (struct yml_list_iter iter = yml_list_iter(args); + iter.node != NULL; + yml_list_next(&iter), i++) + { argv[i] = yml_value_as_string(iter.node); } } - const char *yml_path = yml_value_as_string(path_node); - char *path = NULL; - - if (yml_path[0] == '~' && yml_path[1] == '/') { - const char *home_dir = getenv("HOME"); - - if (home_dir == NULL) { - LOG_ERRNO("failed to expand '~"); - return NULL; - } - - if (asprintf(&path, "%s/%s", home_dir, yml_path + 2) < 0) { - LOG_ERRNO("failed to expand '~"); - return NULL; - } - } else - path = strdup(yml_path); - - return script_new(path, argc, argv, poll_interval != NULL ? yml_value_as_int(poll_interval) : 0, - conf_to_particle(c, inherited)); + return script_new( + yml_value_as_string(path), argc, argv, + poll_interval != NULL ? yml_value_as_int(poll_interval) : -1, + conf_to_particle(c, inherited)); } static bool @@ -680,12 +681,8 @@ conf_verify_path(keychain_t *chain, const struct yml_node *node) return false; const char *path = yml_value_as_string(node); - - const bool is_tilde = path[0] == '~' && path[1] == '/'; - const bool is_absolute = path[0] == '/'; - - if (!is_tilde && !is_absolute) { - LOG_ERR("%s: path must either be absolute, or begin with '~/'", conf_err_prefix(chain, node)); + if (strlen(path) < 1 || path[0] != '/') { + LOG_ERR("%s: path must be absolute", conf_err_prefix(chain, node)); return false; } @@ -698,27 +695,13 @@ conf_verify_args(keychain_t *chain, const struct yml_node *node) return conf_verify_list(chain, node, &conf_verify_string); } -static bool -conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node) -{ - if (!conf_verify_unsigned(chain, node)) - return false; - - if (yml_value_as_int(node) < min_poll_interval) { - LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval); - return false; - } - - return true; -} - static bool verify_conf(keychain_t *chain, const struct yml_node *node) { static const struct attr_info attrs[] = { {"path", true, &conf_verify_path}, {"args", false, &conf_verify_args}, - {"poll-interval", false, &conf_verify_poll_interval}, + {"poll-interval", false, &conf_verify_unsigned}, MODULE_COMMON_ATTRS, }; diff --git a/modules/sway-xkb.c b/modules/sway-xkb.c index 1507241..96d8388 100644 --- a/modules/sway-xkb.c +++ b/modules/sway-xkb.c @@ -3,15 +3,15 @@ #define LOG_MODULE "sway-xkb" #define LOG_ENABLE_DBG 0 +#include "../log.h" #include "../bar/bar.h" #include "../config-verify.h" #include "../config.h" -#include "../log.h" #include "../particles/dynlist.h" #include "../plugin.h" -#include "i3-common.h" #include "i3-ipc.h" +#include "i3-common.h" #define max(x, y) ((x) > (y) ? (x) : (y)) @@ -21,8 +21,7 @@ struct input { char *layout; }; -struct private -{ +struct private { struct particle *template; int left_spacing; int right_spacing; @@ -90,7 +89,8 @@ content(struct module *mod) } mtx_unlock(&mod->lock); - return dynlist_exposable_new(particles, m->num_existing_inputs, m->left_spacing, m->right_spacing); + return dynlist_exposable_new( + particles, m->num_existing_inputs, m->left_spacing, m->right_spacing); } static bool @@ -121,7 +121,8 @@ handle_input_reply(int sock, int type, const struct json_object *json, void *_mo struct input *input = NULL; for (size_t i = 0; i < m->num_inputs; i++) { struct input *maybe_input = &m->inputs[i]; - if (strcmp(maybe_input->identifier, id) == 0 && !maybe_input->exists) { + if (strcmp(maybe_input->identifier, id) == 0 && !maybe_input->exists) + { input = maybe_input; LOG_DBG("adding: %s", id); @@ -141,7 +142,8 @@ handle_input_reply(int sock, int type, const struct json_object *json, void *_mo /* Get current/active layout */ struct json_object *layout; - if (!json_object_object_get_ex(obj, "xkb_active_layout_name", &layout)) + if (!json_object_object_get_ex( + obj, "xkb_active_layout_name", &layout)) return false; const char *new_layout_str = json_object_get_string(layout); @@ -238,7 +240,8 @@ handle_input_event(int sock, int type, const struct json_object *json, void *_mo /* Get current/active layout */ struct json_object *layout; - if (!json_object_object_get_ex(obj, "xkb_active_layout_name", &layout)) + if (!json_object_object_get_ex( + obj, "xkb_active_layout_name", &layout)) return false; const char *new_layout_str = json_object_get_string(layout); @@ -306,8 +309,8 @@ run(struct module *mod) } static struct module * -sway_xkb_new(struct particle *template, const char *identifiers[], size_t num_identifiers, int left_spacing, - int right_spacing) +sway_xkb_new(struct particle *template, const char *identifiers[], + size_t num_identifiers, int left_spacing, int right_spacing) { struct private *m = calloc(1, sizeof(*m)); m->template = template; @@ -340,32 +343,40 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited) const struct yml_node *left_spacing = yml_get_value(node, "left-spacing"); const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); - int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; - int right = spacing != NULL ? yml_value_as_int(spacing) - : right_spacing != NULL ? yml_value_as_int(right_spacing) - : 0; + int left = spacing != NULL ? yml_value_as_int(spacing) : + left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; + int right = spacing != NULL ? yml_value_as_int(spacing) : + right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; const struct yml_node *ids = yml_get_value(node, "identifiers"); const size_t num_ids = yml_list_length(ids); const char *identifiers[num_ids]; size_t i = 0; - for (struct yml_list_iter it = yml_list_iter(ids); it.node != NULL; yml_list_next(&it), i++) { + for (struct yml_list_iter it = yml_list_iter(ids); + it.node != NULL; + yml_list_next(&it), i++) + { identifiers[i] = yml_value_as_string(it.node); } - return sway_xkb_new(conf_to_particle(c, inherited), identifiers, num_ids, left, right); + return sway_xkb_new( + conf_to_particle(c, inherited), identifiers, num_ids, left, right); } static bool verify_identifiers(keychain_t *chain, const struct yml_node *node) { if (!yml_is_list(node)) { - LOG_ERR("%s: identifiers must be a list of strings", conf_err_prefix(chain, node)); + LOG_ERR("%s: identifiers must be a list of strings", + conf_err_prefix(chain, node)); return false; } - for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) { + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it)) + { if (!conf_verify_string(chain, it.node)) return false; } @@ -393,5 +404,5 @@ const struct module_iface module_sway_xkb_iface = { }; #if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) -extern const struct module_iface iface __attribute__((weak, alias("module_sway_xkb_iface"))); +extern const struct module_iface iface __attribute__((weak, alias("module_sway_xkb_iface"))) ; #endif diff --git a/modules/xkb.c b/modules/xkb.c index e8e3c91..edd0afe 100644 --- a/modules/xkb.c +++ b/modules/xkb.c @@ -1,7 +1,7 @@ -#include -#include #include #include +#include +#include #include @@ -10,10 +10,10 @@ #define LOG_MODULE "xkb" #define LOG_ENABLE_DBG 0 -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../plugin.h" #include "../xcb.h" @@ -32,8 +32,7 @@ struct indicators { char **names; }; -struct private -{ +struct private { struct particle *label; struct indicators indicators; struct layouts layouts; @@ -118,8 +117,10 @@ xkb_enable(xcb_connection_t *conn) { xcb_generic_error_t *err; - xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); - xcb_xkb_use_extension_reply_t *reply = xcb_xkb_use_extension_reply(conn, cookie, &err); + xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension( + conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); + xcb_xkb_use_extension_reply_t *reply = xcb_xkb_use_extension_reply( + conn, cookie, &err); if (err != NULL) { LOG_ERR("failed to query for XKB extension: %s", xcb_error(err)); @@ -141,7 +142,8 @@ xkb_enable(xcb_connection_t *conn) static int get_xkb_event_base(xcb_connection_t *conn) { - const struct xcb_query_extension_reply_t *reply = xcb_get_extension_data(conn, &xcb_xkb_id); + const struct xcb_query_extension_reply_t *reply = xcb_get_extension_data( + conn, &xcb_xkb_id); if (reply == NULL) { LOG_ERR("failed to get XKB extension data"); @@ -157,14 +159,19 @@ get_xkb_event_base(xcb_connection_t *conn) } static bool -get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, struct indicators *indicators) +get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, + struct indicators *indicators) { xcb_generic_error_t *err; - xcb_xkb_get_names_cookie_t cookie = xcb_xkb_get_names(conn, XCB_XKB_ID_USE_CORE_KBD, - XCB_XKB_NAME_DETAIL_GROUP_NAMES | XCB_XKB_NAME_DETAIL_SYMBOLS - | XCB_XKB_NAME_DETAIL_INDICATOR_NAMES); + xcb_xkb_get_names_cookie_t cookie = xcb_xkb_get_names( + conn, + XCB_XKB_ID_USE_CORE_KBD, + XCB_XKB_NAME_DETAIL_GROUP_NAMES | + XCB_XKB_NAME_DETAIL_SYMBOLS | + XCB_XKB_NAME_DETAIL_INDICATOR_NAMES); - xcb_xkb_get_names_reply_t *reply = xcb_xkb_get_names_reply(conn, cookie, &err); + xcb_xkb_get_names_reply_t *reply = xcb_xkb_get_names_reply( + conn, cookie, &err); if (err != NULL) { LOG_ERR("failed to get layouts and indicators: %s", xcb_error(err)); @@ -174,18 +181,22 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru xcb_xkb_get_names_value_list_t vlist; void *buf = xcb_xkb_get_names_value_list(reply); - xcb_xkb_get_names_value_list_unpack(buf, reply->nTypes, reply->indicators, reply->virtualMods, reply->groupNames, - reply->nKeys, reply->nKeyAliases, reply->nRadioGroups, reply->which, &vlist); + xcb_xkb_get_names_value_list_unpack( + buf, reply->nTypes, reply->indicators, reply->virtualMods, + reply->groupNames, reply->nKeys, reply->nKeyAliases, + reply->nRadioGroups, reply->which, &vlist); /* Number of groups (aka layouts) */ layouts->count = xcb_xkb_get_names_value_list_groups_length(reply, &vlist); layouts->layouts = calloc(layouts->count, sizeof(layouts->layouts[0])); /* Number of indicators */ - indicators->count = xcb_xkb_get_names_value_list_indicator_names_length(reply, &vlist); + indicators->count = xcb_xkb_get_names_value_list_indicator_names_length( + reply, &vlist); indicators->names = calloc(indicators->count, sizeof(indicators->names[0])); - xcb_get_atom_name_cookie_t symbols_name_cookie = xcb_get_atom_name(conn, vlist.symbolsName); + xcb_get_atom_name_cookie_t symbols_name_cookie = xcb_get_atom_name( + conn, vlist.symbolsName); xcb_get_atom_name_cookie_t group_name_cookies[layouts->count]; for (size_t i = 0; i < layouts->count; i++) @@ -198,14 +209,17 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru char *symbols = NULL; /* Get layout short names (e.g. "us") */ - xcb_get_atom_name_reply_t *atom_name = xcb_get_atom_name_reply(conn, symbols_name_cookie, &err); + xcb_get_atom_name_reply_t *atom_name = xcb_get_atom_name_reply( + conn, symbols_name_cookie, &err); if (err != NULL) { LOG_ERR("failed to get 'symbols' atom name: %s", xcb_error(err)); free(err); goto err; } - symbols = strndup(xcb_get_atom_name_name(atom_name), xcb_get_atom_name_name_length(atom_name)); + symbols = strndup( + xcb_get_atom_name_name(atom_name), + xcb_get_atom_name_name_length(atom_name)); LOG_DBG("symbols: %s", symbols); free(atom_name); @@ -218,7 +232,9 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru goto err; } - layouts->layouts[i].name = strndup(xcb_get_atom_name_name(atom_name), xcb_get_atom_name_name_length(atom_name)); + layouts->layouts[i].name = strndup( + xcb_get_atom_name_name(atom_name), + xcb_get_atom_name_name_length(atom_name)); LOG_DBG("layout #%zd: long name: %s", i, layouts->layouts[i].name); free(atom_name); @@ -233,7 +249,9 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru goto err; } - indicators->names[i] = strndup(xcb_get_atom_name_name(atom_name), xcb_get_atom_name_name_length(atom_name)); + indicators->names[i] = strndup( + xcb_get_atom_name_name(atom_name), + xcb_get_atom_name_name_length(atom_name)); LOG_DBG("indicator #%zd: %s", i, indicators->names[i]); free(atom_name); @@ -241,7 +259,8 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru /* e.g. pc+us+inet(evdev)+group(..) */ size_t layout_idx = 0; - for (char *tok_ctx = NULL, *tok = strtok_r(symbols, "+", &tok_ctx); tok != NULL; + for (char *tok_ctx = NULL, *tok = strtok_r(symbols, "+", &tok_ctx); + tok != NULL; tok = strtok_r(NULL, "+", &tok_ctx)) { char *fname = strtok(tok, "()"); @@ -260,7 +279,8 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru continue; if (layout_idx >= layouts->count) { - LOG_ERR("layout vs group name count mismatch: %zd > %zd", layout_idx + 1, layouts->count); + LOG_ERR("layout vs group name count mismatch: %zd > %zd", + layout_idx + 1, layouts->count); goto err; } @@ -270,7 +290,8 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, stru } if (layout_idx != layouts->count) { - LOG_ERR("layout vs group name count mismatch: %zd != %zd", layout_idx, layouts->count); + LOG_ERR("layout vs group name count mismatch: %zd != %zd", + layout_idx, layouts->count); goto err; } @@ -291,8 +312,10 @@ get_current_layout(xcb_connection_t *conn) { xcb_generic_error_t *err; - xcb_xkb_get_state_cookie_t cookie = xcb_xkb_get_state(conn, XCB_XKB_ID_USE_CORE_KBD); - xcb_xkb_get_state_reply_t *reply = xcb_xkb_get_state_reply(conn, cookie, &err); + xcb_xkb_get_state_cookie_t cookie = xcb_xkb_get_state( + conn, XCB_XKB_ID_USE_CORE_KBD); + xcb_xkb_get_state_reply_t *reply = xcb_xkb_get_state_reply( + conn, cookie, &err); if (err != NULL) { LOG_ERR("failed to get XKB state: %s", xcb_error(err)); @@ -309,8 +332,10 @@ static uint32_t get_indicator_state(xcb_connection_t *conn) { xcb_generic_error_t *err; - xcb_xkb_get_indicator_state_cookie_t cookie = xcb_xkb_get_indicator_state(conn, XCB_XKB_ID_USE_CORE_KBD); - xcb_xkb_get_indicator_state_reply_t *reply = xcb_xkb_get_indicator_state_reply(conn, cookie, &err); + xcb_xkb_get_indicator_state_cookie_t cookie = xcb_xkb_get_indicator_state( + conn, XCB_XKB_ID_USE_CORE_KBD); + xcb_xkb_get_indicator_state_reply_t *reply = xcb_xkb_get_indicator_state_reply( + conn, cookie, &err); if (err != NULL) { LOG_ERR("failed to get indicator state: %s", xcb_error(err)); @@ -328,14 +353,23 @@ get_indicator_state(xcb_connection_t *conn) static bool register_for_events(xcb_connection_t *conn) { - xcb_void_cookie_t cookie - = xcb_xkb_select_events_checked(conn, XCB_XKB_ID_USE_CORE_KBD, - (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY - | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY), - 0, - (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY - | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY), - 0, 0, NULL); + xcb_void_cookie_t cookie = xcb_xkb_select_events_checked( + conn, + XCB_XKB_ID_USE_CORE_KBD, + ( + XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | + XCB_XKB_EVENT_TYPE_STATE_NOTIFY | + XCB_XKB_EVENT_TYPE_MAP_NOTIFY | + XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY + ), + 0, + ( + XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | + XCB_XKB_EVENT_TYPE_STATE_NOTIFY | + XCB_XKB_EVENT_TYPE_MAP_NOTIFY | + XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY + ), + 0, 0, NULL); xcb_generic_error_t *err = xcb_request_check(conn, cookie); if (err != NULL) { @@ -359,7 +393,10 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) assert(xcb_fd >= 0); while (!has_error) { - struct pollfd pfds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = xcb_fd, .events = POLLIN | POLLHUP}}; + struct pollfd pfds[] = { + {.fd = mod->abort_fd, .events = POLLIN }, + {.fd = xcb_fd, .events = POLLIN | POLLHUP } + }; /* Use poll() since xcb_wait_for_events() doesn't return on signals */ if (poll(pfds, sizeof(pfds) / sizeof(pfds[0]), -1) < 0) { @@ -388,7 +425,9 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) * not for long though... */ - for (xcb_generic_event_t *_evt = xcb_wait_for_event(conn); _evt != NULL; _evt = xcb_poll_for_event(conn)) { + for (xcb_generic_event_t *_evt = xcb_wait_for_event(conn); + _evt != NULL; + _evt = xcb_poll_for_event(conn)) { if (_evt->response_type != xkb_event_base) { LOG_WARN("non-XKB event ignored: %d", _evt->response_type); @@ -396,7 +435,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) continue; } - switch (_evt->pad0) { + switch(_evt->pad0) { default: LOG_WARN("unimplemented XKB event: %d", _evt->pad0); break; @@ -424,7 +463,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) mtx_unlock(&mod->lock); bar->refresh(bar); } else { - /* Can happen while transitioning to a new map */ + /* Can happen while transitioning to a new map */ free_layouts(layouts); free_indicators(indicators); } @@ -433,7 +472,8 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) } case XCB_XKB_STATE_NOTIFY: { - const xcb_xkb_state_notify_event_t *evt = (const xcb_xkb_state_notify_event_t *)_evt; + const xcb_xkb_state_notify_event_t *evt = + (const xcb_xkb_state_notify_event_t *)_evt; if (evt->changed & XCB_XKB_STATE_PART_GROUP_STATE) { mtx_lock(&mod->lock); @@ -450,8 +490,8 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) break; case XCB_XKB_INDICATOR_STATE_NOTIFY: { - const xcb_xkb_indicator_state_notify_event_t *evt - = (const xcb_xkb_indicator_state_notify_event_t *)_evt; + const xcb_xkb_indicator_state_notify_event_t *evt = + (const xcb_xkb_indicator_state_notify_event_t *)_evt; #if 0 size_t idx = __builtin_ctz(evt->stateChanged); @@ -468,7 +508,8 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base) continue; bool enabled = (evt->state >> i) & 1; - LOG_DBG("%s: %s", m->indicators.names[i], enabled ? "enabled" : "disabled"); + LOG_DBG("%s: %s", m->indicators.names[i], + enabled ? "enabled" : "disabled"); const char *name = m->indicators.names[i]; bool is_caps = strcasecmp(name, "caps lock") == 0; @@ -568,12 +609,18 @@ talk_to_xkb(struct module *mod, xcb_connection_t *conn) size_t idx = 0; for (size_t i = 0; i < layouts.count; i++) { - idx += snprintf(&buf[idx], sizeof(buf) - idx, "%s%s (%s)%s", i == m->current ? "*" : "", - layouts.layouts[i].name, layouts.layouts[i].symbol, i + 1 < layouts.count ? ", " : ""); + idx += snprintf(&buf[idx], sizeof(buf) - idx, "%s%s (%s)%s", + i == m->current ? "*" : "", + layouts.layouts[i].name, + layouts.layouts[i].symbol, + i + 1 < layouts.count ? ", " : ""); } - LOG_INFO("layouts: %s, caps-lock:%s, num-lock:%s, scroll-lock:%s", buf, caps_lock ? "on" : "off", - num_lock ? "on" : "off", scroll_lock ? "on" : "off"); + LOG_INFO("layouts: %s, caps-lock:%s, num-lock:%s, scroll-lock:%s", + buf, + caps_lock ? "on" : "off", + num_lock ? "on" : "off", + scroll_lock ? "on" : "off"); } mtx_lock(&mod->lock); diff --git a/modules/xwindow.c b/modules/xwindow.c index c730128..e53114e 100644 --- a/modules/xwindow.c +++ b/modules/xwindow.c @@ -1,30 +1,29 @@ -#include -#include -#include #include #include #include -#include +#include +#include #include +#include +#include +#include #include #include -#include #include #include #include #define LOG_MODULE "xwindow" -#include "../bar/bar.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../bar/bar.h" +#include "../config.h" +#include "../config-verify.h" #include "../plugin.h" #include "../xcb.h" -struct private -{ +struct private { /* Accessed from bar thread only */ struct particle *label; @@ -49,19 +48,23 @@ static void update_active_window(struct private *m) { if (m->active_win != 0) { - xcb_void_cookie_t c = xcb_change_window_attributes_checked(m->conn, m->active_win, XCB_CW_EVENT_MASK, - (const uint32_t[]){XCB_EVENT_MASK_NO_EVENT}); + xcb_void_cookie_t c = xcb_change_window_attributes_checked( + m->conn, m->active_win, XCB_CW_EVENT_MASK, + (const uint32_t []){XCB_EVENT_MASK_NO_EVENT}); xcb_generic_error_t *e = xcb_request_check(m->conn, c); if (e != NULL) { - LOG_DBG("failed to de-register events on previous active window: %s", xcb_error(e)); + LOG_DBG( + "failed to de-register events on previous active window: %s", + xcb_error(e)); free(e); } m->active_win = 0; } - xcb_get_property_cookie_t c = xcb_get_property(m->conn, 0, m->root_win, _NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, 32); + xcb_get_property_cookie_t c = xcb_get_property( + m->conn, 0, m->root_win, _NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, 32); xcb_generic_error_t *e; xcb_get_property_reply_t *r = xcb_get_property_reply(m->conn, c, &e); @@ -83,8 +86,9 @@ update_active_window(struct private *m) free(r); if (m->active_win != 0) { - xcb_change_window_attributes(m->conn, m->active_win, XCB_CW_EVENT_MASK, - (const uint32_t[]){XCB_EVENT_MASK_PROPERTY_CHANGE}); + xcb_change_window_attributes( + m->conn, m->active_win, XCB_CW_EVENT_MASK, + (const uint32_t []){XCB_EVENT_MASK_PROPERTY_CHANGE}); } } @@ -101,7 +105,8 @@ update_application(struct module *mod) if (m->active_win == 0) return; - xcb_get_property_cookie_t c = xcb_get_property(m->conn, 0, m->active_win, _NET_WM_PID, XCB_ATOM_CARDINAL, 0, 32); + xcb_get_property_cookie_t c = xcb_get_property( + m->conn, 0, m->active_win, _NET_WM_PID, XCB_ATOM_CARDINAL, 0, 32); xcb_generic_error_t *e; xcb_get_property_reply_t *r = xcb_get_property_reply(m->conn, c, &e); @@ -130,7 +135,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; @@ -159,11 +164,12 @@ update_title(struct module *mod) if (m->active_win == 0) return; - xcb_get_property_cookie_t c1 - = xcb_get_property(m->conn, 0, m->active_win, _NET_WM_VISIBLE_NAME, UTF8_STRING, 0, 1000); - xcb_get_property_cookie_t c2 = xcb_get_property(m->conn, 0, m->active_win, _NET_WM_NAME, UTF8_STRING, 0, 1000); - xcb_get_property_cookie_t c3 - = xcb_get_property(m->conn, 0, m->active_win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1000); + xcb_get_property_cookie_t c1 = xcb_get_property( + m->conn, 0, m->active_win, _NET_WM_VISIBLE_NAME, UTF8_STRING, 0, 1000); + xcb_get_property_cookie_t c2 = xcb_get_property( + m->conn, 0, m->active_win, _NET_WM_NAME, UTF8_STRING, 0, 1000); + xcb_get_property_cookie_t c3 = xcb_get_property( + m->conn, 0, m->active_win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1000); xcb_generic_error_t *e1, *e2, *e3; xcb_get_property_reply_t *r1 = xcb_get_property_reply(m->conn, c1, &e1); @@ -201,7 +207,7 @@ update_title(struct module *mod) free(r1); free(r2); free(r3); -} + } static int run(struct module *mod) @@ -221,16 +227,19 @@ run(struct module *mod) /* Need a window(?) to be able to process events */ m->monitor_win = xcb_generate_id(m->conn); - xcb_create_window(m->conn, screen->root_depth, m->monitor_win, screen->root, -1, -1, 1, 1, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_OVERRIDE_REDIRECT, - (const uint32_t[]){1}); + xcb_create_window(m->conn, screen->root_depth, m->monitor_win, screen->root, + -1, -1, 1, 1, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, + XCB_CW_OVERRIDE_REDIRECT, (const uint32_t []){1}); xcb_map_window(m->conn, m->monitor_win); /* Register for property changes on root window. This allows us to * catch e.g. window switches etc */ - xcb_change_window_attributes(m->conn, screen->root, XCB_CW_EVENT_MASK, - (const uint32_t[]){XCB_EVENT_MASK_PROPERTY_CHANGE}); + xcb_change_window_attributes( + m->conn, screen->root, XCB_CW_EVENT_MASK, + (const uint32_t []){XCB_EVENT_MASK_PROPERTY_CHANGE}); xcb_flush(m->conn); @@ -243,7 +252,8 @@ run(struct module *mod) int xcb_fd = xcb_get_file_descriptor(m->conn); while (true) { - struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = xcb_fd, .events = POLLIN}}; + struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, + {.fd = xcb_fd, .events = POLLIN}}; if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) < 0) { if (errno == EINTR) continue; @@ -257,7 +267,10 @@ run(struct module *mod) break; } - for (xcb_generic_event_t *_e = xcb_wait_for_event(m->conn); _e != NULL; _e = xcb_poll_for_event(m->conn)) { + for (xcb_generic_event_t *_e = xcb_wait_for_event(m->conn); + _e != NULL; + _e = xcb_poll_for_event(m->conn)) + { switch (XCB_EVENT_RESPONSE_TYPE(_e)) { case 0: LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)_e)); @@ -265,13 +278,18 @@ run(struct module *mod) case XCB_PROPERTY_NOTIFY: { xcb_property_notify_event_t *e = (xcb_property_notify_event_t *)_e; - if (e->atom == _NET_ACTIVE_WINDOW || e->atom == _NET_CURRENT_DESKTOP) { + if (e->atom == _NET_ACTIVE_WINDOW || + e->atom == _NET_CURRENT_DESKTOP) + { /* Active desktop and/or window changed */ update_active_window(m); update_application(mod); update_title(mod); mod->bar->refresh(mod->bar); - } else if (e->atom == _NET_WM_VISIBLE_NAME || e->atom == _NET_WM_NAME || e->atom == XCB_ATOM_WM_NAME) { + } else if (e->atom == _NET_WM_VISIBLE_NAME || + e->atom == _NET_WM_NAME || + e->atom == XCB_ATOM_WM_NAME) + { assert(e->window == m->active_win); update_title(mod); mod->bar->refresh(mod->bar); diff --git a/particle.c b/particle.c index f35b5d1..fe1d138 100644 --- a/particle.c +++ b/particle.c @@ -1,21 +1,21 @@ #include "particle.h" -#include -#include -#include #include #include #include +#include +#include +#include -#include -#include #include +#include #include +#include #define LOG_MODULE "particle" #define LOG_ENABLE_DBG 0 -#include "bar/bar.h" #include "log.h" +#include "bar/bar.h" void particle_default_destroy(struct particle *particle) @@ -29,8 +29,10 @@ particle_default_destroy(struct particle *particle) } struct particle * -particle_common_new(int left_margin, int right_margin, char **on_click_templates, struct fcft_font *font, - enum font_shaping font_shaping, pixman_color_t foreground, struct deco *deco) +particle_common_new(int left_margin, int right_margin, + const char **on_click_templates, + struct fcft_font *font, enum font_shaping font_shaping, + pixman_color_t foreground, struct deco *deco) { struct particle *p = calloc(1, sizeof(*p)); p->left_margin = left_margin; @@ -44,7 +46,7 @@ particle_common_new(int left_margin, int right_margin, char **on_click_templates for (size_t i = 0; i < MOUSE_BTN_COUNT; i++) { if (on_click_templates[i] != NULL) { p->have_on_click_template = true; - p->on_click_templates[i] = on_click_templates[i]; + p->on_click_templates[i] = strdup(on_click_templates[i]); } } } @@ -61,11 +63,13 @@ exposable_default_destroy(struct exposable *exposable) } void -exposable_render_deco(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height) +exposable_render_deco(const struct exposable *exposable, + pixman_image_t *pix, int x, int y, int height) { const struct deco *deco = exposable->particle->deco; if (deco != NULL) deco->expose(deco, pix, x, y, exposable->width, height); + } static bool @@ -110,7 +114,9 @@ tokenize_cmdline(char *cmdline, char ***argv) return false; } - if (!push_argv(argv, &argv_size, p, &idx) || !push_argv(argv, &argv_size, NULL, &idx)) { + if (!push_argv(argv, &argv_size, p, &idx) || + !push_argv(argv, &argv_size, NULL, &idx)) + { goto err; } else return true; @@ -146,7 +152,8 @@ err: } void -exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, +exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, + enum mouse_event event, enum mouse_button btn, int x, int y) { #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG @@ -161,13 +168,17 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mo [MOUSE_BTN_PREVIOUS] = "previous", [MOUSE_BTN_NEXT] = "next", }; - LOG_DBG("on_mouse: exposable=%p, event=%s, btn=%s, x=%d, y=%d (on-click=%s)", exposable, - event == ON_MOUSE_MOTION ? "motion" : "click", button_name[btn], x, y, exposable->on_click[btn]); + LOG_DBG("on_mouse: exposable=%p, event=%s, btn=%s, x=%d, y=%d (on-click=%s)", + exposable, event == ON_MOUSE_MOTION ? "motion" : "click", + button_name[btn], x, y, exposable->on_click[btn]); #endif /* If we have a handler, change cursor to a hand */ - const char *cursor - = (exposable->particle != NULL && exposable->particle->have_on_click_template) ? "hand2" : "left_ptr"; + const char *cursor = + (exposable->particle != NULL && + exposable->particle->have_on_click_template) + ? "hand2" + : "left_ptr"; bar->set_cursor(bar, cursor); /* If this is a mouse click, and we have a handler, execute it */ @@ -235,7 +246,7 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mo case 0: /* Child */ - close(pipe_fds[0]); /* Close read end */ + close(pipe_fds[0]); /* Close read end */ LOG_DBG("executing on-click handler: %s", cmd); @@ -243,8 +254,11 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mo sigemptyset(&mask); const struct sigaction sa = {.sa_handler = SIG_DFL}; - if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0 - || sigaction(SIGCHLD, &sa, NULL) < 0 || sigprocmask(SIG_SETMASK, &mask, NULL) < 0) { + if (sigaction(SIGINT, &sa, NULL) < 0 || + sigaction(SIGTERM, &sa, NULL) < 0 || + sigaction(SIGCHLD, &sa, NULL) < 0 || + sigprocmask(SIG_SETMASK, &mask, NULL) < 0) + { goto fail; } @@ -257,8 +271,10 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mo goto fail; } - if (dup2(dev_null_r, STDIN_FILENO) == -1 || dup2(dev_null_w, STDOUT_FILENO) == -1 - || dup2(dev_null_w, STDERR_FILENO) == -1) { + if (dup2(dev_null_r, STDIN_FILENO) == -1 || + dup2(dev_null_w, STDOUT_FILENO) == -1 || + dup2(dev_null_w, STDERR_FILENO) == -1) + { LOG_ERRNO("failed to redirect stdin/stdout/stderr"); goto fail; } @@ -300,7 +316,10 @@ exposable_common_new(const struct particle *particle, const struct tag_set *tags exposable->particle = particle; if (particle != NULL && particle->have_on_click_template) { - tags_expand_templates(exposable->on_click, (const char **)particle->on_click_templates, MOUSE_BTN_COUNT, tags); + tags_expand_templates( + exposable->on_click, + (const char **)particle->on_click_templates, + MOUSE_BTN_COUNT, tags); } exposable->destroy = &exposable_default_destroy; exposable->on_mouse = &exposable_default_on_mouse; diff --git a/particle.h b/particle.h index bc8648d..c92c5fc 100644 --- a/particle.h +++ b/particle.h @@ -42,9 +42,11 @@ struct particle { struct deco *deco; void (*destroy)(struct particle *particle); - struct exposable *(*instantiate)(const struct particle *particle, const struct tag_set *tags); + struct exposable *(*instantiate)(const struct particle *particle, + const struct tag_set *tags); }; + struct exposable { const struct particle *particle; void *private; @@ -54,31 +56,38 @@ struct exposable { void (*destroy)(struct exposable *exposable); int (*begin_expose)(struct exposable *exposable); - void (*expose)(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height); + void (*expose)(const struct exposable *exposable, pixman_image_t *pix, + int x, int y, int height); - void (*on_mouse)(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, - int y); + void (*on_mouse)(struct exposable *exposable, struct bar *bar, + enum mouse_event event, enum mouse_button btn, int x, int y); }; -struct particle *particle_common_new(int left_margin, int right_margin, char *on_click_templates[], - struct fcft_font *font, enum font_shaping font_shaping, pixman_color_t foreground, - struct deco *deco); +struct particle *particle_common_new( + int left_margin, int right_margin, const char *on_click_templates[], + struct fcft_font *font, enum font_shaping font_shaping, + pixman_color_t foreground, struct deco *deco); void particle_default_destroy(struct particle *particle); -struct exposable *exposable_common_new(const struct particle *particle, const struct tag_set *tags); +struct exposable *exposable_common_new( + const struct particle *particle, const struct tag_set *tags); void exposable_default_destroy(struct exposable *exposable); -void exposable_render_deco(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height); +void exposable_render_deco( + const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height); -void exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, - enum mouse_button btn, int x, int y); +void exposable_default_on_mouse( + struct exposable *exposable, struct bar *bar, + enum mouse_event event, enum mouse_button btn, int x, int y); /* List of attributes *all* particles implement */ -#define PARTICLE_COMMON_ATTRS \ - {"margin", false, &conf_verify_unsigned}, {"left-margin", false, &conf_verify_unsigned}, \ - {"right-margin", false, &conf_verify_unsigned}, {"on-click", false, &conf_verify_on_click}, \ - {"font", false, &conf_verify_font}, {"font-shaping", false, &conf_verify_font_shaping}, \ - {"foreground", false, &conf_verify_color}, {"deco", false, &conf_verify_decoration}, \ - { \ - NULL, false, NULL \ - } +#define PARTICLE_COMMON_ATTRS \ + {"margin", false, &conf_verify_unsigned}, \ + {"left-margin", false, &conf_verify_unsigned}, \ + {"right-margin", false, &conf_verify_unsigned}, \ + {"on-click", false, &conf_verify_on_click}, \ + {"font", false, &conf_verify_font}, \ + {"font-shaping", false, &conf_verify_font_shaping}, \ + {"foreground", false, &conf_verify_color}, \ + {"deco", false, &conf_verify_decoration}, \ + {NULL, false, NULL} diff --git a/particles/dynlist.c b/particles/dynlist.c index fcd0066..5b64dbe 100644 --- a/particles/dynlist.c +++ b/particles/dynlist.c @@ -1,14 +1,13 @@ #include "dynlist.h" -#include #include +#include #define LOG_MODULE "dynlist" #include "../log.h" #include "../particle.h" -struct private -{ +struct private { int left_spacing; int right_spacing; @@ -72,13 +71,13 @@ dynlist_expose(const struct exposable *exposable, pixman_image_t *pix, int x, in for (size_t i = 0; i < e->count; i++) { const struct exposable *ee = e->exposables[i]; ee->expose(ee, pix, x + left_spacing, y, height); - if (e->widths[i] > 0) - x += left_spacing + e->widths[i] + right_spacing; + x += left_spacing + e->widths[i] + right_spacing; } } static void -on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) +on_mouse(struct exposable *exposable, struct bar *bar, + enum mouse_event event, enum mouse_button btn, int x, int y) { const struct private *e = exposable->private; @@ -87,16 +86,17 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, e return; } - int px = /*p->left_margin;*/ 0; + int px = /*p->left_margin;*/0; for (size_t i = 0; i < e->count; i++) { if (x >= px && x < px + e->exposables[i]->width) { if (e->exposables[i]->on_mouse != NULL) { - e->exposables[i]->on_mouse(e->exposables[i], bar, event, btn, x - px, y); + e->exposables[i]->on_mouse( + e->exposables[i], bar, event, btn, x - px, y); } return; } - if (e->exposables[i]->width > 0) - px += e->left_spacing + e->exposables[i]->width + e->right_spacing; + + px += e->left_spacing + e->exposables[i]->width + e->right_spacing; } LOG_DBG("on_mouse missed all sub-particles"); @@ -104,7 +104,8 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, e } struct exposable * -dynlist_exposable_new(struct exposable **exposables, size_t count, int left_spacing, int right_spacing) +dynlist_exposable_new(struct exposable **exposables, size_t count, + int left_spacing, int right_spacing) { struct private *e = calloc(1, sizeof(*e)); e->count = count; diff --git a/particles/dynlist.h b/particles/dynlist.h index 810df45..4867997 100644 --- a/particles/dynlist.h +++ b/particles/dynlist.h @@ -3,5 +3,5 @@ #include struct particle; -struct exposable *dynlist_exposable_new(struct exposable **exposables, size_t count, int left_spacing, - int right_spacing); +struct exposable *dynlist_exposable_new( + struct exposable **exposables, size_t count, int left_spacing, int right_spacing); diff --git a/particles/empty.c b/particles/empty.c index 052eacd..5c0be16 100644 --- a/particles/empty.c +++ b/particles/empty.c @@ -1,14 +1,15 @@ #include -#include "../config-verify.h" #include "../config.h" +#include "../config-verify.h" #include "../particle.h" #include "../plugin.h" static int begin_expose(struct exposable *exposable) { - exposable->width = exposable->particle->left_margin + exposable->particle->right_margin; + exposable->width = exposable->particle->left_margin + + exposable->particle->right_margin; return exposable->width; } diff --git a/particles/list.c b/particles/list.c index 83b5d0c..a2c37c6 100644 --- a/particles/list.c +++ b/particles/list.c @@ -2,14 +2,13 @@ #define LOG_MODULE "list" #define LOG_ENABLE_DBG 0 -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../config.h" +#include "../config-verify.h" #include "../particle.h" #include "../plugin.h" -struct private -{ +struct private { struct particle **particles; size_t count; int left_spacing, right_spacing; @@ -22,6 +21,7 @@ struct eprivate { int left_spacing, right_spacing; }; + static void exposable_destroy(struct exposable *exposable) { @@ -80,18 +80,21 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int for (size_t i = 0; i < e->count; i++) { const struct exposable *ee = e->exposables[i]; ee->expose(ee, pix, x + left_spacing, y, height); - if (e->widths[i] > 0) - x += left_spacing + e->widths[i] + right_spacing; + x += left_spacing + e->widths[i] + right_spacing; } } static void -on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) +on_mouse(struct exposable *exposable, struct bar *bar, + enum mouse_event event, enum mouse_button btn, int x, int y) { const struct particle *p = exposable->particle; const struct eprivate *e = exposable->private; - if ((event == ON_MOUSE_MOTION && exposable->particle->have_on_click_template) || exposable->on_click[btn] != NULL) { + if ((event == ON_MOUSE_MOTION && + exposable->particle->have_on_click_template) || + exposable->on_click[btn] != NULL) + { /* We have our own handler */ exposable_default_on_mouse(exposable, bar, event, btn, x, y); return; @@ -101,12 +104,13 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, e for (size_t i = 0; i < e->count; i++) { if (x >= px && x < px + e->exposables[i]->width) { if (e->exposables[i]->on_mouse != NULL) { - e->exposables[i]->on_mouse(e->exposables[i], bar, event, btn, x - px, y); + e->exposables[i]->on_mouse( + e->exposables[i], bar, event, btn, x - px, y); } return; } - if (e->exposables[i]->width > 0) - px += e->left_spacing + e->exposables[i]->width + e->right_spacing; + + px += e->left_spacing + e->exposables[i]->width + e->right_spacing; } /* We're between sub-particles (or in the left/right margin) */ @@ -152,8 +156,9 @@ particle_destroy(struct particle *particle) } struct particle * -particle_list_new(struct particle *common, struct particle *particles[], size_t count, int left_spacing, - int right_spacing) +particle_list_new(struct particle *common, + struct particle *particles[], size_t count, + int left_spacing, int right_spacing) { struct private *p = calloc(1, sizeof(*p)); p->particles = malloc(count * sizeof(p->particles[0])); @@ -178,20 +183,21 @@ from_conf(const struct yml_node *node, struct particle *common) const struct yml_node *_left_spacing = yml_get_value(node, "left-spacing"); const struct yml_node *_right_spacing = yml_get_value(node, "right-spacing"); - int left_spacing = spacing != NULL ? yml_value_as_int(spacing) - : _left_spacing != NULL ? yml_value_as_int(_left_spacing) - : 0; - int right_spacing = spacing != NULL ? yml_value_as_int(spacing) - : _right_spacing != NULL ? yml_value_as_int(_right_spacing) - : 2; + int left_spacing = spacing != NULL ? yml_value_as_int(spacing) : + _left_spacing != NULL ? yml_value_as_int(_left_spacing) : 0; + int right_spacing = spacing != NULL ? yml_value_as_int(spacing) : + _right_spacing != NULL ? yml_value_as_int(_right_spacing) : 2; size_t count = yml_list_length(items); struct particle *parts[count]; size_t idx = 0; - for (struct yml_list_iter it = yml_list_iter(items); it.node != NULL; yml_list_next(&it), idx++) { - parts[idx] - = conf_to_particle(it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground}); + for (struct yml_list_iter it = yml_list_iter(items); + it.node != NULL; + yml_list_next(&it), idx++) + { + parts[idx] = conf_to_particle( + it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground}); } return particle_list_new(common, parts, count, left_spacing, right_spacing); diff --git a/particles/map.c b/particles/map.c index c5510ff..82a1ee0 100644 --- a/particles/map.c +++ b/particles/map.c @@ -1,146 +1,65 @@ -#include -#include #include #include +#include +#include #define LOG_MODULE "map" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../config.h" +#include "../config-verify.h" #include "../particle.h" #include "../plugin.h" #include "dynlist.h" #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 +bool int_condition(const long tag_value, const long cond_value, enum map_op op) { switch (op) { - case MAP_OP_EQ: - return tag_value == cond_value; - case MAP_OP_NE: - return tag_value != cond_value; - case MAP_OP_LE: - return tag_value <= cond_value; - case MAP_OP_LT: - return tag_value < cond_value; - case MAP_OP_GE: - return tag_value >= cond_value; - case MAP_OP_GT: - return tag_value > cond_value; - case MAP_OP_SELF: - LOG_WARN("using int tag as bool"); - default: - return false; + case MAP_OP_EQ: return tag_value == cond_value; + case MAP_OP_NE: return tag_value != cond_value; + case MAP_OP_LE: return tag_value <= cond_value; + case MAP_OP_LT: return tag_value < cond_value; + case MAP_OP_GE: return tag_value >= cond_value; + case MAP_OP_GT: return tag_value > cond_value; + case MAP_OP_SELF: LOG_WARN("using int tag as bool"); + default: return false; } } -static bool +bool float_condition(const double tag_value, const double cond_value, enum map_op op) { switch (op) { - case MAP_OP_EQ: - return tag_value == cond_value; - case MAP_OP_NE: - return tag_value != cond_value; - case MAP_OP_LE: - return tag_value <= cond_value; - case MAP_OP_LT: - return tag_value < cond_value; - case MAP_OP_GE: - return tag_value >= cond_value; - case MAP_OP_GT: - return tag_value > cond_value; - case MAP_OP_SELF: - LOG_WARN("using float tag as bool"); - default: - return false; + case MAP_OP_EQ: return tag_value == cond_value; + case MAP_OP_NE: return tag_value != cond_value; + case MAP_OP_LE: return tag_value <= cond_value; + case MAP_OP_LT: return tag_value < cond_value; + case MAP_OP_GE: return tag_value >= cond_value; + case MAP_OP_GT: return tag_value > cond_value; + case MAP_OP_SELF: LOG_WARN("using float tag as bool"); + default: return false; } } -static bool -str_condition(const char *tag_value, const char *cond_value, enum map_op op) +bool +str_condition(const char* tag_value, const char* cond_value, enum map_op op) { switch (op) { - case MAP_OP_EQ: - return strcmp(tag_value, cond_value) == 0; - case MAP_OP_NE: - return strcmp(tag_value, cond_value) != 0; - case MAP_OP_LE: - return strcmp(tag_value, cond_value) <= 0; - case MAP_OP_LT: - return strcmp(tag_value, cond_value) < 0; - case MAP_OP_GE: - 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: - return false; + case MAP_OP_EQ: return strcmp(tag_value, cond_value) == 0; + case MAP_OP_NE: return strcmp(tag_value, cond_value) != 0; + case MAP_OP_LE: return strcmp(tag_value, cond_value) <= 0; + case MAP_OP_LT: return strcmp(tag_value, cond_value) < 0; + case MAP_OP_GE: return strcmp(tag_value, cond_value) >= 0; + case MAP_OP_GT: return strcmp(tag_value, cond_value) > 0; + case MAP_OP_SELF: LOG_WARN("using String tag as bool"); + default: return false; } } -static bool -eval_comparison(const struct map_condition *map_cond, const struct tag_set *tags) +bool +eval_comparison(const struct map_condition* map_cond, const struct tag_set *tags) { const struct tag *tag = tag_for_name(tags, map_cond->tag); if (tag == NULL) { @@ -189,54 +108,48 @@ eval_comparison(const struct map_condition *map_cond, const struct tag_set *tags return false; } case TAG_TYPE_STRING: { - const char *tag_value = tag->as_string(tag); + const char* tag_value = tag->as_string(tag); return str_condition(tag_value, map_cond->value, map_cond->op); } } return false; } -static bool -eval_map_condition(const struct map_condition *map_cond, const struct tag_set *tags) +bool +eval_map_condition(const struct map_condition* map_cond, const struct tag_set *tags) { - switch (map_cond->op) { - case MAP_OP_NOT: - return !eval_map_condition(map_cond->cond1, tags); - - case MAP_OP_AND: - return eval_map_condition(map_cond->cond1, tags) && eval_map_condition(map_cond->cond2, tags); - - case MAP_OP_OR: - return eval_map_condition(map_cond->cond1, tags) || eval_map_condition(map_cond->cond2, tags); - - default: - return eval_comparison(map_cond, tags); + switch(map_cond->op) + { + case MAP_OP_NOT: return !eval_map_condition(map_cond->cond1, tags); + case MAP_OP_AND: return eval_map_condition(map_cond->cond1, tags) && eval_map_condition(map_cond->cond2, tags); + case MAP_OP_OR: return eval_map_condition(map_cond->cond1, tags) || eval_map_condition(map_cond->cond2, tags); + default: return eval_comparison(map_cond, tags); } } void -free_map_condition(struct map_condition *c) +free_map_condition(struct map_condition* c) { - switch (c->op) { - case MAP_OP_EQ: - case MAP_OP_NE: - case MAP_OP_LE: - case MAP_OP_LT: - case MAP_OP_GE: - case MAP_OP_LIKE: - case MAP_OP_GT: - free(c->value); - /* FALLTHROUGH */ - case MAP_OP_SELF: - free(c->tag); - break; - case MAP_OP_AND: - case MAP_OP_OR: - free_map_condition(c->cond2); - /* FALLTHROUGH */ - case MAP_OP_NOT: - free_map_condition(c->cond1); - break; + switch (c->op) + { + case MAP_OP_EQ: + case MAP_OP_NE: + case MAP_OP_LE: + case MAP_OP_LT: + case MAP_OP_GE: + case MAP_OP_GT: + free(c->value); + /* FALLTHROUGH */ + case MAP_OP_SELF: + free(c->tag); + break; + case MAP_OP_AND: + case MAP_OP_OR: + free_map_condition(c->cond2); + /* FALLTHROUGH */ + case MAP_OP_NOT: + free_map_condition(c->cond1); + break; } free(c); } @@ -246,8 +159,7 @@ struct particle_map { struct particle *particle; }; -struct private -{ +struct private { struct particle *default_particle; struct particle_map *map; size_t count; @@ -288,16 +200,21 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int struct eprivate *e = exposable->private; exposable_render_deco(exposable, pix, x, y, height); - e->exposable->expose(e->exposable, pix, x + exposable->particle->left_margin, y, height); + e->exposable->expose( + e->exposable, pix, x + exposable->particle->left_margin, y, height); } static void -on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) +on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y) { const struct particle *p = exposable->particle; const struct eprivate *e = exposable->private; - if ((event == ON_MOUSE_MOTION && exposable->particle->have_on_click_template) || exposable->on_click[btn] != NULL) { + if ((event == ON_MOUSE_MOTION && + exposable->particle->have_on_click_template) || + exposable->on_click[btn] != NULL) + { /* We have our own handler */ exposable_default_on_mouse(exposable, bar, event, btn, x, y); return; @@ -370,8 +287,8 @@ particle_destroy(struct particle *particle) } static struct particle * -map_new(struct particle *common, const struct particle_map particle_map[], size_t count, - struct particle *default_particle) +map_new(struct particle *common, const struct particle_map particle_map[], + size_t count, struct particle *default_particle) { struct private *priv = calloc(1, sizeof(*priv)); priv->default_particle = default_particle; @@ -389,16 +306,22 @@ map_new(struct particle *common, const struct particle_map particle_map[], size_ return common; } + static bool verify_map_conditions(keychain_t *chain, const struct yml_node *node) { if (!yml_is_dict(node)) { - LOG_ERR("%s: must be a dictionary of workspace-name: particle mappings", conf_err_prefix(chain, node)); + LOG_ERR( + "%s: must be a dictionary of workspace-name: particle mappings", + conf_err_prefix(chain, node)); return false; } bool result = true; - for (struct yml_dict_iter it = yml_dict_iter(node); it.key != NULL; yml_dict_next(&it)) { + for (struct yml_dict_iter it = yml_dict_iter(node); + it.key != NULL; + yml_dict_next(&it)) + { const char *key = yml_value_as_string(it.key); if (key == NULL) { LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key)); @@ -432,11 +355,17 @@ from_conf(const struct yml_node *node, struct particle *common) struct particle_map particle_map[yml_dict_length(conditions)]; - struct conf_inherit inherited - = {.font = common->font, .font_shaping = common->font_shaping, .foreground = common->foreground}; + struct conf_inherit inherited = { + .font = common->font, + .font_shaping = common->font_shaping, + .foreground = common->foreground + }; size_t idx = 0; - for (struct yml_dict_iter it = yml_dict_iter(conditions); it.key != NULL; yml_dict_next(&it), idx++) { + for (struct yml_dict_iter it = yml_dict_iter(conditions); + it.key != NULL; + yml_dict_next(&it), idx++) + { /* Note we can skip the error checking here */ char *key_clone = strdup(yml_value_as_string(it.key)); YY_BUFFER_STATE buffer = yy_scan_string(key_clone); @@ -447,7 +376,8 @@ from_conf(const struct yml_node *node, struct particle *common) particle_map[idx].particle = conf_to_particle(it.value, inherited); } - struct particle *default_particle = def != NULL ? conf_to_particle(def, inherited) : NULL; + struct particle *default_particle = def != NULL + ? conf_to_particle(def, inherited) : NULL; return map_new(common, particle_map, yml_dict_length(conditions), default_particle); } diff --git a/particles/map.h b/particles/map.h index 1256744..a6d35b4 100644 --- a/particles/map.h +++ b/particles/map.h @@ -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, @@ -29,7 +28,7 @@ struct map_condition { void free_map_condition(struct map_condition *c); -typedef struct yy_buffer_state *YY_BUFFER_STATE; +typedef struct yy_buffer_state* YY_BUFFER_STATE; YY_BUFFER_STATE yy_scan_string(const char *str); int yyparse(); void yy_delete_buffer(YY_BUFFER_STATE buffer); diff --git a/particles/map.l b/particles/map.l index 034353c..7a5ebc8 100644 --- a/particles/map.l +++ b/particles/map.l @@ -2,74 +2,19 @@ #include #include "map.h" #include "map.tab.h" -void yyerror(const char *s); %} %option warn nodefault nounput noinput noyywrap - char *quoted = NULL; - size_t quote_len = 0; - -%x QUOTE - %% - [[:alnum:]_-]+ yylval.str = strdup(yytext); return WORD; - -\" { - BEGIN(QUOTE); - quoted = calloc(1, sizeof(quoted[0])); -} - -[^\\\"]* { - /* printf("CAT: %s\n", yytext); */ - const size_t yy_length = strlen(yytext); - quoted = realloc(quoted, quote_len + yy_length + 1); - strcat(quoted, yytext); - quote_len += yy_length; -} - -\\\" { - /* printf("escaped quote\n"); */ - quoted = realloc(quoted, quote_len + 1 + 1); - strcat(quoted, "\""); - quote_len++; -} - -\\. { - /* printf("CAT: %s\n", yytext); */ - const size_t yy_length = strlen(yytext); - quoted = realloc(quoted, quote_len + yy_length + 1); - strcat(quoted, yytext); - quote_len += yy_length; -} - -\\ { - /* quoted string that ends with a backslash: "string\ */ - quoted = realloc(quoted, quote_len + 1 + 1); - strcat(quoted, "\\"); - quote_len++; -} - -\" { - /* printf("QUOTED=%s\n", quoted); */ - yylval.str = strdup(quoted); - - free(quoted); - quoted = NULL; - quote_len = 0; - - BEGIN(INITIAL); - return STRING; -} - +\".*\" yylval.str = strndup(yytext + 1, strlen(yytext) - 2); return STRING; == yylval.op = MAP_OP_EQ; return CMP_OP; != yylval.op = MAP_OP_NE; return CMP_OP; \<= yylval.op = MAP_OP_LE; return CMP_OP; \< 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; diff --git a/particles/map.y b/particles/map.y index 8f3f46b..ee426da 100644 --- a/particles/map.y +++ b/particles/map.y @@ -35,27 +35,27 @@ result: condition { MAP_CONDITION_PARSE_RESULT = $1; }; condition: WORD { $$ = malloc(sizeof(struct map_condition)); - $$->tag = $1; + $$->tag = $1; $$->op = MAP_OP_SELF; } | WORD CMP_OP WORD { $$ = malloc(sizeof(struct map_condition)); - $$->tag = $1; + $$->tag = $1; $$->op = $2; - $$->value = $3; + $$->value = $3; } | WORD CMP_OP STRING { $$ = malloc(sizeof(struct map_condition)); - $$->tag = $1; + $$->tag = $1; $$->op = $2; - $$->value = $3; + $$->value = $3; } | L_PAR condition R_PAR { $$ = $2; } | - NOT condition { + NOT condition { $$ = malloc(sizeof(struct map_condition)); $$->cond1 = $2; $$->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 ")"; diff --git a/particles/progress-bar.c b/particles/progress-bar.c index f0bacbf..f9e3999 100644 --- a/particles/progress-bar.c +++ b/particles/progress-bar.c @@ -1,17 +1,16 @@ -#include #include #include +#include #define LOG_MODULE "progress_bar" #define LOG_ENABLE_DBG 0 -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../config.h" +#include "../config-verify.h" #include "../particle.h" #include "../plugin.h" -struct private -{ +struct private { char *tag; int width; @@ -75,7 +74,8 @@ begin_expose(struct exposable *exposable) /* Margins */ if (have_at_least_one) { - exposable->width += exposable->particle->left_margin + exposable->particle->right_margin; + exposable->width += exposable->particle->left_margin + + exposable->particle->right_margin; } else assert(exposable->width == 0); @@ -97,7 +97,8 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int } static void -on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) +on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y) { const struct particle *p = exposable->particle; const struct eprivate *e = exposable->private; @@ -160,14 +161,18 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, e original[i] = exposable->on_click[i]; if (event == ON_MOUSE_CLICK) { - long where = clickable_width > 0 ? 100 * (x - x_offset) / clickable_width : 0; + long where = clickable_width > 0 + ? 100 * (x - x_offset) / clickable_width + : 0; struct tag_set tags = { .tags = (struct tag *[]){tag_new_int(NULL, "where", where)}, .count = 1, }; - tags_expand_templates(exposable->on_click, (const char **)exposable->on_click, MOUSE_BTN_COUNT, &tags); + tags_expand_templates( + exposable->on_click, (const char **)exposable->on_click, + MOUSE_BTN_COUNT, &tags); tag_set_destroy(&tags); } @@ -193,17 +198,19 @@ instantiate(const struct particle *particle, const struct tag_set *tags) long min = tag != NULL ? tag->min(tag) : 0; long max = tag != NULL ? tag->max(tag) : 0; - LOG_DBG("%s: value=%ld, min=%ld, max=%ld", tag != NULL ? tag->name(tag) : "", value, min, max); + LOG_DBG("%s: value=%ld, min=%ld, max=%ld", + tag != NULL ? tag->name(tag) : "", value, min, max); long fill_count = max == min ? 0 : p->width * value / (max - min); long empty_count = p->width - fill_count; struct eprivate *epriv = calloc(1, sizeof(*epriv)); - epriv->count = (1 + /* Start marker */ - fill_count + /* Before current position */ - 1 + /* Current position indicator */ - empty_count + /* After current position */ - 1); /* End marker */ + epriv->count = ( + 1 + /* Start marker */ + fill_count + /* Before current position */ + 1 + /* Current position indicator */ + empty_count + /* After current position */ + 1); /* End marker */ epriv->exposables = malloc(epriv->count * sizeof(epriv->exposables[0])); @@ -252,7 +259,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags) LOG_DBG("tag: %s, value: %ld, " "units-per-segment: %f, units-filled: %f, units-til-next: %f", - tag->name(tag), value, units_per_segment, units_filled, units_til_next_segment); + tag->name(tag), value, + units_per_segment, units_filled, units_til_next_segment); #endif @@ -263,8 +271,10 @@ instantiate(const struct particle *particle, const struct tag_set *tags) } static struct particle * -progress_bar_new(struct particle *common, const char *tag, int width, struct particle *start_marker, - struct particle *end_marker, struct particle *fill, struct particle *empty, struct particle *indicator) +progress_bar_new(struct particle *common, const char *tag, int width, + struct particle *start_marker, struct particle *end_marker, + struct particle *fill, struct particle *empty, + struct particle *indicator) { struct private *priv = calloc(1, sizeof(*priv)); priv->tag = strdup(tag); @@ -298,10 +308,15 @@ from_conf(const struct yml_node *node, struct particle *common) .foreground = common->foreground, }; - return progress_bar_new(common, yml_value_as_string(tag), yml_value_as_int(length), - conf_to_particle(start, inherited), conf_to_particle(end, inherited), - conf_to_particle(fill, inherited), conf_to_particle(empty, inherited), - conf_to_particle(indicator, inherited)); + return progress_bar_new( + common, + yml_value_as_string(tag), + yml_value_as_int(length), + conf_to_particle(start, inherited), + conf_to_particle(end, inherited), + conf_to_particle(fill, inherited), + conf_to_particle(empty, inherited), + conf_to_particle(indicator, inherited)); } static bool diff --git a/particles/ramp.c b/particles/ramp.c index befe1d9..0127519 100644 --- a/particles/ramp.c +++ b/particles/ramp.c @@ -1,19 +1,18 @@ -#include #include #include +#include #include #define LOG_MODULE "ramp" #define LOG_ENABLE_DBG 0 -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../config.h" +#include "../config-verify.h" #include "../particle.h" #include "../plugin.h" -struct private -{ +struct private { char *tag; bool use_custom_min; long min; @@ -58,16 +57,21 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int struct eprivate *e = exposable->private; exposable_render_deco(exposable, pix, x, y, height); - e->exposable->expose(e->exposable, pix, x + exposable->particle->left_margin, y, height); + e->exposable->expose( + e->exposable, pix, x + exposable->particle->left_margin, y, height); } static void -on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) +on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, + enum mouse_button btn, int x, int y) { const struct particle *p = exposable->particle; const struct eprivate *e = exposable->private; - if ((event == ON_MOUSE_MOTION && exposable->particle->have_on_click_template) || exposable->on_click[btn] != NULL) { + if ((event == ON_MOUSE_MOTION && + exposable->particle->have_on_click_template) || + exposable->on_click[btn] != NULL) + { /* We have our own handler */ exposable_default_on_mouse(exposable, bar, event, btn, x, y); return; @@ -114,22 +118,22 @@ instantiate(const struct particle *particle, const struct tag_set *tags) max = p->use_custom_max ? p->max : max; if (min > max) { - LOG_WARN("tag's minimum value is greater than its maximum: " - "tag=\"%s\", min=%ld, max=%ld", - p->tag, min, max); + LOG_WARN( + "tag's minimum value is greater than its maximum: " + "tag=\"%s\", min=%ld, max=%ld", p->tag, min, max); min = max; } if (value < min) { - LOG_WARN("tag's value is less than its minimum value: " - "tag=\"%s\", min=%ld, value=%ld", - p->tag, min, value); + LOG_WARN( + "tag's value is less than its minimum value: " + "tag=\"%s\", min=%ld, value=%ld", p->tag, min, value); value = min; } if (value > max) { - LOG_WARN("tag's value is greater than its maximum value: " - "tag=\"%s\", max=%ld, value=%ld", - p->tag, max, value); + LOG_WARN( + "tag's value is greater than its maximum value: " + "tag=\"%s\", max=%ld, value=%ld", p->tag, max, value); value = max; } @@ -164,8 +168,10 @@ instantiate(const struct particle *particle, const struct tag_set *tags) } static struct particle * -ramp_new(struct particle *common, const char *tag, struct particle *particles[], size_t count, bool use_custom_min, - long min, bool use_custom_max, long max) +ramp_new(struct particle *common, const char *tag, + struct particle *particles[], size_t count, + bool use_custom_min, long min, + bool use_custom_max, long max) { struct private *priv = calloc(1, sizeof(*priv)); @@ -198,15 +204,19 @@ from_conf(const struct yml_node *node, struct particle *common) struct particle *parts[count]; size_t idx = 0; - for (struct yml_list_iter it = yml_list_iter(items); it.node != NULL; yml_list_next(&it), idx++) { - parts[idx] - = conf_to_particle(it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground}); + for (struct yml_list_iter it = yml_list_iter(items); + it.node != NULL; + yml_list_next(&it), idx++) + { + parts[idx] = conf_to_particle( + it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground}); } long min_v = min != NULL ? yml_value_as_int(min) : 0; long max_v = max != NULL ? yml_value_as_int(max) : 0; - return ramp_new(common, yml_value_as_string(tag), parts, count, min != NULL, min_v, max != NULL, max_v); + return ramp_new(common, yml_value_as_string(tag), parts, count, min != NULL, + min_v, max != NULL, max_v); } static bool diff --git a/particles/string.c b/particles/string.c index 4922d7d..e679600 100644 --- a/particles/string.c +++ b/particles/string.c @@ -1,13 +1,13 @@ -#include #include #include +#include #define LOG_MODULE "string" #define LOG_ENABLE_DBG 0 -#include "../char32.h" -#include "../config-verify.h" -#include "../config.h" #include "../log.h" +#include "../char32.h" +#include "../config.h" +#include "../config-verify.h" #include "../particle.h" #include "../plugin.h" @@ -18,8 +18,7 @@ struct text_run_cache { bool in_use; }; -struct private -{ +struct private { char *text; size_t max_len; @@ -52,7 +51,9 @@ begin_expose(struct exposable *exposable) struct eprivate *e = exposable->private; struct private *p = exposable->particle->private; - exposable->width = exposable->particle->left_margin + exposable->particle->right_margin; + exposable->width = + exposable->particle->left_margin + + exposable->particle->right_margin; if (e->cache_idx >= 0) { exposable->width += p->cache[e->cache_idx].width; @@ -93,11 +94,12 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int * * Finally, if the font's descent is negative, ignore it (except * for the height calculation). This is unfortunately not based on - * any real facts, but works very well with e.g. the "Awesome 6" + * any real facts, but works very well with e.g. the "Awesome 5" * font family. */ - const double baseline - = (double)y + (double)(height + font->ascent + font->descent) / 2.0 - (font->descent > 0 ? font->descent : 0); + const double baseline = (double)y + + (double)(height + font->ascent + font->descent) / 2.0 - + (font->descent > 0 ? font->descent : 0); x += exposable->particle->left_margin; @@ -110,13 +112,17 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) { /* Glyph surface is a pre-rendered image (typically a color emoji...) */ - pixman_image_composite32(PIXMAN_OP_OVER, glyph->pix, NULL, pix, 0, 0, 0, 0, x + glyph->x, - baseline - glyph->y, glyph->width, glyph->height); + pixman_image_composite32( + PIXMAN_OP_OVER, glyph->pix, NULL, pix, 0, 0, 0, 0, + x + glyph->x, baseline - glyph->y, + glyph->width, glyph->height); } else { /* Glyph surface is an alpha mask */ pixman_image_t *src = pixman_image_create_solid_fill(&exposable->particle->foreground); - pixman_image_composite32(PIXMAN_OP_OVER, src, glyph->pix, pix, 0, 0, 0, 0, x + glyph->x, - baseline - glyph->y, glyph->width, glyph->height); + pixman_image_composite32( + PIXMAN_OP_OVER, src, glyph->pix, pix, 0, 0, 0, 0, + x + glyph->x, baseline - glyph->y, + glyph->width, glyph->height); pixman_image_unref(src); } @@ -174,16 +180,29 @@ instantiate(const struct particle *particle, const struct tag_set *tags) /* Truncate, if necessary */ if (p->max_len > 0 && chars > p->max_len) { - chars = p->max_len; - if (p->max_len > 3) - wtext[p->max_len - 1] = U'…'; - wtext[p->max_len] = U'\0'; + size_t end = p->max_len; + if (end >= 1) { + /* "allocate" room for three dots at the end */ + end -= 1; + } + + if (p->max_len > 1) { + wtext[end] = U'…'; + wtext[end + 1] = U'\0'; + chars = end + 1; + } else { + wtext[end] = U'\0'; + chars = 0; + } } e->kern_x = calloc(chars, sizeof(e->kern_x[0])); - if (particle->font_shaping == FONT_SHAPE_FULL && fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) { - struct fcft_text_run *run = fcft_rasterize_text_run_utf32(font, chars, wtext, FCFT_SUBPIXEL_NONE); + if (particle->font_shaping == FONT_SHAPE_FULL && + fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) + { + struct fcft_text_run *run = fcft_rasterize_text_run_utf32( + font, chars, wtext, FCFT_SUBPIXEL_NONE); if (run != NULL) { int w = 0; @@ -201,7 +220,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags) if (cache_idx < 0) { size_t new_size = p->cache_size + 1; - struct text_run_cache *new_cache = realloc(p->cache, new_size * sizeof(new_cache[0])); + struct text_run_cache *new_cache = realloc( + p->cache, new_size * sizeof(new_cache[0])); p->cache_size = new_size; p->cache = new_cache; @@ -225,7 +245,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags) /* Convert text to glyph masks/images. */ for (size_t i = 0; i < chars; i++) { - const struct fcft_glyph *glyph = fcft_rasterize_char_utf32(font, wtext[i], FCFT_SUBPIXEL_NONE); + const struct fcft_glyph *glyph = fcft_rasterize_char_utf32( + font, wtext[i], FCFT_SUBPIXEL_NONE); if (glyph == NULL) continue; @@ -286,7 +307,10 @@ from_conf(const struct yml_node *node, struct particle *common) const struct yml_node *text = yml_get_value(node, "text"); const struct yml_node *max = yml_get_value(node, "max"); - return string_new(common, yml_value_as_string(text), max != NULL ? yml_value_as_int(max) : 0); + return string_new( + common, + yml_value_as_string(text), + max != NULL ? yml_value_as_int(max) : 0); } static bool diff --git a/plugin.c b/plugin.c index 2ed0a4f..ed7f63c 100644 --- a/plugin.c +++ b/plugin.c @@ -1,103 +1,99 @@ #include "plugin.h" -#include #include +#include #include #define LOG_MODULE "plugin" #define LOG_ENABLE_DBG 0 -#include "config.h" #include "log.h" +#include "config.h" #if !defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) -#define EXTERN_MODULE(plug_name) \ - extern const struct module_iface module_##plug_name##_iface; \ - extern bool plug_name##_verify_conf(keychain_t *chain, const struct yml_node *node); \ - extern struct module *plug_name##_from_conf(const struct yml_node *node, struct conf_inherit inherited); +#define EXTERN_MODULE(plug_name) \ + extern const struct module_iface module_##plug_name##_iface; \ + extern bool plug_name##_verify_conf( \ + keychain_t *chain, const struct yml_node *node); \ + extern struct module *plug_name##_from_conf( \ + const struct yml_node *node, struct conf_inherit inherited); -#define EXTERN_PARTICLE(plug_name) \ - extern const struct particle_iface particle_##plug_name##_iface; \ - extern bool plug_name##_verify_conf(keychain_t *chain, const struct yml_node *node); \ - extern struct particle *plug_name##_from_conf(const struct yml_node *node, struct particle *common); +#define EXTERN_PARTICLE(plug_name) \ + extern const struct particle_iface particle_##plug_name##_iface; \ + extern bool plug_name##_verify_conf( \ + keychain_t *chain, const struct yml_node *node); \ + extern struct particle *plug_name##_from_conf( \ + const struct yml_node *node, struct particle *common); -#define EXTERN_DECORATION(plug_name) \ - extern const struct deco_iface deco_##plug_name##_iface; \ - extern bool plug_name##_verify_conf(keychain_t *chain, const struct yml_node *node); \ +#define EXTERN_DECORATION(plug_name) \ + extern const struct deco_iface deco_##plug_name##_iface; \ + extern bool plug_name##_verify_conf( \ + keychain_t *chain, const struct yml_node *node); \ extern struct deco *plug_name##_from_conf(const struct yml_node *node); #if defined(HAVE_PLUGIN_alsa) -EXTERN_MODULE(alsa); + EXTERN_MODULE(alsa); #endif #if defined(HAVE_PLUGIN_backlight) -EXTERN_MODULE(backlight); + EXTERN_MODULE(backlight); #endif #if defined(HAVE_PLUGIN_battery) -EXTERN_MODULE(battery); + EXTERN_MODULE(battery); #endif #if defined(HAVE_PLUGIN_clock) -EXTERN_MODULE(clock); + EXTERN_MODULE(clock); #endif #if defined(HAVE_PLUGIN_cpu) -EXTERN_MODULE(cpu); + EXTERN_MODULE(cpu); #endif #if defined(HAVE_PLUGIN_disk_io) -EXTERN_MODULE(disk_io); + EXTERN_MODULE(disk_io); #endif #if defined(HAVE_PLUGIN_dwl) -EXTERN_MODULE(dwl); + EXTERN_MODULE(dwl); #endif #if defined(HAVE_PLUGIN_foreign_toplevel) -EXTERN_MODULE(foreign_toplevel); + EXTERN_MODULE(foreign_toplevel); #endif #if defined(HAVE_PLUGIN_mem) -EXTERN_MODULE(mem); + EXTERN_MODULE(mem); #endif #if defined(HAVE_PLUGIN_mpd) -EXTERN_MODULE(mpd); -#endif -#if defined(HAVE_PLUGIN_mpris) -EXTERN_MODULE(mpris); + EXTERN_MODULE(mpd); #endif #if defined(HAVE_PLUGIN_i3) -EXTERN_MODULE(i3); + EXTERN_MODULE(i3); #endif #if defined(HAVE_PLUGIN_label) -EXTERN_MODULE(label); + EXTERN_MODULE(label); #endif #if defined(HAVE_PLUGIN_network) -EXTERN_MODULE(network); + EXTERN_MODULE(network); #endif #if defined(HAVE_PLUGIN_pipewire) -EXTERN_MODULE(pipewire); + EXTERN_MODULE(pipewire); #endif #if defined(HAVE_PLUGIN_pulse) -EXTERN_MODULE(pulse); + EXTERN_MODULE(pulse); #endif #if defined(HAVE_PLUGIN_removables) -EXTERN_MODULE(removables); + EXTERN_MODULE(removables); #endif #if defined(HAVE_PLUGIN_river) -EXTERN_MODULE(river); + EXTERN_MODULE(river); #endif #if defined(HAVE_PLUGIN_script) -EXTERN_MODULE(script); + EXTERN_MODULE(script); #endif #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); + EXTERN_MODULE(sway_xkb); #endif #if defined(HAVE_PLUGIN_xkb) -EXTERN_MODULE(xkb); + EXTERN_MODULE(xkb); #endif #if defined(HAVE_PLUGIN_xwindow) -EXTERN_MODULE(xwindow); + EXTERN_MODULE(xwindow); #endif EXTERN_PARTICLE(empty); @@ -125,45 +121,41 @@ static const char * type2str(enum plugin_type type) { switch (type) { - case PLUGIN_MODULE: - return "module"; - case PLUGIN_PARTICLE: - return "particle"; - case PLUGIN_DECORATION: - return "decoration"; + case PLUGIN_MODULE: return "module"; + case PLUGIN_PARTICLE: return "particle"; + case PLUGIN_DECORATION: return "decoration"; } - assert(false && "invalid type"); - return ""; + return NULL; } -static void __attribute__((constructor)) init(void) +static void __attribute__((constructor)) +init(void) { #if !defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) -#define REGISTER_CORE_PLUGIN(plug_name, func_prefix, plug_type) \ - do { \ - tll_push_back(plugins, ((struct plugin){ \ - .name = strdup(#plug_name), \ - .type = (plug_type), \ - .lib = RTLD_DEFAULT, \ - })); \ +#define REGISTER_CORE_PLUGIN(plug_name, func_prefix, plug_type) \ + do { \ + tll_push_back( \ + plugins, \ + ((struct plugin){ \ + .name = strdup(#plug_name), \ + .type = (plug_type), \ + .lib = RTLD_DEFAULT, \ + })); \ } while (0) -#define REGISTER_CORE_MODULE(plug_name, func_prefix) \ - do { \ - REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_MODULE); \ - tll_back(plugins).module = &module_##func_prefix##_iface; \ +#define REGISTER_CORE_MODULE(plug_name, func_prefix) do { \ + REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_MODULE); \ + tll_back(plugins).module = &module_##func_prefix##_iface; \ } while (0) -#define REGISTER_CORE_PARTICLE(plug_name, func_prefix) \ - do { \ - REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_PARTICLE); \ - tll_back(plugins).particle = &particle_##func_prefix##_iface; \ +#define REGISTER_CORE_PARTICLE(plug_name, func_prefix) do { \ + REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_PARTICLE); \ + tll_back(plugins).particle = &particle_##func_prefix##_iface; \ } while (0) -#define REGISTER_CORE_DECORATION(plug_name, func_prefix) \ - do { \ - REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_DECORATION); \ - tll_back(plugins).decoration = &deco_##func_prefix##_iface; \ +#define REGISTER_CORE_DECORATION(plug_name, func_prefix) do { \ + REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_DECORATION); \ + tll_back(plugins).decoration = &deco_##func_prefix##_iface; \ } while (0) #if defined(HAVE_PLUGIN_alsa) @@ -196,9 +188,6 @@ static void __attribute__((constructor)) init(void) #if defined(HAVE_PLUGIN_mpd) REGISTER_CORE_MODULE(mpd, mpd); #endif -#if defined(HAVE_PLUGIN_mpris) - REGISTER_CORE_MODULE(mpris, mpris); -#endif #if defined(HAVE_PLUGIN_i3) REGISTER_CORE_MODULE(i3, i3); #endif @@ -226,12 +215,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 @@ -274,13 +257,16 @@ free_plugin(struct plugin plug) free(plug.name); } -static void __attribute__((destructor)) fini(void) { tll_free_and_free(plugins, free_plugin); } +static void __attribute__((destructor)) +fini(void) +{ + tll_free_and_free(plugins, free_plugin); +} const struct plugin * plugin_load(const char *name, enum plugin_type type) { - tll_foreach(plugins, plug) - { + tll_foreach(plugins, plug) { if (plug->item.type == type && strcmp(plug->item.name, name) == 0) { LOG_DBG("%s: %s already loaded: %p", type2str(type), name, plug->item.lib); assert(plug->item.dummy != NULL); @@ -288,6 +274,7 @@ plugin_load(const char *name, enum plugin_type type) } } + char path[128]; snprintf(path, sizeof(path), "%s_%s.so", type2str(type), name); diff --git a/plugin.h b/plugin.h index 4c49caa..1b2da24 100644 --- a/plugin.h +++ b/plugin.h @@ -1,7 +1,7 @@ #pragma once -#include "config-verify.h" #include "config.h" +#include "config-verify.h" #include "module.h" #include "particle.h" @@ -9,12 +9,14 @@ typedef bool (*verify_func_t)(keychain_t *chain, const struct yml_node *node); struct module_iface { verify_func_t verify_conf; - struct module *(*from_conf)(const struct yml_node *node, struct conf_inherit inherited); + struct module *(*from_conf)( + const struct yml_node *node, struct conf_inherit inherited); }; struct particle_iface { verify_func_t verify_conf; - struct particle *(*from_conf)(const struct yml_node *node, struct particle *common); + struct particle *(*from_conf)( + const struct yml_node *node, struct particle *common); }; struct deco_iface { diff --git a/tag.c b/tag.c index d6609af..4e72c2e 100644 --- a/tag.c +++ b/tag.c @@ -1,20 +1,18 @@ #include "tag.h" -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include #define LOG_MODULE "tag" #define LOG_ENABLE_DBG 1 #include "log.h" #include "module.h" -struct private -{ +struct private { char *name; union { struct { @@ -157,8 +155,8 @@ int_refresh_in(const struct tag *tag, long units) if (tag->owner == NULL || tag->owner->refresh_in == NULL) return false; - assert(priv->value_as_int.realtime_unit == TAG_REALTIME_SECS - || priv->value_as_int.realtime_unit == TAG_REALTIME_MSECS); + assert(priv->value_as_int.realtime_unit == TAG_REALTIME_SECS || + priv->value_as_int.realtime_unit == TAG_REALTIME_MSECS); long milli_seconds = units; if (priv->value_as_int.realtime_unit == TAG_REALTIME_SECS) @@ -270,14 +268,15 @@ tag_new_int(struct module *owner, const char *name, long value) } struct tag * -tag_new_int_range(struct module *owner, const char *name, long value, long min, long max) +tag_new_int_range(struct module *owner, const char *name, long value, + long min, long max) { return tag_new_int_realtime(owner, name, value, min, max, TAG_REALTIME_NONE); } struct tag * -tag_new_int_realtime(struct module *owner, const char *name, long value, long min, long max, - enum tag_realtime_unit unit) +tag_new_int_realtime(struct module *owner, const char *name, long value, + long min, long max, enum tag_realtime_unit unit) { struct private *priv = malloc(sizeof(*priv)); priv->name = strdup(name); @@ -414,7 +413,7 @@ sbuf_append_at_most(struct sbuf *s1, const char *s2, size_t n) s1->size = 2 * required_size; s1->s = realloc(s1->s, s1->size); - // s1->s[s1->len] = '\0'; + //s1->s[s1->len] = '\0'; } memcpy(&s1->s[s1->len], s2, n); @@ -428,18 +427,13 @@ sbuf_append(struct sbuf *s1, const char *s2) sbuf_append_at_most(s1, s2, strlen(s2)); } -// stores the number in "*value" on success -static bool -is_number(const char *str, long *value) -{ - errno = 0; - - char *end; - long v = strtol(str, &end, 10); - if (errno != 0 || *end != '\0') - return false; - - *value = v; +bool +is_number(const char *str) { + while (*str != '\0') { + if (!isdigit(*str)) + return false; + ++str; + } return true; } @@ -510,23 +504,23 @@ tags_expand_template(const char *template, const struct tag_set *tags) FMT_HEX, FMT_OCT, FMT_PERCENT, - FMT_DIVIDE, - } format - = FMT_DEFAULT; + FMT_KBYTE, + FMT_MBYTE, + FMT_GBYTE, + FMT_KIBYTE, + FMT_MIBYTE, + FMT_GIBYTE, + } format = FMT_DEFAULT; enum { VALUE_VALUE, VALUE_MIN, VALUE_MAX, VALUE_UNIT, - } kind - = VALUE_VALUE; + } kind = VALUE_VALUE; - long digits = 0; - long decimals = 2; - long divider = 1; - bool zero_pad = false; - char *point = NULL; + int decimals = 2; + char *float_fmt_end; for (size_t i = 0; i < MAX_TAG_ARGS; i++) { if (tag_args[i] == NULL) @@ -537,65 +531,27 @@ 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, ÷r) || 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) kind = VALUE_MAX; else if (strcmp(tag_args[i], "unit") == 0) kind = VALUE_UNIT; - else if (is_number(tag_args[i], &digits)) // i.e.: "{tag:3}" - zero_pad = tag_args[i][0] == '0'; - else if ((point = strchr(tag_args[i], '.')) != NULL) { - *point = '\0'; - - const char *digits_str = tag_args[i]; - const char *decimals_str = point + 1; - - if (digits_str[0] != '\0') { // guards against i.e. "{tag:.3}" - if (!is_number(digits_str, &digits)) { - LOG_WARN("tag `%s`: invalid field width formatter. Ignoring...", tag_name); - } - } - - if (decimals_str[0] != '\0') { // guards against i.e. "{tag:3.}" - if (!is_number(decimals_str, &decimals)) { - LOG_WARN("tag `%s`: invalid decimals formatter. Ignoring...", tag_name); - } - } - zero_pad = digits_str[0] == '0'; - } else + else if (tag_args[i][0] == '.' && is_number(tag_args[i] + 1)) + decimals = strtol(tag_args[i] + 1, &float_fmt_end, 10); + else LOG_WARN("invalid tag formatter: %s", tag_args[i]); } @@ -604,36 +560,21 @@ tags_expand_template(const char *template, const struct tag_set *tags) case VALUE_VALUE: switch (format) { case FMT_DEFAULT: { - switch (tag->type(tag)) { - case TAG_TYPE_FLOAT: { - const char *fmt = zero_pad ? "%0*.*f" : "%*.*f"; + if (tag->type(tag) == TAG_TYPE_FLOAT){ char str[24]; - snprintf(str, sizeof(str), fmt, digits, decimals, tag->as_float(tag)); + snprintf(str, sizeof(str), "%.*f", decimals, tag->as_float(tag)); sbuf_append(&formatted, str); - break; - } - - case TAG_TYPE_INT: { - const char *fmt = zero_pad ? "%0*ld" : "%*ld"; - char str[24]; - snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag)); - sbuf_append(&formatted, str); - break; - } - - default: + } else { sbuf_append(&formatted, tag->as_string(tag)); - break; } - break; } case FMT_HEX: case FMT_OCT: { - const char *fmt = format == FMT_HEX ? zero_pad ? "%0*lx" : "%*lx" : zero_pad ? "%0*lo" : "%*lo"; char str[24]; - snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag)); + snprintf(str, sizeof(str), format == FMT_HEX ? "%lx" : "%lo", + tag->as_int(tag)); sbuf_append(&formatted, str); break; } @@ -643,22 +584,32 @@ tags_expand_template(const char *template, const struct tag_set *tags) const long max = tag->max(tag); const long cur = tag->as_int(tag); - const char *fmt = zero_pad ? "%0*lu" : "%*lu"; char str[4]; - snprintf(str, sizeof(str), fmt, digits, (cur - min) * 100 / (max - min)); + snprintf(str, sizeof(str), "%lu", (cur - min) * 100 / (max - min)); sbuf_append(&formatted, str); 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"; - snprintf(str, sizeof(str), fmt, digits, decimals, tag->as_float(tag) / (double)divider); - } else { - const char *fmt = zero_pad ? "%0*lu" : "%*lu"; - snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag) / divider); - } + if (tag->type(tag) == TAG_TYPE_FLOAT) + snprintf(str, sizeof(str), "%.*f", decimals, tag->as_float(tag) / (double)divider); + else + snprintf(str, sizeof(str), "%lu", tag->as_int(tag) / divider); sbuf_append(&formatted, str); break; } @@ -671,33 +622,39 @@ tags_expand_template(const char *template, const struct tag_set *tags) const long max = tag->max(tag); long value = kind == VALUE_MIN ? min : max; - const char *fmt = NULL; + const char *fmt; switch (format) { - case FMT_DEFAULT: - fmt = zero_pad ? "%0*ld" : "%*ld"; - break; - case FMT_HEX: - fmt = zero_pad ? "%0*lx" : "%*lx"; - break; - case FMT_OCT: - fmt = zero_pad ? "%0*lo" : "%*lo"; - break; + case FMT_DEFAULT: fmt = "%ld"; break; + case FMT_HEX: fmt = "%lx"; break; + case FMT_OCT: fmt = "%lo"; break; + case FMT_PERCENT: value = (value - min) * 100 / (max - min); - fmt = zero_pad ? "%0*lu" : "%*lu"; + fmt = "%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"; + fmt = "%lu"; break; } } - assert(fmt != NULL); - char str[24]; - snprintf(str, sizeof(str), fmt, digits, value); + snprintf(str, sizeof(str), fmt, value); sbuf_append(&formatted, str); break; } @@ -706,15 +663,9 @@ tags_expand_template(const char *template, const struct tag_set *tags) const char *value = NULL; switch (tag->realtime(tag)) { - case TAG_REALTIME_NONE: - value = ""; - break; - case TAG_REALTIME_SECS: - value = "s"; - break; - case TAG_REALTIME_MSECS: - value = "ms"; - break; + case TAG_REALTIME_NONE: value = ""; break; + case TAG_REALTIME_SECS: value = "s"; break; + case TAG_REALTIME_MSECS: value = "ms"; break; } sbuf_append(&formatted, value); @@ -730,7 +681,8 @@ tags_expand_template(const char *template, const struct tag_set *tags) } void -tags_expand_templates(char *expanded[], const char *template[], size_t nmemb, const struct tag_set *tags) +tags_expand_templates(char *expanded[], const char *template[], size_t nmemb, + const struct tag_set *tags) { for (size_t i = 0; i < nmemb; i++) expanded[i] = tags_expand_template(template[i], tags); diff --git a/tag.h b/tag.h index 6149b1e..1e9742a 100644 --- a/tag.h +++ b/tag.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include enum tag_type { TAG_TYPE_BOOL, @@ -43,16 +43,21 @@ struct tag_set { }; struct tag *tag_new_int(struct module *owner, const char *name, long value); -struct tag *tag_new_int_range(struct module *owner, const char *name, long value, long min, long max); -struct tag *tag_new_int_realtime(struct module *owner, const char *name, long value, long min, long max, - enum tag_realtime_unit unit); +struct tag *tag_new_int_range( + struct module *owner, const char *name, long value, long min, long max); +struct tag *tag_new_int_realtime( + struct module *owner, const char *name, long value, long min, + long max, enum tag_realtime_unit unit); struct tag *tag_new_bool(struct module *owner, const char *name, bool value); struct tag *tag_new_float(struct module *owner, const char *name, double value); -struct tag *tag_new_string(struct module *owner, const char *name, const char *value); +struct tag *tag_new_string( + struct module *owner, const char *name, const char *value); const struct tag *tag_for_name(const struct tag_set *set, const char *name); void tag_set_destroy(struct tag_set *set); /* Utility functions */ char *tags_expand_template(const char *template, const struct tag_set *tags); -void tags_expand_templates(char *expanded[], const char *template[], size_t nmemb, const struct tag_set *tags); +void tags_expand_templates( + char *expanded[], const char *template[], size_t nmemb, + const struct tag_set *tags); diff --git a/test/full-conf-good.yml b/test/full-conf-good.yml index a6f6e99..d89d494 100644 --- a/test/full-conf-good.yml +++ b/test/full-conf-good.yml @@ -39,13 +39,8 @@ bar: host: 127.0.0.1 content: {string: {text: "{state}"}} - network: - content: - map: - default: - string: {text: "{name}: {state} ({ipv4})"} - conditions: - ipv4 == "": - string: {text: "{name}: {state}"} + name: ldsjfdf + content: {string: {text: "{name}"}} - removables: content: {string: {text: "{label}"}} # - xkb: diff --git a/test/meson.build b/test/meson.build index a3635a2..e8c7138 100644 --- a/test/meson.build +++ b/test/meson.build @@ -7,9 +7,4 @@ test('no-config', yambar, args: ['-C', '-c', 'xyz'], should_fail: true) test('config-isnt-file', yambar, args: ['-C', '-c', '.'], should_fail: true) test('config-no-bar', yambar, args: ['-C', '-c', join_paths(pwd, 'no-bar.yml')], should_fail: true) -if plugin_alsa_enabled and plugin_backlight_enabled and \ - plugin_battery_enabled and plugin_clock_enabled and \ - plugin_i3_enabled and plugin_mpd_enabled and plugin_network_enabled \ - and plugin_removables_enabled - test('full-conf-good', yambar, args: ['-C', '-c', join_paths(pwd, 'full-conf-good.yml')]) -endif +test('full-conf-good', yambar, args: ['-C', '-c', join_paths(pwd, 'full-conf-good.yml')]) diff --git a/xcb.c b/xcb.c index d3d2e30..a157c1a 100644 --- a/xcb.c +++ b/xcb.c @@ -1,16 +1,16 @@ #include "xcb.h" -#include #include #include #include +#include +#include #include #include -#include #if defined(HAVE_XCB_ERRORS) -#include + #include #endif #define LOG_MODULE "xcb" @@ -36,7 +36,8 @@ xcb_atom_t _NET_WM_NAME; static xcb_errors_context_t *err_context; #endif -static void __attribute__((destructor)) fini(void) +static void __attribute__((destructor)) +fini(void) { #if defined(HAVE_XCB_ERRORS) xcb_errors_context_free(err_context); @@ -62,17 +63,19 @@ xcb_init(void) /* Vendor release number */ unsigned release = setup->release_number; - unsigned major = release / 10000000; - release %= 10000000; - unsigned minor = release / 100000; - release %= 100000; + unsigned major = release / 10000000; release %= 10000000; + unsigned minor = release / 100000; release %= 100000; unsigned patch = release / 1000; #endif - LOG_DBG("%.*s %u.%u.%u (protocol: %u.%u)", xcb_setup_vendor_length(setup), xcb_setup_vendor(setup), major, minor, - patch, setup->protocol_major_version, setup->protocol_minor_version); + LOG_DBG("%.*s %u.%u.%u (protocol: %u.%u)", + xcb_setup_vendor_length(setup), xcb_setup_vendor(setup), + major, minor, patch, + setup->protocol_major_version, + setup->protocol_minor_version); - const xcb_query_extension_reply_t *randr = xcb_get_extension_data(conn, &xcb_randr_id); + const xcb_query_extension_reply_t *randr = + xcb_get_extension_data(conn, &xcb_randr_id); if (randr == NULL || !randr->present) { LOG_ERR("RANDR extension not present"); @@ -80,7 +83,8 @@ xcb_init(void) return false; } - const xcb_query_extension_reply_t *render = xcb_get_extension_data(conn, &xcb_render_id); + const xcb_query_extension_reply_t *render = + xcb_get_extension_data(conn, &xcb_render_id); if (render == NULL || !render->present) { LOG_ERR("RENDER extension not present"); @@ -88,15 +92,18 @@ xcb_init(void) return false; } - xcb_randr_query_version_cookie_t randr_cookie - = xcb_randr_query_version(conn, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION); - xcb_render_query_version_cookie_t render_cookie - = xcb_render_query_version(conn, XCB_RENDER_MAJOR_VERSION, XCB_RENDER_MINOR_VERSION); + xcb_randr_query_version_cookie_t randr_cookie = + xcb_randr_query_version(conn, XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION); + xcb_render_query_version_cookie_t render_cookie = + xcb_render_query_version(conn, XCB_RENDER_MAJOR_VERSION, + XCB_RENDER_MINOR_VERSION); xcb_flush(conn); xcb_generic_error_t *e; - xcb_randr_query_version_reply_t *randr_version = xcb_randr_query_version_reply(conn, randr_cookie, &e); + xcb_randr_query_version_reply_t *randr_version = + xcb_randr_query_version_reply(conn, randr_cookie, &e); if (e != NULL) { LOG_ERR("failed to query RANDR version: %s", xcb_error(e)); free(e); @@ -104,7 +111,8 @@ xcb_init(void) return false; } - xcb_render_query_version_reply_t *render_version = xcb_render_query_version_reply(conn, render_cookie, &e); + xcb_render_query_version_reply_t *render_version = + xcb_render_query_version_reply(conn, render_cookie, &e); if (e != NULL) { LOG_ERR("failed to query RENDER version: %s", xcb_error(e)); free(e); @@ -112,8 +120,10 @@ xcb_init(void) return false; } - LOG_DBG("RANDR: %u.%u", randr_version->major_version, randr_version->minor_version); - LOG_DBG("RENDER: %u.%u", render_version->major_version, render_version->minor_version); + LOG_DBG("RANDR: %u.%u", + randr_version->major_version, randr_version->minor_version); + LOG_DBG("RENDER: %u.%u", + render_version->major_version, render_version->minor_version); free(randr_version); free(render_version); @@ -121,7 +131,7 @@ xcb_init(void) /* Cache atoms */ UTF8_STRING = get_atom(conn, "UTF8_STRING"); _NET_WM_PID = get_atom(conn, "_NET_WM_PID"); - _NET_WM_WINDOW_TYPE = get_atom(conn, "_NET_WM_WINDOW_TYPE"); + _NET_WM_WINDOW_TYPE = get_atom(conn, "_NET_WM_WINDOW_TYPE"); _NET_WM_WINDOW_TYPE_DOCK = get_atom(conn, "_NET_WM_WINDOW_TYPE_DOCK"); _NET_WM_STATE = get_atom(conn, "_NET_WM_STATE"); _NET_WM_STATE_ABOVE = get_atom(conn, "_NET_WM_STATE_ABOVE"); @@ -143,7 +153,10 @@ xcb_atom_t get_atom(xcb_connection_t *conn, const char *name) { xcb_generic_error_t *e; - xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, xcb_intern_atom(conn, 0, strlen(name), name), &e); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply( + conn, + xcb_intern_atom(conn, 0, strlen(name), name), + &e); if (e != NULL) { LOG_ERR("%s: failed to get atom for %s", name, xcb_error(e)); @@ -169,7 +182,8 @@ char * get_atom_name(xcb_connection_t *conn, xcb_atom_t atom) { xcb_generic_error_t *e; - xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(conn, xcb_get_atom_name(conn, atom), &e); + xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply( + conn, xcb_get_atom_name(conn, atom), &e); if (e != NULL) { LOG_ERR("failed to get atom name: %s", xcb_error(e)); @@ -178,7 +192,8 @@ get_atom_name(xcb_connection_t *conn, xcb_atom_t atom) return NULL; } - char *name = strndup(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); + char *name = strndup( + xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); LOG_DBG("atom name: %s", name); @@ -192,17 +207,22 @@ xcb_error(const xcb_generic_error_t *error) static char msg[1024]; #if defined(HAVE_XCB_ERRORS) - const char *major = xcb_errors_get_name_for_major_code(err_context, error->major_code); - const char *minor = xcb_errors_get_name_for_minor_code(err_context, error->major_code, error->minor_code); + const char *major = xcb_errors_get_name_for_major_code( + err_context, error->major_code); + const char *minor = xcb_errors_get_name_for_minor_code( + err_context, error->major_code, error->minor_code); const char *extension; - const char *name = xcb_errors_get_name_for_error(err_context, error->error_code, &extension); + const char *name = xcb_errors_get_name_for_error( + err_context, error->error_code, &extension); - snprintf(msg, sizeof(msg), "major=%s, minor=%s), code=%s, extension=%s, sequence=%u", major, minor, name, extension, - error->sequence); + snprintf(msg, sizeof(msg), + "major=%s, minor=%s), code=%s, extension=%s, sequence=%u", + major, minor, name, extension, error->sequence); #else - snprintf(msg, sizeof(msg), "op %hhu:%hu, code %hhu, sequence %hu", error->major_code, error->minor_code, - error->error_code, error->sequence); + snprintf(msg, sizeof(msg), "op %hhu:%hu, code %hhu, sequence %hu", + error->major_code, error->minor_code, error->error_code, + error->sequence); #endif return msg; diff --git a/yml.c b/yml.c index 4769d38..b3f3d42 100644 --- a/yml.c +++ b/yml.c @@ -1,13 +1,13 @@ #include "yml.h" -#include -#include -#include -#include #include +#include +#include +#include +#include -#include #include +#include #define UNUSED __attribute__((unused)) @@ -78,8 +78,7 @@ clone_node(struct yml_node *parent, const struct yml_node *node) break; case DICT: - tll_foreach(node->dict.pairs, it) - { + tll_foreach(node->dict.pairs, it) { struct dict_pair p = { .key = clone_node(clone, it->item.key), .value = clone_node(clone, it->item.value), @@ -89,7 +88,8 @@ clone_node(struct yml_node *parent, const struct yml_node *node) break; case LIST: - tll_foreach(node->list.values, it) tll_push_back(clone->list.values, clone_node(clone, it->item)); + tll_foreach(node->list.values, it) + tll_push_back(clone->list.values, clone_node(clone, it->item)); break; case ROOT: @@ -119,8 +119,7 @@ dict_has_key(const struct yml_node *node, const struct yml_node *key) { assert(node->type == DICT); - tll_foreach(node->dict.pairs, pair) - { + tll_foreach(node->dict.pairs, pair) { if (node_equal(pair->item.key, key)) return true; } @@ -131,7 +130,7 @@ dict_has_key(const struct yml_node *node, const struct yml_node *key) static enum yml_error add_node(struct yml_node *parent, struct yml_node *new_node, yaml_mark_t loc) { - new_node->line = loc.line + 1; /* yaml uses 0-based line numbers */ + new_node->line = loc.line + 1; /* yaml uses 0-based line numbers */ new_node->column = loc.column; switch (parent->type) { @@ -169,7 +168,8 @@ add_node(struct yml_node *parent, struct yml_node *new_node, yaml_mark_t loc) } static void -add_anchor(struct yml_node *root, const char *anchor, const struct yml_node *node) +add_anchor(struct yml_node *root, const char *anchor, + const struct yml_node *node) { assert(root->type == ROOT); @@ -190,23 +190,25 @@ post_process(struct yml_node *node, char **error) break; case SCALAR: - // assert(strcmp(node->scalar.value, "<<") != 0); + //assert(strcmp(node->scalar.value, "<<") != 0); break; case LIST: - tll_foreach(node->list.values, it) if (!post_process(it->item, error)) return false; + tll_foreach(node->list.values, it) + if (!post_process(it->item, error)) + return false; break; case DICT: - tll_foreach(node->dict.pairs, it) - { - if (!post_process(it->item.key, error) || !post_process(it->item.value, error)) { + tll_foreach(node->dict.pairs, it) { + if (!post_process(it->item.key, error) || + !post_process(it->item.value, error)) + { return false; } } - tll_foreach(node->dict.pairs, it) - { + tll_foreach(node->dict.pairs, it) { if (it->item.key->type != SCALAR) continue; @@ -218,32 +220,29 @@ post_process(struct yml_node *node, char **error) * Merge value is a list (of dictionaries) * e.g. <<: [*foo, *bar] */ - tll_foreach(it->item.value->list.values, v_it) - { + tll_foreach(it->item.value->list.values, v_it) { if (v_it->item->type != DICT) { - int cnt = snprintf(NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", v_it->item->line, - v_it->item->column); + int cnt = snprintf( + NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", + v_it->item->line, v_it->item->column); *error = malloc(cnt + 1); - snprintf(*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", v_it->item->line, - v_it->item->column); + snprintf( + *error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", + v_it->item->line, v_it->item->column); return false; } - tll_foreach(v_it->item->dict.pairs, vv_it) - { + tll_foreach(v_it->item->dict.pairs, vv_it) { struct dict_pair p = { .key = vv_it->item.key, .value = vv_it->item.value, }; + /* TODO: handle this. Is it an error? Or + * should we replace the existing key/value + * pair */ + assert(!dict_has_key(node, vv_it->item.key)); - if (dict_has_key(node, vv_it->item.key)) { - /* Prefer value in target dictionary, over the - * value from the anchor */ - yml_destroy(vv_it->item.key); - yml_destroy(vv_it->item.value); - } else { - tll_push_back(node->dict.pairs, p); - } + tll_push_back(node->dict.pairs, p); } /* Destroy list, but don't free (since its nodes @@ -259,29 +258,27 @@ post_process(struct yml_node *node, char **error) * e.g. <<: *foo */ if (it->item.value->type != DICT) { - int cnt = snprintf(NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", it->item.value->line, - it->item.value->column); + int cnt = snprintf( + NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", + it->item.value->line, it->item.value->column); *error = malloc(cnt + 1); - snprintf(*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", it->item.value->line, - it->item.value->column); + snprintf( + *error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", + it->item.value->line, it->item.value->column); return false; } - tll_foreach(it->item.value->dict.pairs, v_it) - { + tll_foreach(it->item.value->dict.pairs, v_it) { struct dict_pair p = { .key = v_it->item.key, .value = v_it->item.value, }; - if (dict_has_key(node, v_it->item.key)) { - /* Prefer value in target dictionary, over the - * value from the anchor */ - yml_destroy(v_it->item.key); - yml_destroy(v_it->item.value); - } else { - tll_push_back(node->dict.pairs, p); - } + /* TODO: handle this. Is it an error? Or should we + * replace the existing key/value pair */ + assert(!dict_has_key(node, v_it->item.key)); + + tll_push_back(node->dict.pairs, p); } /* Destroy list here, *without* freeing nodes (since @@ -304,7 +301,10 @@ post_process(struct yml_node *node, char **error) } static const char * -format_error(enum yml_error err, const struct yml_node *parent, const struct yml_node *node, const char *anchor) +format_error(enum yml_error err, + const struct yml_node *parent, + const struct yml_node *node, + const char *anchor) { static char err_str[512]; @@ -315,9 +315,11 @@ format_error(enum yml_error err, const struct yml_node *parent, const struct yml case YML_ERR_DUPLICATE_KEY: { /* Find parent's key (i.e its name) */ - if (parent->parent != NULL && parent->parent->type == DICT && node->type == SCALAR) { - tll_foreach(parent->parent->dict.pairs, pair) - { + if (parent->parent != NULL && + parent->parent->type == DICT && + node->type == SCALAR) + { + tll_foreach(parent->parent->dict.pairs, pair) { if (pair->item.value != parent) continue; @@ -327,14 +329,17 @@ format_error(enum yml_error err, const struct yml_node *parent, const struct yml assert(pair->item.key->type == SCALAR); assert(node->type == SCALAR); - snprintf(err_str, sizeof(err_str), "%s: duplicate key: '%s'", pair->item.key->scalar.value, + snprintf(err_str, sizeof(err_str), + "%s: duplicate key: '%s'", + pair->item.key->scalar.value, node->scalar.value); return err_str; } } if (node->type == SCALAR) { - snprintf(err_str, sizeof(err_str), "duplicate key: %s", node->scalar.value); + snprintf(err_str, sizeof(err_str), + "duplicate key: %s", node->scalar.value); } else snprintf(err_str, sizeof(err_str), "duplicate key"); break; @@ -342,20 +347,22 @@ format_error(enum yml_error err, const struct yml_node *parent, const struct yml case YML_ERR_INVALID_ANCHOR: if (parent->parent != NULL && parent->parent->type == DICT) { - tll_foreach(parent->parent->dict.pairs, pair) - { + tll_foreach(parent->parent->dict.pairs, pair) { if (pair->item.value != parent) continue; if (pair->item.key->type != SCALAR) break; - snprintf(err_str, sizeof(err_str), "%s: invalid anchor: %s", pair->item.key->scalar.value, + snprintf(err_str, sizeof(err_str), + "%s: invalid anchor: %s", + pair->item.key->scalar.value, anchor != NULL ? anchor : ""); return err_str; } } - snprintf(err_str, sizeof(err_str), "invalid anchor: %s", anchor != NULL ? anchor : ""); + snprintf(err_str, sizeof(err_str), "invalid anchor: %s", + anchor != NULL ? anchor : ""); break; case YML_ERR_UNKNOWN: @@ -366,47 +373,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) { @@ -431,12 +397,19 @@ yml_load(FILE *yml, char **error) yaml_event_t event; if (!yaml_parser_parse(&yaml, &event)) { if (error != NULL) { - int cnt = snprintf(NULL, 0, "%zu:%zu: %s %s", yaml.problem_mark.line + 1, yaml.problem_mark.column, - yaml.problem, yaml.context != NULL ? yaml.context : ""); + int cnt = snprintf( + NULL, 0, "%zu:%zu: %s %s", + yaml.problem_mark.line + 1, + yaml.problem_mark.column, + yaml.problem, + yaml.context != NULL ? yaml.context : ""); *error = malloc(cnt + 1); - snprintf(*error, cnt + 1, "%zu:%zu: %s %s", yaml.problem_mark.line + 1, yaml.problem_mark.column, - yaml.problem, yaml.context != NULL ? yaml.context : ""); + snprintf(*error, cnt + 1, "%zu:%zu: %s %s", + yaml.problem_mark.line + 1, + yaml.problem_mark.column, + yaml.problem, + yaml.context != NULL ? yaml.context : ""); } goto err_no_error_formatting; @@ -487,7 +460,9 @@ yml_load(FILE *yml, char **error) } if (!got_match) { - error_str = format_error(YML_ERR_INVALID_ANCHOR, n, NULL, (const char *)event.data.alias.anchor); + error_str = format_error( + YML_ERR_INVALID_ANCHOR, n, NULL, + (const char *)event.data.alias.anchor); yaml_event_delete(&event); goto err; } @@ -497,7 +472,8 @@ 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) { @@ -587,13 +563,23 @@ yml_load(FILE *yml, char **error) err: if (error_str != NULL) { - int cnt = snprintf(NULL, 0, "%zu:%zu: %s", yaml.mark.line + 1, yaml.mark.column, error_str); + int cnt = snprintf( + NULL, 0, "%zu:%zu: %s", + yaml.mark.line + 1, + yaml.mark.column, + error_str); *error = malloc(cnt + 1); - snprintf(*error, cnt + 1, "%zu:%zu: %s", yaml.mark.line + 1, yaml.mark.column, error_str); + snprintf( + *error, cnt + 1, "%zu:%zu: %s", + yaml.mark.line + 1, + yaml.mark.column, + error_str); } else { - int cnt = snprintf(NULL, 0, "%zu:%zu: unknown error", yaml.mark.line + 1, yaml.mark.column); + int cnt = snprintf(NULL, 0, "%zu:%zu: unknown error", + yaml.mark.line + 1, yaml.mark.column); *error = malloc(cnt + 1); - snprintf(*error, cnt + 1, "%zu:%zu: unknown error", yaml.mark.line + 1, yaml.mark.column); + snprintf(*error, cnt + 1, "%zu:%zu: unknown error", + yaml.mark.line + 1, yaml.mark.column); } err_no_error_formatting: @@ -625,8 +611,7 @@ yml_destroy(struct yml_node *node) break; case DICT: - tll_foreach(node->dict.pairs, it) - { + tll_foreach(node->dict.pairs, it) { yml_destroy(it->item.key); yml_destroy(it->item.value); } @@ -668,12 +653,13 @@ yml_get_(struct yml_node const *node, char const *_path, bool value) char *path = strdup(_path); - for (const char *part = strtok(path, "."), *next_part = strtok(NULL, "."); part != NULL; - part = next_part, next_part = strtok(NULL, ".")) { + for (const char *part = strtok(path, "."), *next_part = strtok(NULL, "."); + part != NULL; + part = next_part, next_part = strtok(NULL, ".")) + { assert(yml_is_dict(node)); - tll_foreach(node->dict.pairs, it) - { + tll_foreach(node->dict.pairs, it) { assert(yml_is_scalar(it->item.key)); if (strcmp(it->item.key->scalar.value, part) == 0) { if (next_part == NULL) { @@ -702,8 +688,7 @@ yml_get_value(const struct yml_node *node, const char *_path) } struct yml_node const * -yml_get_key(struct yml_node const *node, char const *_path) -{ +yml_get_key(struct yml_node const *node, char const *_path) { return yml_get_(node, _path, false); } @@ -711,8 +696,7 @@ struct yml_list_iter yml_list_iter(const struct yml_node *list) { assert(yml_is_list(list)); - tll_foreach(list->list.values, it) - { + tll_foreach(list->list.values, it) { return (struct yml_list_iter){ .node = it->item, .private = it, @@ -745,7 +729,9 @@ yml_list_length(const struct yml_node *list) assert(yml_is_list(list)); size_t length = 0; - for (struct yml_list_iter it = yml_list_iter(list); it.node != NULL; yml_list_next(&it), length++) + for (struct yml_list_iter it = yml_list_iter(list); + it.node != NULL; + yml_list_next(&it), length++) ; return length; @@ -756,8 +742,7 @@ yml_dict_iter(const struct yml_node *dict) { assert(yml_is_dict(dict)); - tll_foreach(dict->dict.pairs, it) - { + tll_foreach(dict->dict.pairs, it) { return (struct yml_dict_iter){ .key = it->item.key, .value = it->item.value, @@ -765,7 +750,7 @@ yml_dict_iter(const struct yml_node *dict) }; } - return (struct yml_dict_iter){ + return (struct yml_dict_iter) { .key = NULL, .value = NULL, .private1 = NULL, @@ -836,12 +821,18 @@ _as_bool(const struct yml_node *value, bool *ret) return false; const char *v = yml_value_as_string(value); - if (strcasecmp(v, "y") == 0 || strcasecmp(v, "yes") == 0 || strcasecmp(v, "true") == 0 - || strcasecmp(v, "on") == 0) { + if (strcasecmp(v, "y") == 0 || + strcasecmp(v, "yes") == 0 || + strcasecmp(v, "true") == 0 || + strcasecmp(v, "on") == 0) + { *ret = true; return true; - } else if (strcasecmp(v, "n") == 0 || strcasecmp(v, "no") == 0 || strcasecmp(v, "false") == 0 - || strcasecmp(v, "off") == 0) { + } else if (strcasecmp(v, "n") == 0 || + strcasecmp(v, "no") == 0 || + strcasecmp(v, "false") == 0 || + strcasecmp(v, "off") == 0) + { *ret = false; return true; } @@ -888,8 +879,7 @@ _print_node(const struct yml_node *n, int indent) break; case DICT: - tll_foreach(n->dict.pairs, it) - { + tll_foreach(n->dict.pairs, it) { _print_node(it->item.key, indent); printf(": "); @@ -904,8 +894,7 @@ _print_node(const struct yml_node *n, int indent) break; case LIST: - tll_foreach(n->list.values, it) - { + tll_foreach(n->list.values, it) { printf("%*s- ", indent, ""); if (it->item->type != SCALAR) { printf("\n"); diff --git a/yml.h b/yml.h index 784252c..0e5eca4 100644 --- a/yml.h +++ b/yml.h @@ -1,6 +1,6 @@ #pragma once -#include #include +#include struct yml_node; @@ -11,8 +11,10 @@ bool yml_is_scalar(const struct yml_node *node); bool yml_is_dict(const struct yml_node *node); bool yml_is_list(const struct yml_node *node); -const struct yml_node *yml_get_value(const struct yml_node *node, const char *path); -const struct yml_node *yml_get_key(struct yml_node const *node, char const *path); +const struct yml_node *yml_get_value( + const struct yml_node *node, const char *path); +const struct yml_node *yml_get_key( + struct yml_node const *node, char const *path); struct yml_list_iter { const struct yml_node *node;