Merge tag '3.6.3'

Search for xcbgen with PYTHON_EXECUTABLE

This way users can specify `-D:PYTHON_EXECUTABLE` to force a certain
python executable and that executable will then also be used to search
for xcbgen.

This should also provide a more universal solution to the configuration
issues with pyenv or conda since the user can just specify
`-D:PYTHON_EXECUTABLE=/usr/bin/python3`.
This commit is contained in:
Przemek Grondek 2023-08-05 18:42:20 +02:00
commit dd03bb3c40
267 changed files with 9900 additions and 10157 deletions

View File

@ -10,4 +10,5 @@ AllowShortIfStatementsOnASingleLine: false
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
DerivePointerAlignment: false DerivePointerAlignment: false
PointerAlignment: Left PointerAlignment: Left
SpacesBeforeTrailingComments: 1
--- ---

View File

@ -32,8 +32,6 @@ Checks: '
CheckOptions: CheckOptions:
- key: modernize-loop-convert.NamingStyle - key: modernize-loop-convert.NamingStyle
value: lower_case value: lower_case
- key: readability-identifier-naming.GlobalConstantPrefix
value: 'g_'
- key: readability-identifier-naming.ClassCase - key: readability-identifier-naming.ClassCase
value: lower_case value: lower_case
- key: readability-identifier-naming.ClassConstantCase - key: readability-identifier-naming.ClassConstantCase

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: polybar
open_collective: polybar

View File

@ -1,61 +0,0 @@
---
name: Bug Report
about: Create a report for something that misbehaves
---
## Checklist
<!-- Please carefully go through this checklist and put an 'x' inside the brackets: '[x]' -->
* [ ] I have read the appropriate section in the [contributing
guidelines](https://github.com/polybar/polybar/blob/master/CONTRIBUTING.md)
* [ ] I believe this issue is a problem with polybar itself and not a misconfiguration on my part.
* [ ] I have searched for other open and closed [issues](https://github.com/polybar/polybar/issues?q=is%3Aissue) that
may have already reported this problem.
* [ ] I have checked the [known issues](https://github.com/polybar/polybar/wiki/Known-Issues) page for this problem.
## Describe the bug
<!-- A clear and concise description of what the bug is: -->
**Expected behavior:**
<!-- A clear and concise description of what you expected to happen: -->
**Actual behavior:**
<!-- What actually happens: -->
**Was it working before?**
* Did you also experience this bug in an earlier version of polybar (yes/no/don't know)?
* If no, what was the last version where this worked correctly?
## To Reproduce
<!-- A minimal but complete config with which the problem occurs: -->
```dosini
```
<!-- List any other steps needed to reproduce the issue, besides starting polybar with the config you posted above. -->
## Polybar Log
<!-- Post everything polybar outputs to the terminal when you run it and the issue occurs below -->
```
```
## Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
## Environment:
* WM:
* Distro:
* Output of `polybar -vvv`:
```
```
## Additional context
<!-- Add any other context that you think is necessary about the problem here. -->

112
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,112 @@
name: Bug Report
description: Create a report for something that misbehaves
title: "[Bug]: "
labels: ["bug", "needs confirmation"]
body:
- type: checkboxes
id: checklist
attributes:
label: Checklist
description: Please carefully go through this checklist and check each option.
options:
- label: I have read the appropriate section in the [contributing guidelines](https://github.com/polybar/polybar/blob/master/CONTRIBUTING.md)
required: true
- label: I believe this issue is a problem with polybar itself and not a misconfiguration on my part
required: true
- label: I have searched for other open and closed [issues](https://github.com/polybar/polybar/issues?q=is%3Aissue) that may have already reported this problem
required: true
- label: I have checked the [known issues](https://github.com/polybar/polybar/wiki/Known-Issues) page for this problem.
required: true
- label: I have followed the [debugging guide](https://github.com/polybar/polybar/wiki/Debugging-your-Config) to narrow down the problem to a minimal config.
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
description: Any steps to take and commands to run to reproduce this issue.
placeholder: |
1. `polybar -c ... bar`
2. ...
validations:
required: true
- type: textarea
id: config
attributes:
label: Minimal config
description: A minimal but complete config with which the problem occurs.
render: dosini
placeholder: |
[bar/example]
...
[module/...]
...
validations:
required: true
- type: textarea
id: logs
attributes:
label: Polybar log
description: Post everything polybar prints to the terminal when you run it and the issue occurs. If possible, run polybar with a higher log level (e.g. `trace` or `info`).
render: text
placeholder: |
notice: Parsing config file: ...
...
- type: textarea
id: expected
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual behavior
description: What actually happens
validations:
required: true
- type: input
id: wm
attributes:
label: Window Manager and Version
placeholder: ex. i3-gaps 4.19.1
validations:
required: true
- type: input
id: distro
attributes:
label: Linux Distribution
placeholder: ex. Ubuntu 21.04
validations:
required: true
- type: textarea
id: version
attributes:
label: Polybar version
description: Output of `polybar -vvv`
render: text
placeholder: |
polybar 3.5.7
Features: +alsa +curl +i3 +mpd +network(libnl) +pulseaudio +xkeyboard
X extensions: +randr (+monitors) +composite +xkb +xrm +xcursor
Build type: Release
Compiler: /usr/bin/c++
Compiler flags: -D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -O3 -DNDEBUG -Wall -Wextra -Wpedantic -Wsuggest-override
Linker flags: -Wall -Wextra -Wpedantic -Wsuggest-override -Wall -Wextra -Wpedantic -Wsuggest-override
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional Context / Screenshots
description: If applicaple, add screenshots and additional context to explain your problem
validations:
required: false
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! :heart:

View File

@ -1,46 +0,0 @@
---
name: Build Issues
about: Report issues while building polybar from source
---
## Checklist
<!-- Please carefully go through this checklist and put an 'x' inside the brackets: '[x]' -->
* [ ] I have followed every step on the [compiling wiki page](https://github.com/polybar/polybar/wiki/Compiling) and
installed all necessary dependencies.
* [ ] My problem is not described on the [known issues page](https://github.com/polybar/polybar/wiki/Known-Issues)
* [ ] I have searched for other open and closed [issues](https://github.com/polybar/polybar/issues?q=is%3Aissue) that
may have already reported this problem.
* [ ] I was able to reproduce this build issue in a clean build
## Build Process
**How did you build polybar?**
<!--
Put an 'x' inside the brackets ([x]) of the entry that applies and respond to the question inside the parenthesis
-->
* [ ] From a release archive (Which version?)
* [ ] By cloning this repository (What is the output of `git describe --tags`?)
* [ ] Some other way (How?)
<!-- List the exact commands you are using to build polybar: -->
## Build Log
<!--
Copy-paste all the terminal output produced while building polybar.
This MUST include the output of the `cmake`, `make`, and/or `build.sh` commands, if you used them.
-->
```
```
## Environment:
* Distro (with Version):
## Additional context
<!-- Add any other context that you think is necessary about the problem here. -->

81
.github/ISSUE_TEMPLATE/build.yml vendored Normal file
View File

@ -0,0 +1,81 @@
name: Build Issues
description: Report issues while building polybar from source
labels: ["build", "needs confirmation"]
body:
- type: checkboxes
id: checklist
attributes:
label: Checklist
description: Please carefully go through this checklist and check each option.
options:
- label: I have followed every step on the [compiling wiki page](https://github.com/polybar/polybar/wiki/Compiling) and installed all necessary dependencies.
required: true
- label: My problem is not described on the [known issues page](https://github.com/polybar/polybar/wiki/Known-Issues)
required: true
- label: I have searched for other open and closed [issues](https://github.com/polybar/polybar/issues?q=is%3Aissue) that may have already reported this problem.
required: true
- label: I was able to reproduce this build issue in a clean build
required: true
- type: dropdown
id: source
attributes:
label: From where are you building polybar?
options:
- From a release archive
- By cloning this repository
- Some other way (How?)
validations:
required: true
- type: input
id: how
attributes:
label: Describe how you are building polybar.
description: Only if you selected "Some other way".
placeholder: ex. polybar from the AUR
validations:
required: false
- type: input
id: version
attributes:
label: Version
description: What version of polybar are you trying to build? If you are building directly from git, this is the output of `git describe --tags`.
placeholder: ex. 3.5.7
validations:
required: true
- type: textarea
id: commands
attributes:
label: Build Process
description: List the exact commands you are using to build polybar
render: shell
placeholder: |
mkdir build
cd build
cmake ..
...
validations:
required: true
- type: textarea
id: logs
attributes:
label: Build log
description: |
Copy-paste all the terminal output produced while building polybar.
This MUST include the output of the `cmake`, `make`, and/or `build.sh` commands, if you used them.
render: text
validations:
required: true
- type: input
id: distro
attributes:
label: Linux Distribution
placeholder: ex. Ubuntu 21.04
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional Context
description: Add any other context that you think is necessary about the problem here
validations:
required: false

View File

@ -1,7 +1,7 @@
--- ---
name: Feature request name: Feature request
about: Suggest an idea for this project about: Suggest an idea for this project
labels: feature, needs confirmation
--- ---
## Is your feature request related to a problem? Please describe. ## Is your feature request related to a problem? Please describe.

View File

@ -18,14 +18,47 @@ jobs:
with: with:
ref: ${{ github.event.inputs.ref }} ref: ${{ github.event.inputs.ref }}
- name: Install Dependencies - name: Install Dependencies
run: sudo apt-get install -y python3-sphinx run: |
sudo apt-get update
sudo apt-get install -y python3-sphinx
- name: Build Documentation - name: Build Documentation
run: | run: |
mkdir -p doc/build mkdir -p build
cd doc/build cd build
cmake .. cmake -DDISABLE_ALL=ON -DBUILD_DOC=ON -DSPHINX_FLAGS="-W" ..
make doc make doc
ipc:
runs-on: ubuntu-20.04
env:
COLOR: "ON"
steps:
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libxcb-composite0-dev \
libxcb-ewmh-dev \
libxcb-icccm4-dev \
libxcb-image0-dev \
libxcb-randr0-dev \
libxcb-util0-dev \
libxcb1-dev \
libcairo2-dev \
python3-xcbgen \
libuv1-dev \
xcb-proto
- uses: actions/checkout@v2
with:
submodules: true
ref: ${{ github.event.inputs.ref }}
- name: Build polybar-msg
run: |
mkdir -p build
cd build
cmake -DDISABLE_ALL=ON -DBUILD_POLYBAR_MSG=ON ..
make polybar-msg
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
@ -62,6 +95,7 @@ jobs:
libxcb1-dev \ libxcb1-dev \
libcairo2-dev \ libcairo2-dev \
python3-xcbgen \ python3-xcbgen \
libuv1-dev \
xcb-proto xcb-proto
if [ "$POLYBAR_BUILD_TYPE" != "minimal" ]; then if [ "$POLYBAR_BUILD_TYPE" != "minimal" ]; then
@ -74,9 +108,13 @@ jobs:
libjsoncpp-dev \ libjsoncpp-dev \
libasound2-dev \ libasound2-dev \
libpulse-dev \ libpulse-dev \
libiw-dev \ libnl-genl-3-dev \
libmpdclient-dev libmpdclient-dev
fi fi
if [ "$POLYBAR_BUILD_TYPE" = "tests" ]; then
sudo apt-get install -y lcov
fi
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
@ -89,10 +127,34 @@ jobs:
run: | run: |
cd $BUILD_DIR cd $BUILD_DIR
make make
- name: Collect initial coverage
if: ${{ matrix.polybar_build_type == 'tests' }}
run: |
lcov --capture --initial --no-external --directory . -o cov_base.info
- name: Tests - name: Tests
if: ${{ matrix.polybar_build_type == 'tests' }} if: ${{ matrix.polybar_build_type == 'tests' }}
run: | run: |
cd $BUILD_DIR cd $BUILD_DIR
make check make check
cd $POLYBAR_DIR - name: Collect coverage
bash <(curl -s https://codecov.io/bash) -F unittests -a "-ap" -Z if: ${{ matrix.polybar_build_type == 'tests' }}
run: |
lcov --capture --no-external --directory . -o cov_tests.info
lcov --add-tracefile cov_base.info --add-tracefile cov_tests.info -o cov_total.info
lcov --remove cov_total.info ${PWD}'/build/*' ${PWD}'/tests/*' ${PWD}'/lib/*' -o cov.info
- name: Upload Coverage
if: ${{ matrix.polybar_build_type == 'tests' }}
uses: codecov/codecov-action@v2
with:
flags: unittests
files: ./cov.info
fail_ci_if_error: true
- name: Upload Logs
if: failure()
uses: actions/upload-artifact@v2
with:
name: cmake
path: |
build/CMakeFiles/CMakeError.log
build/CMakeFiles/CMakeOutput.log
retention-days: 5

2
.gitignore vendored
View File

@ -1,11 +1,11 @@
/build /build
/tags /tags
/compile_commands.json /compile_commands.json
/config
*.bak *.bak
*.pyc *.pyc
*.swp *.swp
*.tmp *.tmp
.tags .tags
*.user
polybar-*.tar polybar-*.tar

View File

@ -10,53 +10,205 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Breaking ### Breaking
- We rewrote our tag parser. This shouldn't break anything, if you experience - `custom/script`:
any problems, please let us know. - now doesn't hide failing script if it's output is not changing ([`#2636`](https://github.com/polybar/polybar/issues/2636)). Somewhat similar behaviour can be imitated with `format-fail`, if necessary.
The new parser now gives errors for certain invalid tags where the old parser - If the `exec` command produced no output and exited with a non-zero exit code the module is no longer completely empty, but just has an empty `%output%` token. If you relied on this behavior to hide the module under certain circumstances, make sure the script exits with an exit code of zero. ([`#2857`](https://github.com/polybar/polybar/discussions/2857), [`#2861`](https://github.com/polybar/polybar/pull/2861))
would just silently ignore them. Adding extra text to the end of a valid tag
now produces an error. For example, tags like `%{T-a}`, `%{T2abc}`, `%{rfoo}`, ### Build
and others will now start producing errors. - Respect `CMAKE_INSTALL_PREFIX` when installing default config ([`#2770`](https://github.com/polybar/polybar/pull/2770), [`#2917`](https://github.com/polybar/polybar/pull/2917))
This does not affect you unless you are producing your own formatting tags - Change default `CMAKE_INSTALL_PREFIX` to `/usr`. Installations with default flags will now go into `/usr` instead of `/usr/local` ([`#2917`](https://github.com/polybar/polybar/pull/2917))
(for example in a script) and you are using one of these invalid tags. - Bump C++ version to C++17 ([`#2847`](https://github.com/polybar/polybar/pull/2847))
### Deprecated
- `custom/text`: The `content` setting and all its properties are deprecated in favor of `format` with the same functionality. ([`#2676`](https://github.com/polybar/polybar/pull/2676))
### Added ### Added
- Warn states for the cpu, memory, fs, and battery modules. - Added support for TAG_LABEL (`<label>`) in ipc module ([`#2841`](https://github.com/polybar/polybar/pull/2841)) by [@madhavpcm](https://github.com/madhavpcm).
([`#570`](https://github.com/polybar/polybar/issues/570), - Added support for format-i for each hook-i defined in ipc module ([`#2775`](https://github.com/polybar/polybar/issues/2775), [`#2810`](https://github.com/polybar/polybar/pull/2810)) by [@madhavpcm](https://github.com/madhavpcm).
[`#956`](https://github.com/polybar/polybar/issues/956), - `internal/temperature`: `%temperature-k%` token displays the temperature in kelvin ([`#2774`](https://github.com/polybar/polybar/discussions/2774), [`#2784`](https://github.com/polybar/polybar/pull/2784))
[`#1871`](https://github.com/polybar/polybar/issues/1871), - `internal/pulseaudio`: `reverse-scroll` option ([`#2664`](https://github.com/polybar/polybar/pull/2664))
[`#2141`](https://github.com/polybar/polybar/issues/2141)) - `custom/script`: Repeat interval for script failure (`interval-fail`) and `exec-if` (`interval-if`) ([`#943`](https://github.com/polybar/polybar/issues/943), [`#2606`](https://github.com/polybar/polybar/issues/2606), [`#2630`](https://github.com/polybar/polybar/pull/2630))
- `internal/battery`: `format-low`, `label-low`, `animation-low`, `low-at = - `custom/text`: Loads the `format` setting, which supports the `<label>` tag, if the deprecated `content` is not defined ([`#1331`](https://github.com/polybar/polybar/issues/1331), [`#2673`](https://github.com/polybar/polybar/pull/2673), [`#2676`](https://github.com/polybar/polybar/pull/2676))
10`. - Added experimental support for positioning the tray like a module
- `internal/backlight`: `scroll-interval` option ([`#2696`](https://github.com/polybar/polybar/issues/2696), [`#2700`](https://github.com/polybar/polybar/pull/2700))
- `internal/temperature`: Added `zone-type` setting ([`#2572`](https://github.com/polybar/polybar/issues/2572), [`#2752`](https://github.com/polybar/polybar/pull/2752)) by [@xphoniex](https://github.com/xphoniex)
- `internal/xwindow`: `%class%` and `%instance%` tokens, which show the contents of the `WM_CLASS` property of the active window ([`#2830`](https://github.com/polybar/polybar/pull/2830))
- Added `enable-struts` option in bar section to enable/disable struts ([`#2769`](https://github.com/polybar/polybar/issues/2769), [`#2844`](https://github.com/polybar/polybar/pull/2844)) by [@VanillaViking](https://github.com/VanillaViking).
- `wm-restack`:
- `bottom`: lowers polybar to the bottom of the window stack (same as the previous behavior of `generic`) ([`#2961`](https://github.com/polybar/polybar/pull/2961))
- `ewmh`: Tries to use the `_NET_SUPPORTING_WM_CHECK` hint to position the bar ([`#2961`](https://github.com/polybar/polybar/pull/2961))
### Changed
- `custom/script`:
- No longer produces a completely empty module if the `exec` command failed. It only produces an empty module if the script had a zero exit code. ([`#2857`](https://github.com/polybar/polybar/discussions/2857), [`#2861`](https://github.com/polybar/polybar/pull/2861))
- Bumped the script polling interval (not related to the `interval` setting) to decrease wakeups. Polybar may take slightly longer to shut down. [`#2879`](https://github.com/polybar/polybar/pull/2879)
- `internal/fs`: Use `/` as a fallback if no mountpoints are specified ([`#2572`](https://github.com/polybar/polybar/issues/2572), [`#2705`](https://github.com/polybar/polybar/pull/2705))
- `internal/backlight`:
- Detect backlight if none specified ([`#2572`](https://github.com/polybar/polybar/issues/2572), [`#2728`](https://github.com/polybar/polybar/pull/2728))
- `use-actual-brightness` defaults to `true` for `amdgpu` backlights ([`#2835`](https://github.com/polybar/polybar/issues/2835), [`2839`](https://github.com/polybar/polybar/pull/2839))
- Providing a negative min-width to a token adds right-padding ([`#2789`](https://github.com/polybar/polybar/issues/2789), [`#2801`](https://github.com/polybar/polybar/pull/2801)) by [@VanillaViking](https://github.com/VanillaViking).
- Changed fuzzy match option on i3 and bspwm modules to find longest match instead of the first match ([`#2831`](https://github.com/polybar/polybar/pull/2831), [`#2829`](https://github.com/polybar/polybar/issues/2829)) by [@Ron0Studios](https://github.com/ron0studios/).
- `wm-restack`
- `generic`: Is now a best effort combination of other restacking strategies. First tries `ewmh` and then the `bottom` strategy ([`#2961`](https://github.com/polybar/polybar/pull/2961))
- `bspwm`: First tries the `ewmh` strategy before falling back to its old behavior ([`#2961`](https://github.com/polybar/polybar/pull/2961))
### Fixed
- Waiting for double click interval on modules that don't have a double click action ([`#2663`](https://github.com/polybar/polybar/issues/2663), [`#2695`](https://github.com/polybar/polybar/pull/2695))
- renderer:
- Small gaps when rendering emojis ([`#2785`](https://github.com/polybar/polybar/issues/2785), [`#2802`](https://github.com/polybar/polybar/pull/2802))
- Crash when using pseudo-transparency with certain wallpapers ([`#2798`](https://github.com/polybar/polybar/issues/2798), [`#2813`](https://github.com/polybar/polybar/pull/2813))
- Crash when invalid UTF-8 text is encountered ([`#2091`](https://github.com/polybar/polybar/issues/2091), [`#2958`](https://github.com/polybar/polybar/pull/2958))
- config:
- Error reporting for deprecated config values ([`#2724`](https://github.com/polybar/polybar/issues/2724))
- Also monitor include-files for changes when --reload is set ([`#675`](https://github.com/polybar/polybar/issues/675), [`#2759`](https://github.com/polybar/polybar/pull/2759))
- `internal/xwindow`: module does not crash when a tag is not provided in format ([`#2826`](https://github.com/polybar/polybar/issues/2826), [`#2833`](https://github.com/polybar/polybar/pull/2833)) by [@VanillaViking](https://github.com/VanillaViking)
- `internal/i3`: module errors when i3 has negative gaps ([`#2888`](https://github.com/polybar/polybar/issues/2888), [`#2889`](https://github.com/polybar/polybar/pull/2889))
- `wm-restack = bspwm`: bar may become unclickable if there are overlapping monitors ([`#2873`](https://github.com/polybar/polybar/issues/2873), [`#2961`](https://github.com/polybar/polybar/pull/2961))
## [3.6.3] - 2022-05-04
### Fixed
- `custom/script`: Output clearing when `exec-if` fails ([`#2674`](https://github.com/polybar/polybar/issues/2674))
- `internal/battery`: `poll-interval` not working ([`#2649`](https://github.com/polybar/polybar/issues/2649), [`#2677`](https://github.com/polybar/polybar/pull/2677))
- ipc: Polybar failing to open IPC channel after another user already ran polybar, if `XDG_RUNTIME_DIR` is not set ([`#2683`](https://github.com/polybar/polybar/issues/2683), [`#2684`](https://github.com/polybar/polybar/pull/2684))
- No overlines/underlines being drawn when using offsets ([`#2685`](https://github.com/polybar/polybar/pull/2685))
- Update struts (`_NET_WM_STRUT_PARTIAL`) when hiding the bar ([`#2702`](https://github.com/polybar/polybar/pull/2702))
- `internal/pulseaudio`: Hanging during startup ([`#2707`](https://github.com/polybar/polybar/issues/2707), [`#2709`](https://github.com/polybar/polybar/pull/2709))
- `internal/xworkspaces`: Updates of `_NET_DESKTOP_VIEWPORT` being ignored ([`#2693`](https://github.com/polybar/polybar/issues/2693), [`#2698`](https://github.com/polybar/polybar/pull/2698))
## [3.6.2] - 2022-04-03
### Fixed
- `format-offset` being ignored ([`#2643`](https://github.com/polybar/polybar/pull/2643))
- Negative struts (`margin-bottom`, `margin-top`) being ignored ([`#2642`](https://github.com/polybar/polybar/issues/2642), [`#2644`](https://github.com/polybar/polybar/pull/2644))
- Positioning in awesomeWM ([`#2651`](https://github.com/polybar/polybar/pull/2651))
- `internal/xworkspaces`: The module sometimes crashed polybar when windows were closed. ([`#2655`](https://github.com/polybar/polybar/pull/2655))
- Mouseover error when only one cursor is defined ([`#2656`](https://github.com/polybar/polybar/pull/2656))
- `custom/script`: Timing inconsistencies ([`#2650`](https://github.com/polybar/polybar/issues/2650), first described at [`#2630`](https://github.com/polybar/polybar/pull/2630))
## [3.6.1] - 2022-03-05
### Build
- Fixed compiler warning in Clang 13 ([`#2613`](https://github.com/polybar/polybar/pull/2613))
- Fixed compiler error in GCC 12 ([`#2616`](https://github.com/polybar/polybar/pull/2616), [`#2614`](https://github.com/polybar/polybar/issues/2614))
- Fixed installation of docs when some are not generated (man, html...) ([`#2612`](https://github.com/polybar/polybar/pull/2612))
- Fix `LDFLAGS` not being respected ([`#2619`](https://github.com/polybar/polybar/pull/2619))
### Fixed
- `tray-offset-x`, `tray-offset-y`, `offset-x`, and `offset-y` were mistakenly capped below at 0 ([`#2620`](https://github.com/polybar/polybar/pull/2620))
- `custom/script`: Polybar shutdown being stalled by hanging script ([`#2621`](https://github.com/polybar/polybar/pull/2621))
- `polybar-msg`: Wrong hint when using deprecated `hook` ([`#2624`](https://github.com/polybar/polybar/pull/2624))
## [3.6.0] - 2022-03-01
### Breaking
- We added the backslash escape character (\\) for configuration values. This means that the literal backslash character now has special meaning in configuration files, therefore if you want to use it in a value as a literal backslash, you need to escape it with the backslash escape character. The parser logs an error if any unescaped backslashes are found in a value. This affects you only if you are using two consecutive backslashes in a config value, which will now be interpreted as a single literal backslash. ([`#2354`](https://github.com/polybar/polybar/issues/2354))
- We rewrote our formatting tag parser. This shouldn't break anything, if you experience any problems, please let us know. The new parser now gives errors for certain invalid tags where the old parser would just silently ignore them. Adding extra text to the end of a valid tag now produces an error. For example, tags like `%{T-a}`, `%{T2abc}`, `%{rfoo}`, and others will now start producing errors. This does not affect you unless you are producing your own invalid formatting tags (for example in a script).
- For security reasons, the named pipe at `/tmp/polybar_mqueue.<PID>` had its permission bits changed from `666` to `600` to prevent sending ipc messages to polybar processes running under a different user.
- Also for security reasons, the `polybar-msg` command will now only send messages to polybar processes running under the same user. See the [IPC documentation](https://polybar.readthedocs.io/en/stable/user/ipc.html) for what exactly this means.
### Build
- New dependency: [libuv](https://github.com/libuv/libuv). At least version 1.3 is required.
- Bump the minimum cmake version to 3.5
- The `BUILD_IPC_MSG` option has been renamed to `BUILD_POLYBAR_MSG`
- Building the documentation is now enabled by default and not just when `sphinx-build` is found.
- Users can control exactly which targets should be available with the following cmake options (together with their default value):
- `BUILD_POLYBAR=ON` - Builds the `polybar` executable
- `BUILD_POLYBAR_MSG=ON` - Builds the `polybar-msg` executable
- `BUILD_TESTS=OFF` - Builds the test suite
- `BUILD_DOC=ON` - Builds the documentation
- `BUILD_DOC_HTML=BUILD_DOC` - Builds the html documentation (depends on `BUILD_DOC`)
- `BUILD_DOC_MAN=BUILD_DOC` - Builds the manpages (depends on `BUILD_DOC`)
- `BUILD_CONFIG=ON` - Generates the default config
- `BUILD_SHELL=ON` - Generates shell completion files
- `DISABLE_ALL=OFF` - Disables all above targets by default. Individual targets can still be enabled explicitly.
- The documentation can no longer be built by directly configuring the `doc` directory.
- The `POLYBAR_FLAGS` cmake variable can be used to pass extra C++ compiler flags.
- The sample config file has been removed.
- Polybar now ships a default config that is installed to `/etc/polybar/config.ini`, it lives in `doc/config.ini`. It will also be placed in the `examples` directory in the documentation folder. ([`#2405`](https://github.com/polybar/polybar/issues/2405))
- The `userconfig` target has been removed, you can no longer use `make userconfig`. As an alternative, you can copy the default config from `/etc/polybar/config.ini`.
- The `DEBUG_SHADED` cmake variable and its associated functionality has been removed.
### Deprecated
- `[settings]`: `throttle-output` and `throttle-output-for` have been removed. The new event loop already does a similar thing where it coalesces update triggers if they happen directly after one another, leading to only a single bar update.
- When not specifying the config file with `--config`, naming your config file `config` is deprecated. Rename your config file to `config.ini`.
- Directly writing ipc messages to `/tmp/polybar_mqueue.<PID>` is deprecated, users should always use `polybar-msg`. As a consequence the message format used for IPC is deprecated as well.
- `polybar-msg hook` is deprecated in favor of using the hook action. `polybar-msg` will tell you the correct command to use.
### Added
- Support `px` and `pt` units everyhwere where before only a number of spaces or pixels could be specified. ([`#2578`](https://github.com/polybar/polybar/pull/2578), [`#1651`](https://github.com/polybar/polybar/issues/1651), [`#951`](https://github.com/polybar/polybar/issues/951))
- `internal/alsa`: Right and middle click settings. ([`#2566`](https://github.com/polybar/polybar/issues/2566), [`#2573`](https://github.com/polybar/polybar/pull/2573))
- `internal/network`:
- New token `%mac%` shows MAC address of selected interface ([`#2568`](https://github.com/polybar/polybar/issues/2568), [`#2569`](https://github.com/polybar/polybar/pull/2569))
- New token `%netspeed%` that provides the total speed of the internet (up + down speed) ([`#2590`](https://github.com/polybar/polybar/pull/2590), [`#1083`](https://github.com/polybar/polybar/issues/1083))
- `speed-unit = B/s` can be used to customize how network speeds are displayed. ([`#2068`](https://github.com/polybar/polybar/pull/2068))
- `interface-type` may be used in place of `interface` to automatically select a network interface ([`#2025`](https://github.com/polybar/polybar/pull/2025), [`#339`](https://github.com/polybar/polybar/issues/339))
- Polybar can now read config files from stdin: `polybar -c /dev/stdin`. ([`#2545`](https://github.com/polybar/polybar/pull/2545))
- `custom/script`:
- Setting environment variables using `env-*` config option. ([`#2090`](https://github.com/polybar/polybar/issues/2090), [`#2512`](https://github.com/polybar/polybar/pull/2512))
- Add formatting for script failure (`format-fail`, `label-fail`) ([`#2588`](https://github.com/polybar/polybar/issues/2588), [`#2596`](https://github.com/polybar/polybar/pull/2596))
- Support for ramp weights. ([`#1750`](https://github.com/polybar/polybar/issues/1750), [`#2505`](https://github.com/polybar/polybar/pull/2505))
- `internal/memory`: New tokens `%used%`, `%free%`, `%total%`, `%swap_total%`, `%swap_free%`, and `%swap_used%` that automatically switch between MiB and GiB when below or above 1GiB. ([`#2472`](https://github.com/polybar/polybar/issues/2472), [`#2488`](https://github.com/polybar/polybar/pull/2488))
- `internal/i3`: `show-urgent` option to always show urgent windows when `pin-workspace` is active ([`#2374`](https://github.com/polybar/polybar/issues/2374), [`#2378`](https://github.com/polybar/polybar/pull/2378))
- `internal/xworkspaces`:
- `reverse-scroll` can be used to reverse the scroll direction when cycling through desktops. ([`#2365`](https://github.com/polybar/polybar/pull/2365))
- `%nwin%` can be used to display the number of open windows per workspace ([`#604`](https://github.com/polybar/polybar/issues/604), [`#2329`](https://github.com/polybar/polybar/pull/2329))
- Initial support for the backslash escape character (\\) in configs. ([`#2354`](https://github.com/polybar/polybar/issues/2354), [`#2361`](https://github.com/polybar/polybar/pull/2361))
- Warn states for the cpu, memory, fs, and battery modules. ([`#570`](https://github.com/polybar/polybar/issues/570), [`#956`](https://github.com/polybar/polybar/issues/956), [`#1871`](https://github.com/polybar/polybar/issues/1871), [`#2141`](https://github.com/polybar/polybar/issues/2141), [`#2199`](https://github.com/polybar/polybar/pull/2199))
- `internal/battery`: `format-low`, `label-low`, `animation-low`, `low-at = 10`.
- `internal/cpu`: `format-warn`, `label-warn`, `warn-percentage = 80` - `internal/cpu`: `format-warn`, `label-warn`, `warn-percentage = 80`
- `internal/fs`: `format-warn`, `label-warn`, `warn-percentage = 90` - `internal/fs`: `format-warn`, `label-warn`, `warn-percentage = 90`
- `internal/memory`: `format-warn`, `label-warn`, `warn-percentage = 90` - `internal/memory`: `format-warn`, `label-warn`, `warn-percentage = 90`
- Per-corner corner radius with `radius-{bottom,top}-{left,right}` - `radius` now affects the bar border as well ([`#1566`](https://github.com/polybar/polybar/issues/1566), [`#2359`](https://github.com/polybar/polybar/pull/2359))
([`#2294`](https://github.com/polybar/polybar/issues/2294)) - Per-corner radius with `radius-{bottom,top}-{left,right}` ([`#2294`](https://github.com/polybar/polybar/issues/2294), [`#2297`](https://github.com/polybar/polybar/pull/2297))
- `internal/network`: `speed-unit = B/s` can be used to customize how network - `internal/xkeyboard`:
speeds are displayed. - `%variant%` token to display the keyboard layout variant ([`#316`](https://github.com/polybar/polybar/issues/316), [`#2163`](https://github.com/polybar/polybar/pull/2163))
- `internal/xkeyboard`: `%variant%` can be used to parse the layout variant - Allow matching of variants in `layout-icon` ([`#2414`](https://github.com/polybar/polybar/issues/2414), [`#2521`](https://github.com/polybar/polybar/pull/2521))
([`#316`](https://github.com/polybar/polybar/issues/316)) - Config option to hide a certain module (`hidden = false`) ([`#2108`](https://github.com/polybar/polybar/issues/2108), [`#2342`](https://github.com/polybar/polybar/pull/2342))
- Actions to control visibility of modules (`module_toggle`, `module_show`, and `module_hide`) ([`#2108`](https://github.com/polybar/polybar/issues/2108), [`#2426`](https://github.com/polybar/polybar/pull/2426))
- `internal/backlight`: `use-actual-brightness` option to use the `actual_brightness` file to get the brightness ([`#2380`](https://github.com/polybar/polybar/pull/2380))
- `wm-restack = generic` option that lowers polybar to the bottom of the window stack. Fixes the issue where the bar is being drawn on top of fullscreen windows in xmonad. ([`#2205`](https://github.com/polybar/polybar/issues/2205), [`#2404`](https://github.com/polybar/polybar/pull/2404))
- `internal/bspwm`: `occupied-scroll = true` option allows scrolling through occupied desktops only. ([`#2427`](https://github.com/polybar/polybar/issues/2427), [`#2428`](https://github.com/polybar/polybar/pull/2428))
- `custom/ipc`:
- `send` action to send arbitrary strings to be displayed in the module. ([`#2455`](https://github.com/polybar/polybar/issues/2455), [`#2463`](https://github.com/polybar/polybar/pull/2463))
- `hook`, `next`, `prev`, `reset` actions to control the module through actions instead of the deprecated hook messages ([`#2464`](https://github.com/polybar/polybar/issues/2464), [`#2528`](https://github.com/polybar/polybar/pull/2528))
- Added `double-click-interval` setting to the bar section to control the time interval in which a double-click is recognized. Defaults to 400 (ms) ([`#1441`](https://github.com/polybar/polybar/issues/1441), [`#2510`](https://github.com/polybar/polybar/pull/2510))
- Added a new `tray-foreground` setting to give hints to tray icons about what color they should be. ([`#2235`](https://github.com/polybar/polybar/issues/2235), [`#2552`](https://github.com/polybar/polybar/pull/2552))
- `polybar-msg`:
- For module actions, you can now also specify the module name, action name, and optional data as separate arguments. ([`#2539`](https://github.com/polybar/polybar/pull/2539))
- Added man page: `man 1 polybar-msg` ([`#2539`](https://github.com/polybar/polybar/pull/2539))
### Changed ### Changed
- Slight changes to the value ranges the different ramp levels are responsible - Polybar now also reads `config.ini` when searching for config files. ([`#2323`](https://github.com/polybar/polybar/issues/2323), [`#2324`](https://github.com/polybar/polybar/pull/2324))
for in the cpu, memory, fs, and battery modules. The first and last level are - Polybar additionally searches in `XDG_CONFIG_DIRS/polybar/config.ini` (or `/etc/xdg/polybar/config.ini` if it is not set) and `/etc/polybar/config.ini` for config files. ([`#2016`](https://github.com/polybar/polybar/issues/2016), [`#2511`](https://github.com/polybar/polybar/pull/2511))
only used for everything at or below and at and above the edges of the value - We rewrote polybar's main event loop. This shouldn't change any behavior for the user, but be on the lookout for X events, click events, or ipc messages not arriving and the bar not shutting down/restarting properly and let us know if you find any issues. ([`#2384`](https://github.com/polybar/polybar/pull/2384))
range, respectively. The other levels are evenly distributed over the value - Slight changes to the value ranges the different ramp levels are responsible for in the cpu, memory, fs, and battery modules. The first level is used for everything at and below the start of the value range and the last level for everything at and above the end of the value range. The other levels are evenly distributed over the value range as before. The value range is bounded by the new warning thresholds. ([`#2199`](https://github.com/polybar/polybar/pull/2199))
range as before. - `custom/script`: `interval` now defaults to 0 if `tail = true` as per the documentation. ([`#2240`](https://github.com/polybar/polybar/pull/2240))
- `custom/script`: `interval` now defaults to 0 if `tail = true` as per the - `internal/network`: Increased precision for upload and download speeds: 0 decimal places for KB/s (as before), 1 for MB/s and 2 for GB/s. ([`#2054`](https://github.com/polybar/polybar/pull/2054))
documentation. - Clicks arriving in close succession, no longer get dropped. Before polybar would drop any click that arrived within 5ms of the previous one. ([`#2510`](https://github.com/polybar/polybar/pull/2510))
- `internal/network`: - Increased the double click interval from 150ms to 400ms. ([`#2510`](https://github.com/polybar/polybar/pull/2510))
- Increased precision for upload and download speeds: 0 decimal places for - Stop ignoring actions if they arrive while the previous one hasn't been processed yet. ([`#2469`](https://github.com/polybar/polybar/issues/2469), [`#2517`](https://github.com/polybar/polybar/pull/2517))
KB/s (as before), 1 for MB/s and 2 for GB/s. - Polybar can now be run without passing the bar name as argument given that the configuration file only defines one bar ([`#2525`](https://github.com/polybar/polybar/issues/2525), [`#2526`](https://github.com/polybar/polybar/pull/2526))
- `include-directory` and `include-file` now support relative paths. The paths are relative to the folder of the file where those directives appear. ([`#2523`](https://github.com/polybar/polybar/issues/2523), [`#2535`](https://github.com/polybar/polybar/issues/2535))
- `custom/ipc`: Empty output strings are no longer formatted. This prevents extraneous spaces and separators from appearing in the bar when the output of an ipc module is empty. ([`#2549`](https://github.com/polybar/polybar/pull/2549))
### Fixed ### Fixed
- Trailing space after the layout label when indicators are empty and made sure right amount - Broken positioning in Openbox when the bar is hidden and shown again ([`#2021`](https://github.com/polybar/polybar/issues/2021), [`#2600`](https://github.com/polybar/polybar/pull/2600))
of spacing is added between the indicator labels, in the xkeyboard module. - Handling of action blocks that contain negative offsets ([`#1814`](https://github.com/polybar/polybar/issues/1814), [`#2601`](https://github.com/polybar/polybar/pull/2601))
([`#2292`](https://github.com/polybar/polybar/issues/2292)) - `polybar -m` used to show both physical outputs and RandR monitors, even if the outputs were covered by monitors. ([`#2481`](https://github.com/polybar/polybar/issues/2481), [`#2485`](https://github.com/polybar/polybar/pull/2485))
- Parser error if click command contained `}` - Parser error if click command contained `}` ([`#2040`](https://github.com/polybar/polybar/issues/2040), [`#2303`](https://github.com/polybar/polybar/pull/2303))
([`#2040`](https://github.com/polybar/polybar/issues/2040)) - Some modules stop updating when system time moves backwards. ([`#857`](https://github.com/polybar/polybar/issues/857), [`#1932`](https://github.com/polybar/polybar/issues/1932), [`#2559`](https://github.com/polybar/polybar/pull/2559))
- `custom/script`: Concurrency issues with fast-updating tailed scripts. ([`#1978`](https://github.com/polybar/polybar/issues/1978), [`#2518`](https://github.com/polybar/polybar/pull/2518))
- `internal/alsa`: Slight imprecision when calculating percentages. This caused the volume reported to be off by one. ([`#2399`](https://github.com/polybar/polybar/issues/2399), [`#2401`](https://github.com/polybar/polybar/pull/2401))
- `internal/backlight`: With amdgpu backlights, the brightness indicator was slightly behind. ([`#2367`](https://github.com/polybar/polybar/issues/2367), [`#2380`](https://github.com/polybar/polybar/pull/2380))
- `internal/bspwm`: Warning message regarding T@ ([`#2371`](https://github.com/polybar/polybar/issues/2371), [`#2439`](https://github.com/polybar/polybar/pull/2439))
- `internal/xkeyboard`: Trailing space after the layout label when indicators are empty and made sure right amount of spacing is added between the indicator labels ([`#2292`](https://github.com/polybar/polybar/issues/2292), [`#2306`](https://github.com/polybar/polybar/pull/2306))
- `internal/xworkspaces`:
- Broken scroll-wrapping and order of workspaces when scrolling ([`#2491`](https://github.com/polybar/polybar/issues/2491), [`#2492`](https://github.com/polybar/polybar/pull/2492))
- Module would error if WM was not full started up. ([`#1915`](https://github.com/polybar/polybar/issues/1915), [`#2429`](https://github.com/polybar/polybar/pull/2429))
- Make the urgent hint persistent ([`#1081`](https://github.com/polybar/polybar/issues/1081), [`#2340`](https://github.com/polybar/polybar/pull/2340))
- Crash when the WM sets -1 for `_NET_WM_DESKTOP` ([`#2352`](https://github.com/polybar/polybar/issues/2352), [`#2353`](https://github.com/polybar/polybar/issues/2353))
- `internal/network`: The module now properly supports 'altnames' for interfaces. ([`#2540`](https://github.com/polybar/polybar/pull/2540))
- `internal/battery`: More accurate battery state ([`#2563`](https://github.com/polybar/polybar/issues/2563), [`#2556`](https://github.com/polybar/polybar/pull/2556))
- Offset tag does not respect current background color ([`#2578`](https://github.com/polybar/polybar/pull/2578), [`#1700`](https://github.com/polybar/polybar/issues/1700))
- Crash when negative margin or padding was specified ([`#2578`](https://github.com/polybar/polybar/pull/2578), [`#1265`](https://github.com/polybar/polybar/issues/1265))
[Unreleased]: https://github.com/polybar/polybar/compare/3.5.2...HEAD
## [3.5.7] - 2021-09-21 ## [3.5.7] - 2021-09-21
### Fixed ### Fixed
- The tray mistakenly removed tray icons that did not support XEMBED - The tray mistakenly removed tray icons that did not support XEMBED
@ -86,7 +238,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Empty color values are no longer treated as invalid and no longer produce an error. - Empty color values are no longer treated as invalid and no longer produce an error.
[Unreleased]: https://github.com/polybar/polybar/compare/3.5.7...HEAD [Unreleased]: https://github.com/polybar/polybar/compare/3.6.3...HEAD
[3.6.3]: https://github.com/polybar/polybar/releases/tag/3.6.3
[3.6.2]: https://github.com/polybar/polybar/releases/tag/3.6.2
[3.6.1]: https://github.com/polybar/polybar/releases/tag/3.6.1
[3.6.0]: https://github.com/polybar/polybar/releases/tag/3.6.0
[3.5.7]: https://github.com/polybar/polybar/releases/tag/3.5.7 [3.5.7]: https://github.com/polybar/polybar/releases/tag/3.5.7
[3.5.6]: https://github.com/polybar/polybar/releases/tag/3.5.6 [3.5.6]: https://github.com/polybar/polybar/releases/tag/3.5.6
[3.5.5]: https://github.com/polybar/polybar/releases/tag/3.5.5 [3.5.5]: https://github.com/polybar/polybar/releases/tag/3.5.5

View File

@ -1,25 +1,7 @@
# #
# Build configuration # Build configuration
# #
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) cmake_minimum_required(VERSION 3.5.0 FATAL_ERROR)
# Enable ccache by default and as early as possible because project() performs
# checks on the compiler
option(ENABLE_CCACHE "Enable ccache support" ON)
if(ENABLE_CCACHE)
message(STATUS "Trying to enable ccache")
find_program(BIN_CCACHE ccache)
string(ASCII 27 esc)
if(NOT BIN_CCACHE)
message(STATUS "${esc}[33mCouldn't locate ccache, disabling ccache...${esc}[0m")
else()
# Enable only if the binary is found
message(STATUS "${esc}[32mUsing compiler cache ${BIN_CCACHE}${esc}[0m")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${BIN_CCACHE})
endif()
endif()
project(polybar CXX) project(polybar CXX)
# Extract version information from version.txt. The first line that looks like # Extract version information from version.txt. The first line that looks like
@ -40,8 +22,7 @@ else()
set(APP_VERSION "${version_txt}") set(APP_VERSION "${version_txt}")
endif() endif()
set(CMAKE_MODULE_PATH list(APPEND CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/cmake
${PROJECT_SOURCE_DIR}/cmake/common ${PROJECT_SOURCE_DIR}/cmake/common
${PROJECT_SOURCE_DIR}/cmake/modules) ${PROJECT_SOURCE_DIR}/cmake/modules)
@ -50,18 +31,27 @@ include(GNUInstallDirs)
include(utils) include(utils)
include(01-core) include(01-core)
include(02-opts) include(02-opts)
include(03-libs)
include(04-targets) include(04-targets)
include(05-summary)
if(BUILD_DOC) if(BUILD_DOC)
add_subdirectory(doc) add_subdirectory(doc)
endif() endif()
add_subdirectory(contrib/bash)
add_subdirectory(contrib/zsh) if (BUILD_SHELL)
add_subdirectory(include) add_subdirectory(contrib/bash)
add_subdirectory(lib) add_subdirectory(contrib/zsh)
add_subdirectory(src bin) endif()
# Setup everything that uses a C++ compiler (polybar, polybar-msg, tests)
if(HAS_CXX_COMPILATION)
include(cxx)
if(BUILD_LIBPOLY)
include(libpoly)
add_subdirectory(lib)
endif()
add_subdirectory(include)
add_subdirectory(src bin)
endif()
# We need to enable testing in the root folder so that 'ctest' and 'make test' # We need to enable testing in the root folder so that 'ctest' and 'make test'
# can be run in the build directory # can be run in the build directory
@ -71,100 +61,10 @@ if(BUILD_TESTS)
endif() endif()
# if(BUILD_CONFIG)
# Generate configuration file install(FILES ${CMAKE_SOURCE_DIR}/doc/config.ini
# DESTINATION /etc/${PROJECT_NAME}
COMPONENT config)
set(MODULES_LEFT "bspwm i3 dwm")
set(MODULES_CENTER "mpd")
set(MODULES_RIGHT "filesystem xbacklight alsa pulseaudio xkeyboard memory cpu wlan eth battery temperature date powermenu")
set(FONT_FIXED "fixed:pixelsize=10")
set(FONT_UNIFONT "unifont:fontformat=truetype")
set(FONT_SIJI "siji:pixelsize=10")
queryfont(FONT_FIXED ${FONT_FIXED} FIELDS family pixelsize)
queryfont(FONT_UNIFONT ${FONT_UNIFONT} FIELDS family fontformat)
queryfont(FONT_SIJI ${FONT_SIJI} FIELDS family pixelsize)
# Strip disabled modules {{{
if(NOT ENABLE_PULSEAUDIO)
string(REPLACE " pulseaudio" "" MODULES_RIGHT ${MODULES_RIGHT})
endif()
if(NOT ENABLE_ALSA)
string(REPLACE " alsa" "" MODULES_RIGHT ${MODULES_RIGHT})
endif()
if(NOT ENABLE_I3)
string(REPLACE " i3" "" MODULES_LEFT ${MODULES_LEFT})
endif()
if(NOT ENABLE_DWM)
string(REPLACE " dwm" "" MODULES_LEFT ${MODULES_LEFT})
endif()
if(NOT ENABLE_MPD)
string(REPLACE "mpd" "" MODULES_CENTER ${MODULES_CENTER})
endif()
if(NOT ENABLE_NETWORK)
string(REPLACE " wlan eth" "" MODULES_RIGHT ${MODULES_RIGHT})
endif()
if(NOT WITH_XRANDR)
string(REPLACE "xbacklight " "backlight-acpi " MODULES_RIGHT ${MODULES_RIGHT})
endif()
if(NOT WITH_XKB)
string(REPLACE "xkeyboard " "" MODULES_RIGHT ${MODULES_RIGHT})
endif() endif()
# }}} include(05-summary)
# Get battery/adapter name {{{
string(REGEX REPLACE /%battery%.* "" PATH_BAT ${SETTING_PATH_BATTERY})
string(REGEX REPLACE /%adapter%.* "" PATH_ADP ${SETTING_PATH_ADAPTER})
file(GLOB BAT_LIST RELATIVE ${PATH_BAT} ${PATH_ADP}/B*)
file(GLOB ADP_LIST RELATIVE ${PATH_ADP} ${PATH_ADP}/A*)
if(BAT_LIST)
list(GET BAT_LIST 0 BATTERY)
else()
set(BATTERY BAT0)
endif()
if(ADP_LIST)
list(GET ADP_LIST 0 ADAPTER)
else()
set(ADAPTER ADP1)
endif()
# }}}
# Get network interfaces {{{
if(ENABLE_NETWORK)
file(GLOB IFLIST RELATIVE /sys/class/net /sys/class/net/*)
foreach(INTERFACE ${IFLIST})
if(NOT ${INTERFACE} STREQUAL "lo")
file(GLOB IS_WIRELESS /sys/class/net/${INTERFACE}/wireless)
if(IS_WIRELESS)
set(INTERFACE_WLAN ${INTERFACE})
else()
set(INTERFACE_ETH ${INTERFACE})
endif()
endif()
endforeach()
if(NOT INTERFACE_ETH)
set(INTERFACE_ETH net0)
endif()
if(NOT INTERFACE_WLAN)
set(INTERFACE_WLAN net1)
endif()
endif()
# }}}
# Configure and install {{{
configure_file(
${CMAKE_CURRENT_LIST_DIR}/config.cmake
${CMAKE_CURRENT_LIST_DIR}/config
ESCAPE_QUOTES @ONLY)
install(FILES config
DESTINATION ${CMAKE_INSTALL_DOCDIR}
COMPONENT config)
# }}}

View File

@ -10,11 +10,12 @@ are awesome! :tada:
+ [Changelog](#changelog) + [Changelog](#changelog)
+ [Documentation](#documentation) + [Documentation](#documentation)
+ [Style](#style) + [Style](#style)
* [Donations](#donations)
## Bug Reports ## Bug Reports
Bugs should be reported at the polybar issue tracker, using the [bug report Bugs should be reported at the polybar issue tracker, using the [bug report
template](https://github.com/polybar/polybar/issues/new?template=bug_report.md). template](https://github.com/polybar/polybar/issues/new?template=bug_report.yml).
Make sure you fill out all the required sections. Make sure you fill out all the required sections.
Before opening a bug report, please search our [issue Before opening a bug report, please search our [issue
@ -58,6 +59,7 @@ unless someone else has already claimed them:
* [confirmed](https://github.com/polybar/polybar/labels/confirmed) * [confirmed](https://github.com/polybar/polybar/labels/confirmed)
* [good first issue](https://github.com/polybar/polybar/labels/good%20first%20issue) * [good first issue](https://github.com/polybar/polybar/labels/good%20first%20issue)
* [help wanted](https://github.com/polybar/polybar/labels/help%20wanted) * [help wanted](https://github.com/polybar/polybar/labels/help%20wanted)
* [hacktoberfest](https://github.com/polybar/polybar/labels/Hacktoberfest) (can also be worked on outside of October :wink:)
For anything else, it's a good idea to first comment under the issue to ask For anything else, it's a good idea to first comment under the issue to ask
whether it is something that can/should be worked on right now. whether it is something that can/should be worked on right now.
@ -103,22 +105,31 @@ and some things may be harder/impossible to test right now.
### Changelog ### Changelog
If your PR introduces notable changes to polybar, please add them to the top of We use the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format for
the `Unreleased` section in the `CHANGELOG.md` file at the root of this keeping track of changes in a release.
repository.
If your PR introduces notable changes to polybar, please add them the correct
subsection in the `Unreleased` section in the `CHANGELOG.md` file at the root
of this repository.
Notable changes are any user-visible changes, like bug fixes, new config Notable changes are any user-visible changes, like bug fixes, new config
options, changes to the build, etc., but not, for example, code cleanup that options, changes to the build, etc., but not, for example, code cleanup that
doesn't change polybar's behavior or minor documentation changes. doesn't change polybar's behavior or minor documentation changes.
One thing that also should not be added to the changelog are bugfixes for One thing that also should not be added to the changelog are bugfixes for
unreleased features. unreleased features.
Also add a reference to all issues that this PR addresses in parentheses behind An entry in the changelog should include a link to the issue(s) that the PR
the changelog entry: addresses, to the PR itself, and to your username:
``` ```
[`#1234`](https://github.com/polybar/polybar/issues/1234) - A short description of the change
([`#XYZ`](https://github.com/polybar/polybar/issues/XYZ),
[`#UVW`](https://github.com/polybar/polybar/pull/UVW))
by [@yourname](https://github.com/yourname).
``` ```
You will first need to open the PR before you can link to it though :wink:.
If you are unsure whether something is a notable change, just add it to the If you are unsure whether something is a notable change, just add it to the
changelog and we can determine whether it is a notable change when reviewing. changelog and we can determine whether it is a notable change when reviewing.
@ -143,3 +154,13 @@ repo.
### Style ### Style
Please read our [style guide](https://github.com/polybar/polybar/wiki/Style-Guide). Please read our [style guide](https://github.com/polybar/polybar/wiki/Style-Guide).
## Donations
Donations support the sustained development of polybar.
We accept donations through [our open collective page](
https://opencollective.com/polybar).
This can be either a one time or a recurring donation.
Our [blog post](https://polybar.github.io/2020/12/21/Polybar-Funding.html) lays
out the why and how behind our decision to accept donations.

435
README.md
View File

@ -1,228 +1,229 @@
# polybar-dwm-module <p align="center">
![DWM <img src="banner.png" alt="Polybar">
Module](https://github.com/mihirlad55/polybar-dwm-module/blob/master/dwm-module.png) </p>
**polybar-dwm-module** is a fork of <p align="center">
[polybar](https://github.com/polybar/polybar) which implements a dwm module. A fast and easy-to-use tool for creating status bars.
</p>
<p align="center">
<a href="https://github.com/polybar/polybar/releases"><img src="https://img.shields.io/github/release/polybar/polybar.svg"></a>
<a href="https://github.com/polybar/polybar/releases"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/polybar/polybar/total" /></a>
<a href="https://github.com/polybar/polybar/actions?query=workflow%3ACI"><img src="https://github.com/polybar/polybar/workflows/CI/badge.svg"></a>
<a href="https://github.com/polybar/polybar/actions?query=workflow%3A%22Release+Workflow%22"><img src="https://github.com/polybar/polybar/workflows/Release%20Workflow/badge.svg?branch=master"></a>
<a href="https://polybar.readthedocs.io"><img src="https://readthedocs.org/projects/polybar/badge/?version=latest"></a>
<a href="https://gitter.im/polybar/polybar"><img src="https://badges.gitter.im/polybar/polybar.svg"></a>
<a href="https://codecov.io/gh/polybar/polybar/branch/master"><img src="https://codecov.io/gh/polybar/polybar/branch/master/graph/badge.svg"></a>
<a href="https://github.com/polybar/polybar/blob/master/LICENSE"><img src="https://img.shields.io/github/license/polybar/polybar.svg"></a>
<a href="https://www.codetriage.com/polybar/polybar"><img src="https://www.codetriage.com/polybar/polybar/badges/users.svg"></a>
<a href="https://opencollective.com/polybar"><img src="https://opencollective.com/polybar/tiers/badge.svg"></a>
</p>
**[Documentation](https://github.com/polybar/polybar/wiki/) | [Installation](#installation) | [Support](SUPPORT.md) | [Donate](#donations)**
**Polybar** aims to help users build beautiful and highly customizable status bars
for their desktop environment, without the need of having a black belt in shell scripting.
![default configuration screenshot](doc/_static/default.png)
## Table of Contents
* [Introduction](#introduction)
* [Getting Help](#getting-help)
* [Contributing](#contributing)
* [Getting started](#getting-started)
* [Installation](#installation)
* [First Steps](#first-steps)
* [Community](#community)
* [Contributors](#contributors)
* [Donations](#donations)
* [Sponsors](#sponsors)
* [Backers](#backers)
* [License](#license)
## Introduction
The main purpose of **Polybar** is to help users create awesome status bars.
It has built-in functionality to display information about the most commonly used services.
Some of the services included so far:
- Systray icons
- Window title
- Playback controls and status display for [MPD](https://www.musicpd.org/) using [libmpdclient](https://www.musicpd.org/libs/libmpdclient/)
- [ALSA](https://www.alsa-project.org/main/index.php/Main_Page) and [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/) volume controls
- Workspace and desktop panel for [bspwm](https://github.com/baskerville/bspwm) and [i3](https://github.com/i3/i3) and [dwm](https://dwm.suckless.org)
- Workspace module for [EWMH compliant](https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130320786080) window managers
- Keyboard layout and indicator status
- CPU and memory load indicator
- Battery display
- Network connection details
- Backlight level
- Date and time label
- Time-based shell script execution
- Command output tailing
- User-defined menu tree
- Inter-process messaging
- And more...
[See the wiki for more details](https://github.com/polybar/polybar/wiki).
## Getting Help
If you find yourself stuck, have a look at our [Support](SUPPORT.md) page for resources where you can find help.
## Contributing
Read our [contributing guidelines](CONTRIBUTING.md) for how to get started with contributing to polybar.
## Getting started
### Installation
<a href="https://repology.org/metapackage/polybar">
<img src="https://repology.org/badge/vertical-allrepos/polybar.svg" alt="Packaging status" align="right">
</a>
Polybar is already available in the package manager for many repositories.
We list some of the more prominent ones here.
Also click the [image on the
right](https://repology.org/project/polybar/versions) to see a more complete
list of available polybar packages.
If you are using **Debian** (bullseye/11/stable) or later, you can install [polybar](https://tracker.debian.org/pkg/polybar)
using `sudo apt install polybar`. Newer releases of polybar are sometimes provided in the [backports](https://wiki.debian.org/Backports)
repository for stable users, you need to enable [backports](https://wiki.debian.org/Backports) and then install using
`sudo apt -t buster-backports install polybar`.
If you are using **Ubuntu** 20.10 (Groovy Gorilla) or later, you can install polybar
using `sudo apt install polybar`.
If you are using **Arch Linux**, you can install the AUR package
[polybar](https://aur.archlinux.org/packages/polybar/) to get the latest
version, or [polybar-git](https://aur.archlinux.org/packages/polybar-git/) for
the most up-to-date (unstable) changes.
If you are using **Void Linux**, you can install [polybar](https://github.com/void-linux/void-packages/blob/master/srcpkgs/polybar/template) using `xbps-install -S polybar`.
If you are using **NixOS**, polybar is available in both the stable and unstable channels and can be installed with the command `nix-env -iA nixos.polybar`.
If you are using **Slackware**, polybar is available from the [SlackBuilds](https://slackbuilds.org/repository/14.2/desktop/polybar/) repository.
If you are using **Source Mage GNU/Linux**, polybar spell is available in test grimoire and can be installed via `cast polybar`.
If you are using **openSUSE Tumbleweed**, polybar is available from the
[official
repositories](https://build.opensuse.org/package/show/openSUSE%3AFactory/polybar)
and can be installed via `zypper install polybar`.
If you are using **openSUSE Leap**, polybar is available from
[OBS](https://build.opensuse.org/package/show/X11:Utilities/polybar/).
The package is available for openSUSE Leap 15.1 and above.
If you are using **FreeBSD**, [polybar](https://svnweb.freebsd.org/ports/head/x11/polybar/) can be installed using `pkg install polybar`. Make sure you are using the `latest` package branch.
If you are using **Gentoo**, both release and git-master versions are available in the [main](https://packages.gentoo.org/packages/x11-misc/polybar) repository.
If you are using **Fedora**, you can install [polybar](https://src.fedoraproject.org/rpms/polybar) using `sudo dnf install polybar`.
If you can't find your distro here, you will have to [build from source](https://github.com/polybar/polybar/wiki/Compiling).
### First Steps
[See the wiki for details on how to run and configure polybar](https://github.com/polybar/polybar/wiki).
## Community
Want to get in touch?
* Join our Gitter room at [gitter.im/polybar/polybar](https://gitter.im/polybar/polybar)
* We have our own subreddit at [r/polybar](https://www.reddit.com/r/polybar).
* Chat with us in the `#polybar` IRC channel on the [`irc.libera.chat:6697`](https://libera.chat/) server.
## Contributors
### Owner
* Michael Carlberg [**@jaagr**](https://github.com/jaagr/)
### Maintainers
* [**@NBonaparte**](https://github.com/NBonaparte)
* Chase Geigle [**@skystrife**](https://github.com/skystrife)
* Patrick Ziegler [**@patrick96**](https://github.com/patrick96)
### Logo Design by
* [**@Tobaloidee**](https://github.com/Tobaloidee)
## Requirements ### [All Contributors](https://github.com/polybar/polybar/graphs/contributors)
* dwm with the [IPC patch](https://github.com/mihirlad55/dwm-ipc) applied
* [dwmipcpp](https://github.com/mihirlad55/dwmipcpp) C++ client library for
communicating with dwm (included as a submodule).
* [jsoncpp](https://github.com/open-source-parsers/jsoncpp) for polybar and
dwmipcpp (required by module).
The [dwm-anybar patch](https://github.com/mihirlad55/dwm-anybar) is optionally ## Donations
recommended for a better experience. This patch allows dwm to manage polybar and
fixes some weird quirks that you may experience without it.
Polybar accepts donations through [open collective](https://opencollective.com/polybar).
## The DWM Module [Become a backer](https://opencollective.com/polybar) and support polybar!
The dwm module currently supports the following: ### Sponsors
- Labels:
* Display dwm tags
- Separator label between tags
* Display the current layout
* Display the currently focused window title (per monitor)
* Display label when focused window is floating
- Click Handlers:
* Tags:
- Left-click tag to view tag
- Right-click tag to toggle view on tag
- Scroll tags to view different tags (with wrapping, reverse scroll, and
empty tag scroll)
* Layout:
- Left-click to set `secondary-layout` (specified in config)
- Right-click to set previous layout
- Scroll to cycle through layouts (with wrapping and reverse scroll)
- Different formatting for different tag states:
* Focused: selected tag on selected monitor
* Unfocused: selected tag on unselected monitor
* Visible: unselected, but occupied tag on any monitor
* Urgent: Tag with window that has the urgent hint set
* Empty: Unselected and unoccupied tags
- The combined power of polybar
<a href="https://opencollective.com/polybar/sponsor/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/0/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/1/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/2/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/3/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/4/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/5/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/6/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/7/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/7/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/8/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/8/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/9/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/9/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/10/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/10/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/11/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/11/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/12/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/12/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/13/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/13/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/14/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/14/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/15/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/15/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/16/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/16/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/17/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/17/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/18/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/18/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/19/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/19/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/20/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/20/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/21/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/21/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/22/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/22/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/23/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/23/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/24/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/24/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/25/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/25/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/26/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/26/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/27/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/27/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/28/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/28/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/sponsor/29/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/sponsor/29/avatar.svg?requireActive=false"></a>
## How to Install ### Backers
First, apply all the patches you want on dwm, saving the IPC patch for last.
Optionally, apply the [dwm-anybar
patch](https://github.com/mihirlad55/dwm-anybar) and make sure your `config.h`
contains the following
```
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const int usealtbar = 1; /* 1 means use non-dwm status bar */
static const char *altbarclass = "Polybar"; /* Alternate bar class name */
static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */
```
If your polybar is to be displayed on the bottom of the monitor, set `topbar`
to `0`.
Next, apply the [IPC patch](https://github.com/mihirlad55/dwm-ipc). There will
likely be merge conflicts. The IPC patch is mostly additive, so in most conflict
cases, you will be keeping both changes.
After applying all your patches, make sure you compile and install dwm
```
$ sudo make install
```
Make sure you have `jsoncpp` installed, and any other requirements from
[polybar](https://github.com/polybar/polybar).
Arch linux users can install the
[`polybar-dwm-module`](https://aur.archlinux.org/packages/polybar-dwm-module/)
package from the AUR.
Otherwise you can clone, make, and install polybar yourself. Follow the on
screen prompts in the `build.sh` script and enable any additional features you
want.
```
$ git clone https://github.com/mihirlad55/polybar-dwm-module
$ cd polybar-dwm-module
$ ./build.sh -d
```
Configure the bar! You can view `/usr/share/doc/polybar/config` for a sample config that
includes the supported settings for the dwm module.
**IF YOU APPLIED THE ANYBAR PATCH**, make sure you have
`override-redirect = false` in your polybar config.
**IF YOU DID NOT APPLY THE ANYBAR PATCH**, make sure you have
`override-redirect = true` in your polybar config. You will have to set the bar
height in your dwm's `config.h` to match polybar's height and make sure
`showbar` is set to `1` in your `config.h`. Also make sure `topbar` is set to
the correct value based on if your polybar is a bottom/top bar.
## Launching Polybar
There are multiple ways to launch polybar. Whatever way you decide to use, make
sure polybar launches a few seconds after dwm, else dwm's socket will not be
initialized and the module will fail:
### Anybar Method
The `altbarcmd` variable can be set to the bar launch script. When you apply the
anybar patch, make sure `spawnbar()` occurs in the `setup()` function after
`setupepoll()` and this will ensure that the bar is launched after dwm is ready.
Also make sure that the script checks for running bars before launching more,
else if dwm is restarted, duplicate bars will be launched.
### Hacky Delay Method
In your `.xsession` script or whatever script launches at startup, add something
like the following:
```
$(sleep 4s && "$HOME/launch-polybar.sh") &
```
This will start your polybar script after a 4 second delay which should give dwm
enough time to initialize before polybar tries to connect to dwm. If this
doesn't work, try a longer delay.
### Autostart Method
Apply the [autostart patch](https://dwm.suckless.org/patches/autostart/). In
your `autostart_blocking.sh`, add your command to launch polybar.
## Sample Module Configuration
```ini
...
modules-left = ... dwm ...
...
[module/dwm]
type = internal/dwm
format = <label-tags> <label-layout> <label-floating> <label-title>
; Path to dwm socket (default: /tmp/dwm.sock)
; socket-path = /tmp/dwm.sock
; Left-click to view tag, right-click to toggle tag view
enable-tags-click = false
; Scroll to cycle between available tags
enable-tags-scroll = false
; If true and enable-tags-scroll = true, scrolling will view all tags regardless if occupied
tags-scroll-empty = false
; If true and enable-tags-scroll = true, scrolling will cycle through tags backwards
tags-scroll-reverse = false
; If true and enable-tags-scroll = true, wrap active tag when scrolling
tags-scroll-wrap = false
; Left-click to set secondary layout, right-click to switch to previous layout
enable-layout-click = false
; Scroll to cycle between available layouts
enable-layout-scroll = false
; Wrap when scrolling and reaching beginning/end of layouts
layout-scroll-wrap = false
; Reverse scroll direction
layout-scroll-reverse = false
; If enable-layout-click = true, clicking the layout symbol will switch to this layout
secondary-layout-symbol = [M]
; Separator in between shown tags
; label-separator = |
; Title of currently focused window
; Available tokens:
; %title%
label-title = %title%
label-title-padding = 2
label-title-foreground = ${colors.primary}
label-title-maxlen = 30
; Defaults to 'Desktop'
label-title-default = "Desktop"
; Symbol of current layout
; Available tokens:
; %symbol%
label-layout = %symbol%
label-layout-padding = 2
label-layout-foreground = #000
label-layout-background = ${colors.primary}
; Text to show when currently focused window is floating
label-floating = F
; States: focused, unfocused, visible, urgent, empty
; Available tokens:
; %name%
; focused = Selected tag on focused monitor
label-focused = %name%
label-focused-background = ${colors.background-alt}
label-focused-underline= ${colors.primary}
label-focused-padding = 2
; unfocused = Unselected tag on unselected monitor
label-unfocused = %name%
label-unfocused-padding = 2
; visible = Unselected tag, but occupied tag on any monitor
label-visible = %name%
label-visible-background = ${self.label-focused-background}
label-visible-underline = ${self.label-focused-underline}
label-visible-padding = ${self.label-focused-padding}
; urgent = Unselected tag with window that has urgency hint set
label-urgent = %name%
label-urgent-background = ${colors.alert}
label-urgent-padding = 2
; empty = Unselected and unoccupied tag
; This can be set to an empty string to hide empty tags
label-empty = %name%
label-empty-background = ${colors.primary}
label-empty-padding = 2
```
You can also take a look at my
[personal](https://github.com/mihirlad55/dotfiles/blob/arch-dwm/.config/polybar/config#L99)
bar configuration which is more representative of the screenshot above.
<a href="https://opencollective.com/polybar/backer/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/0/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/1/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/2/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/3/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/4/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/5/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/6/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/7/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/7/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/8/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/8/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/9/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/9/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/10/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/10/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/11/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/11/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/12/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/12/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/13/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/13/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/14/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/14/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/15/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/15/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/16/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/16/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/17/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/17/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/18/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/18/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/19/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/19/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/20/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/20/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/21/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/21/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/22/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/22/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/23/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/23/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/24/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/24/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/25/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/25/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/26/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/26/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/27/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/27/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/28/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/28/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/polybar/backer/29/website?requireActive=false" target="_blank"><img src="https://opencollective.com/polybar/backer/29/avatar.svg?requireActive=false"></a>
## License ## License
Polybar is licensed under the MIT license. [See LICENSE for more
information](https://github.com/polybar/polybar/blob/master/LICENSE). Polybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/polybar/polybar/blob/master/LICENSE).

View File

@ -8,7 +8,7 @@ If you need help or troubleshooting tips or just have a question:
* Read the [Wiki page](https://github.com/polybar/polybar/wiki) for the thing you have problems with. * Read the [Wiki page](https://github.com/polybar/polybar/wiki) for the thing you have problems with.
* Join our Gitter room at [gitter.im/polybar/polybar](https://gitter.im/polybar/polybar) * Join our Gitter room at [gitter.im/polybar/polybar](https://gitter.im/polybar/polybar)
* Ask in our reddit community at [r/polybar](https://www.reddit.com/r/polybar) * Ask in our reddit community at [r/polybar](https://www.reddit.com/r/polybar)
* Join the official IRC channel `#polybar` on the `chat.freenode.net` network. If you don't get an answer try asking on [Gitter](https://gitter.im/polybar/polybar). * Join the official IRC channel `#polybar` on the [`irc.libera.chat:6697`](https://libera.chat/) network. If you don't get an answer try asking on [Gitter](https://gitter.im/polybar/polybar).
* Ask on [Unix & Linux StackExchange](https://unix.stackexchange.com/). Though not all questions may be suited over there, make sure you're [on topic](https://unix.stackexchange.com/help/on-topic). * Ask on [Unix & Linux StackExchange](https://unix.stackexchange.com/). Though not all questions may be suited over there, make sure you're [on topic](https://unix.stackexchange.com/help/on-topic).
Please **do not** use the github issue tracker to ask for help or if you have a question, it is meant for bug reports and feature requests. Issues will be closed and you will be referred to the above resources. Please **do not** use the github issue tracker to ask for help or if you have a question, it is meant for bug reports and feature requests. Issues will be closed and you will be referred to the above resources.

View File

@ -48,8 +48,6 @@ usage() {
Remove existing build dir; disabled by default. Remove existing build dir; disabled by default.
${COLORS[GREEN]}-I, --no-install${COLORS[OFF]} ${COLORS[GREEN]}-I, --no-install${COLORS[OFF]}
Do not execute 'sudo make install'; enabled by default. Do not execute 'sudo make install'; enabled by default.
${COLORS[GREEN]}-C, --install-config${COLORS[OFF]}
Install example configuration; disabled by default.
${COLORS[GREEN]}-A, --auto${COLORS[OFF]} ${COLORS[GREEN]}-A, --auto${COLORS[OFF]}
Automatic, non-interactive installation; disabled by default. Automatic, non-interactive installation; disabled by default.
When set, script defaults options not explicitly set. When set, script defaults options not explicitly set.
@ -72,7 +70,6 @@ install() {
if [[ "$AUTO" == ON ]]; then if [[ "$AUTO" == ON ]]; then
[[ -z "$INSTALL" ]] && INSTALL="ON" [[ -z "$INSTALL" ]] && INSTALL="ON"
[[ -z "$INSTALL_CONF" ]] && INSTALL_CONF="OFF"
fi fi
if [[ -z "$INSTALL" ]]; then if [[ -z "$INSTALL" ]]; then
@ -80,19 +77,9 @@ install() {
[[ "${p^^}" != "N" ]] && INSTALL="ON" || INSTALL="OFF" [[ "${p^^}" != "N" ]] && INSTALL="ON" || INSTALL="OFF"
fi fi
if [[ -z "$INSTALL_CONF" ]]; then
read -r -p "$(msg "Install example configuration? [y/N]: ")" -n 1 p && echo
[[ "${p^^}" != "Y" ]] && INSTALL_CONF="OFF" || INSTALL_CONF="ON"
fi
if [[ "$INSTALL" == ON ]]; then if [[ "$INSTALL" == ON ]]; then
sudo make install || msg_err "Failed to install executables..." sudo make install || msg_err "Failed to install executables..."
fi fi
if [[ "$INSTALL_CONF" == ON ]]; then
make userconfig || msg_err "Failed to install user configuration..."
fi
} }
set_build_opts() { set_build_opts() {
@ -159,8 +146,8 @@ set_build_opts() {
fi fi
if [[ -z "$JOB_COUNT" ]]; then if [[ -z "$JOB_COUNT" ]]; then
read -r -p "$(msg "Parallelize the build using make -j$(nproc) --------------------------- [y/N]: ")" -n 1 p && echo read -r -p "$(msg "Parallelize the build using make -j$(nproc) --------------------------- [y/N]: ")" -n 1 p && echo
[[ "${p^^}" != "Y" ]] && JOB_COUNT=1 || JOB_COUNT=$(nproc) [[ "${p^^}" != "Y" ]] && JOB_COUNT=1 || JOB_COUNT=$(nproc)
fi fi
@ -209,14 +196,14 @@ main() {
-DENABLE_MPD:BOOL="${ENABLE_MPD}" \ -DENABLE_MPD:BOOL="${ENABLE_MPD}" \
-DENABLE_NETWORK:BOOL="${ENABLE_NETWORK}" \ -DENABLE_NETWORK:BOOL="${ENABLE_NETWORK}" \
-DENABLE_CURL:BOOL="${ENABLE_CURL}" \ -DENABLE_CURL:BOOL="${ENABLE_CURL}" \
-DBUILD_IPC_MSG:BOOL="${ENABLE_IPC_MSG}" \ -DBUILD_POLYBAR_MSG:BOOL="${ENABLE_IPC_MSG}" \
.. || msg_err "Failed to generate build... read output to get a hint of what went wrong" .. || msg_err "Failed to generate build... read output to get a hint of what went wrong"
msg "Building project" msg "Building project"
if [ -z ${JOB_COUNT} ]; then if [ -z ${JOB_COUNT} ]; then
make || msg_err "Failed to build project" make || msg_err "Failed to build project"
else else
make -j$JOB_COUNT || msg_err "Failed to build project" make -j$JOB_COUNT || msg_err "Failed to build project"
fi fi
install install
msg "Build complete!" msg "Build complete!"
@ -260,13 +247,11 @@ while [[ "$1" == -* ]]; do
-g|--gcc) -g|--gcc)
USE_GCC=ON; shift ;; USE_GCC=ON; shift ;;
-j|--jobs) -j|--jobs)
JOB_COUNT=$(nproc); shift ;; JOB_COUNT=$(nproc); shift ;;
-f) -f)
REMOVE_BUILD_DIR=ON; shift ;; REMOVE_BUILD_DIR=ON; shift ;;
-I|--no-install) -I|--no-install)
INSTALL=OFF; shift ;; INSTALL=OFF; shift ;;
-C|--install-config)
INSTALL_CONF=ON; shift ;;
-A|--auto) -A|--auto)
AUTO=ON; shift ;; AUTO=ON; shift ;;
-h|--help) -h|--help)

View File

@ -1,12 +1,38 @@
# #
# Core setup # Core setup
# #
option(DISABLE_ALL "Set this to ON disable all targets. Individual targets can be enabled explicitly." OFF)
set(CMAKE_CXX_STANDARD 14) # If all targets are disabled, we set the default value for options that are on
set(CMAKE_CXX_STANDARD_REQUIRED ON) # by default to OFF
set(CMAKE_CXX_EXTENSIONS OFF) if (DISABLE_ALL)
set(DEFAULT_ON OFF)
else()
set(DEFAULT_ON ON)
endif()
set(THREADS_PREFER_PTHREAD_FLAG ON) option(BUILD_POLYBAR "Build the main polybar executable" ${DEFAULT_ON})
option(BUILD_POLYBAR_MSG "Build polybar-msg" ${DEFAULT_ON})
option(BUILD_TESTS "Build testsuite" OFF)
option(BUILD_DOC "Build documentation" ${DEFAULT_ON})
option(BUILD_CONFIG "Generate default configuration" ${DEFAULT_ON})
option(BUILD_SHELL "Generate shell completion files" ${DEFAULT_ON})
include(CMakeDependentOption)
CMAKE_DEPENDENT_OPTION(BUILD_DOC_HTML "Build HTML documentation" ON "BUILD_DOC" OFF)
CMAKE_DEPENDENT_OPTION(BUILD_DOC_MAN "Build manpages" ON "BUILD_DOC" OFF)
if (BUILD_POLYBAR OR BUILD_TESTS OR BUILD_POLYBAR_MSG)
set(BUILD_LIBPOLY ON)
else()
set(BUILD_LIBPOLY OFF)
endif()
if (BUILD_POLYBAR OR BUILD_POLYBAR_MSG OR BUILD_TESTS)
set(HAS_CXX_COMPILATION ON)
else()
set(HAS_CXX_COMPILATION OFF)
endif()
# Export compile commands used for custom targets # Export compile commands used for custom targets
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -17,77 +43,3 @@ if(NOT CMAKE_BUILD_TYPE)
message_colored(STATUS "No build type specified; using ${CMAKE_BUILD_TYPE}" 33) message_colored(STATUS "No build type specified; using ${CMAKE_BUILD_TYPE}" 33)
endif() endif()
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER) string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
# Compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
# Need dprintf() for FreeBSD 11.1 and older
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WITH_DPRINTF")
# libinotify uses c99 extension, so suppress this error
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c99-extensions")
# Ensures that libraries from dependencies in LOCALBASE are used
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
endif()
if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=parentheses-equality")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-zero-length-array")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g2")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -fdata-sections -ffunction-sections")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -Wl,--gc-sections,--icf=safe")
endif()
# Check compiler
if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.4.0")
message_colored(FATAL_ERROR "Compiler not supported (Requires clang-3.4+ or gcc-5.1+)" 31)
else()
message_colored(STATUS "Using supported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 32)
endif()
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1.0")
message_colored(FATAL_ERROR "Compiler not supported (Requires clang-3.4+ or gcc-5.1+)" 31)
else()
message_colored(STATUS "Using supported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 32)
endif()
else()
message_colored(WARNING "Using unsupported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION} !" 31)
endif()
# Set compiler and linker flags for preferred C++ library
if(CXXLIB_CLANG)
message_colored(STATUS "Linking against libc++" 32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lc++ -lc++abi")
elseif(CXXLIB_GCC)
message_colored(STATUS "Linking against libstdc++" 32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++")
endif()
# Custom build type ; SANITIZE
SET(CMAKE_CXX_FLAGS_SANITIZE "-O0 -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls"
CACHE STRING "Flags used by the C++ compiler during sanitize builds." FORCE)
SET(CMAKE_EXE_LINKER_FLAGS_SANITIZE ""
CACHE STRING "Flags used for linking binaries during sanitize builds." FORCE)
SET(CMAKE_SHARED_LINKER_FLAGS_SANITIZE ""
CACHE STRING "Flags used by the shared libraries linker during sanitize builds." FORCE)
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_SANITIZE
CMAKE_EXE_LINKER_FLAGS_SANITIZE
CMAKE_SHARED_LINKER_FLAGS_SANITIZE)
# Custom build type ; Coverage
SET(CMAKE_CXX_FLAGS_COVERAGE
"${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_COVERAGE} --coverage")
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${CMAKE_EXE_LINKER_FLAGS_COVERAGE}")
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${CMAKE_SHARED_LINKER_FLAGS_COVERAGE}")

View File

@ -1,64 +1,3 @@
#
# Build options
#
set(SPHINX_BUILD "sphinx-build" CACHE STRING "Name/Path of the sphinx-build executable to use.")
checklib(BUILD_DOC "binary" "${SPHINX_BUILD}")
checklib(ENABLE_ALSA "pkg-config" alsa)
checklib(ENABLE_CURL "pkg-config" libcurl)
checklib(ENABLE_I3 "binary" i3)
checklib(ENABLE_MPD "pkg-config" libmpdclient)
checklib(WITH_LIBNL "pkg-config" libnl-genl-3.0)
if(WITH_LIBNL)
checklib(ENABLE_NETWORK "pkg-config" libnl-genl-3.0)
set(WIRELESS_LIB "libnl")
else()
checklib(ENABLE_NETWORK "cmake" Libiw)
set(WIRELESS_LIB "wireless-tools")
endif()
checklib(ENABLE_PULSEAUDIO "pkg-config" libpulse)
checklib(WITH_XKB "pkg-config" xcb-xkb)
checklib(WITH_XRM "pkg-config" xcb-xrm)
checklib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12")
checklib(WITH_XCURSOR "pkg-config" "xcb-cursor")
if(NOT DEFINED ENABLE_CCACHE AND CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
set(ENABLE_CCACHE ON)
endif()
option(CXXLIB_CLANG "Link against libc++" OFF)
option(CXXLIB_GCC "Link against stdlibc++" OFF)
option(BUILD_IPC_MSG "Build ipc messager" ON)
option(BUILD_TESTS "Build testsuite" OFF)
option(BUILD_DOC "Build documentation" ON)
option(ENABLE_ALSA "Enable alsa support" ON)
option(ENABLE_CURL "Enable curl support" ON)
option(ENABLE_DWM "Enable dwm support" ON)
option(ENABLE_I3 "Enable i3 support" ON)
option(ENABLE_MPD "Enable mpd support" ON)
option(WITH_LIBNL "Use netlink interface for wireless" ON)
option(ENABLE_NETWORK "Enable network support" ON)
option(ENABLE_XKEYBOARD "Enable xkeyboard support" ON)
option(ENABLE_PULSEAUDIO "Enable PulseAudio support" ON)
option(WITH_XRANDR "xcb-randr support" ON)
option(WITH_XRANDR_MONITORS "xcb-randr monitor support" ON)
option(WITH_XCOMPOSITE "xcb-composite support" ON)
option(WITH_XKB "xcb-xkb support" ON)
option(WITH_XRM "xcb-xrm support" ON)
option(WITH_XCURSOR "xcb-cursor support" ON)
option(DEBUG_LOGGER "Trace logging" ON)
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
option(DEBUG_LOGGER_VERBOSE "Trace logging (verbose)" OFF)
option(DEBUG_HINTS "Debug clickable areas" OFF)
option(DEBUG_WHITESPACE "Debug whitespace" OFF)
option(DEBUG_FONTCONFIG "Debug fontconfig" OFF)
endif()
set(SETTING_ALSA_SOUNDCARD "default" set(SETTING_ALSA_SOUNDCARD "default"
CACHE STRING "Name of the ALSA soundcard driver") CACHE STRING "Name of the ALSA soundcard driver")
set(SETTING_BSPWM_SOCKET_PATH "/tmp/bspwm_0_0-socket" set(SETTING_BSPWM_SOCKET_PATH "/tmp/bspwm_0_0-socket"

View File

@ -1,30 +0,0 @@
#
# Check libraries
#
find_package(Threads REQUIRED)
list(APPEND libs ${CMAKE_THREAD_LIBS_INIT})
querylib(TRUE "pkg-config" cairo-fc libs dirs)
querylib(ENABLE_ALSA "pkg-config" alsa libs dirs)
querylib(ENABLE_CURL "pkg-config" libcurl libs dirs)
querylib(ENABLE_MPD "pkg-config" libmpdclient libs dirs)
if(WITH_LIBNL)
querylib(ENABLE_NETWORK "pkg-config" libnl-genl-3.0 libs dirs)
else()
querylib(ENABLE_NETWORK "cmake" Libiw libs dirs)
endif()
querylib(ENABLE_PULSEAUDIO "pkg-config" libpulse libs dirs)
querylib(WITH_XCOMPOSITE "pkg-config" xcb-composite libs dirs)
querylib(WITH_XKB "pkg-config" xcb-xkb libs dirs)
querylib(WITH_XRANDR "pkg-config" xcb-randr libs dirs)
querylib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12" libs dirs)
querylib(WITH_XRM "pkg-config" xcb-xrm libs dirs)
querylib(WITH_XCURSOR "pkg-config" xcb-cursor libs dirs)
# FreeBSD Support
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
querylib(TRUE "pkg-config" libinotify libs dirs)
endif()

View File

@ -2,18 +2,6 @@
# Custom targets # Custom targets
# #
# Target: userconfig {{{
configure_file(
${PROJECT_SOURCE_DIR}/cmake/templates/userconfig.cmake.in
${PROJECT_BINARY_DIR}/cmake/userconfig.cmake
ESCAPE_QUOTES @ONLY)
add_custom_target(userconfig
DEPENDS ${PROJECT_NAME}
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/cmake/userconfig.cmake)
# }}}
# Target: uninstall {{{ # Target: uninstall {{{
configure_file( configure_file(

View File

@ -1,12 +1,16 @@
# #
# Output build summary # Output build summary
# #
message(STATUS " Build:") message(STATUS " Build:")
message_colored(STATUS " Version: ${APP_VERSION}" "32;1") message_colored(STATUS " Version: ${APP_VERSION}" "32;1")
message_colored(STATUS " Type: ${CMAKE_BUILD_TYPE}" "37;2") message_colored(STATUS " Type: ${CMAKE_BUILD_TYPE}" "37;2")
message_colored(STATUS " CXX: ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}" "37;2") if (HAS_CXX_COMPILATION)
message_colored(STATUS " LD: ${CMAKE_LINKER} ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}" "37;2") message_colored(STATUS " CXX: ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} ${cxx_flags_str}" "37;2")
message_colored(STATUS " LD: ${CMAKE_LINKER} ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} ${cxx_linker_flags_str}" "37;2")
endif()
if (BUILD_DOC)
message_colored(STATUS " sphinx-build: ${BIN_SPHINX} ${SPHINX_FLAGS}" "37;2")
endif()
message(STATUS " Install Paths:") message(STATUS " Install Paths:")
message_colored(STATUS " PREFIX: ${CMAKE_INSTALL_PREFIX}" "32") message_colored(STATUS " PREFIX: ${CMAKE_INSTALL_PREFIX}" "32")
@ -16,35 +20,41 @@ message_colored(STATUS " DOCDIR: ${CMAKE_INSTALL_FULL_DOCDIR}" "32")
message_colored(STATUS " MANDIR: ${CMAKE_INSTALL_FULL_MANDIR}" "32") message_colored(STATUS " MANDIR: ${CMAKE_INSTALL_FULL_MANDIR}" "32")
message(STATUS " Targets:") message(STATUS " Targets:")
colored_option(" polybar-msg" BUILD_IPC_MSG) colored_option(" polybar" BUILD_POLYBAR)
colored_option(" polybar-msg" BUILD_POLYBAR_MSG)
colored_option(" testsuite" BUILD_TESTS) colored_option(" testsuite" BUILD_TESTS)
colored_option(" documentation" BUILD_DOC) colored_option(" documentation" BUILD_DOC)
colored_option(" html" BUILD_DOC_HTML)
colored_option(" man" BUILD_DOC_MAN)
colored_option(" default config" BUILD_CONFIG)
colored_option(" shell files" BUILD_SHELL)
message(STATUS " Module support:") if (BUILD_LIBPOLY)
colored_option(" alsa" ENABLE_ALSA) message(STATUS " Module support:")
colored_option(" curl" ENABLE_CURL) colored_option(" alsa" ENABLE_ALSA ALSA_VERSION)
colored_option(" dwm" ENABLE_DWM) colored_option(" curl" ENABLE_CURL CURL_VERSION)
colored_option(" i3" ENABLE_I3) colored_option(" dwm" ENABLE_DWM)
colored_option(" mpd" ENABLE_MPD) colored_option(" i3" ENABLE_I3)
colored_option(" network (${WIRELESS_LIB})" ENABLE_NETWORK) colored_option(" mpd" ENABLE_MPD MPD_VERSION)
colored_option(" pulseaudio" ENABLE_PULSEAUDIO) colored_option(" network (${WIRELESS_LIB})" ENABLE_NETWORK NETWORK_LIBRARY_VERSION)
colored_option(" xkeyboard" WITH_XKB) colored_option(" pulseaudio" ENABLE_PULSEAUDIO PULSEAUDIO_VERSION)
colored_option(" xkeyboard" WITH_XKB Xcb_XKB_VERSION)
message(STATUS " X extensions:") message(STATUS " X extensions:")
colored_option(" xcb-randr" WITH_XRANDR) colored_option(" xcb-randr" Xcb_RANDR_FOUND Xcb_RANDR_VERSION)
colored_option(" xcb-randr (monitor support)" WITH_XRANDR_MONITORS) colored_option(" xcb-randr (monitor support)" WITH_XRANDR_MONITORS Xcb_RANDR_VERSION)
colored_option(" xcb-composite" WITH_XCOMPOSITE) colored_option(" xcb-composite" Xcb_COMPOSITE_FOUND Xcb_COMPOSITE_VERSION)
colored_option(" xcb-xkb" WITH_XKB) colored_option(" xcb-xkb" WITH_XKB Xcb_XKB_VERSION)
colored_option(" xcb-xrm" WITH_XRM) colored_option(" xcb-xrm" WITH_XRM Xcb_XRM_VERSION)
colored_option(" xcb-cursor" WITH_XCURSOR) colored_option(" xcb-cursor" WITH_XCURSOR Xcb_CURSOR_VERSION)
message(STATUS " Log options:") message(STATUS " Log options:")
colored_option(" Trace logging" DEBUG_LOGGER) colored_option(" Trace logging" DEBUG_LOGGER)
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG) if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
message(STATUS " Debug options:") message(STATUS " Debug options:")
colored_option(" Trace logging (verbose)" DEBUG_LOGGER_VERBOSE) colored_option(" Trace logging (verbose)" DEBUG_LOGGER_VERBOSE)
colored_option(" Draw clickable areas" DEBUG_HINTS) colored_option(" Draw clickable areas" DEBUG_HINTS)
colored_option(" Print fc-match details" DEBUG_FONTCONFIG) colored_option(" Print fc-match details" DEBUG_FONTCONFIG)
colored_option(" Enable window shading" DEBUG_SHADED) endif()
endif() endif()

View File

@ -13,11 +13,8 @@ endfunction()
# colored_option {{{ # colored_option {{{
function(colored_option text flag) function(colored_option text flag)
# Append version of option, if ${flag}_VERSION is set if(ARGC GREATER 2 AND NOT "${${ARGV2}}" STREQUAL "")
set(version ${${flag}_VERSION}) set(text "${text} (${${ARGV2}})")
if(NOT "${version}" STREQUAL "")
set(text "${text} (${version})")
endif() endif()
if(${flag}) if(${flag})
@ -29,73 +26,58 @@ endfunction()
# }}} # }}}
# queryfont {{{ # find_package_impl {{{
function(queryfont output_variable fontname) # Uses PkgConfig to search for pkg_config_name
set(multi_value_args FIELDS) #
cmake_parse_arguments(ARG "" "" "${multi_value_args}" ${ARGN}) # Defines the following variables:
# ${find_pkg_name}_FOUND - True if the package has been found
# ${find_pkg_name}_INCLUDE_DIR - <...>_INCLUDE_DIRS exported by pkg_check_modules
# ${find_pkg_name}_INCLUDE_DIRS - Same as ${find_pkg_name}_INCLUDE_DIR
# ${find_pkg_name}_LIBRARY - <...>_LIBRARIES exported by pkg_check_modules
# ${find_pkg_name}_LIBRARIES - Same as ${find_pkg_name}_LIBRARY
# ${find_pkg_name}_VERSION - <...>_VERSION exported by pkg_check_modules
#
macro(find_package_impl pkg_config_name find_pkg_name header_to_find)
find_package(PkgConfig REQUIRED)
include(FindPackageHandleStandardArgs)
find_program(BIN_FCLIST fc-list) pkg_check_modules(PC_${find_pkg_name} REQUIRED ${pkg_config_name})
if(NOT BIN_FCLIST)
message_colored(WARNING "Failed to locate `fc-list`" "33;1") if (NOT ${header_to_find} STREQUAL "")
return() find_path(PC_${find_pkg_name}_INCLUDE_DIRS_
NAMES "${header_to_find}"
HINTS "${PC_${find_pkg_name}_INCLUDE_DIRS}"
)
set(PC_${find_pkg_name}_INCLUDE_DIRS ${PC_${find_pkg_name}_INCLUDE_DIRS_})
endif() endif()
string(REPLACE ";" " " FIELDS "${ARG_FIELDS}") set(${find_pkg_name}_INCLUDE_DIR ${PC_${find_pkg_name}_INCLUDE_DIRS})
if(NOT FIELDS) set(${find_pkg_name}_INCLUDE_DIRS ${${find_pkg_name}_INCLUDE_DIR})
set(FIELDS family) set(${find_pkg_name}_LIBRARY ${PC_${find_pkg_name}_LIBRARIES})
endif() set(${find_pkg_name}_VERSION ${PC_${find_pkg_name}_VERSION})
set(${find_pkg_name}_LIBRARIES ${${find_pkg_name}_LIBRARY})
execute_process( find_package_handle_standard_args(${find_pkg_name}
COMMAND sh -c "${BIN_FCLIST} : ${FIELDS}" REQUIRED_VARS
RESULT_VARIABLE status ${find_pkg_name}_INCLUDE_DIRS
OUTPUT_VARIABLE output ${find_pkg_name}_LIBRARIES
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) VERSION_VAR
STRING(REGEX REPLACE ";" "\\\\;" output "${output}") ${find_pkg_name}_VERSION
STRING(REGEX REPLACE "\n" ";" output "${output}") )
STRING(TOLOWER "${output}" output)
foreach(match LISTS ${output}) mark_as_advanced(${find_pkg_name}_INCLUDE_DIR ${find_pkg_name}_LIBRARY)
if(${match} MATCHES ".*${fontname}.*$") endmacro()
list(APPEND matches ${match})
endif()
endforeach()
if(matches)
list(GET matches 0 fst_match)
set(${output_variable} "${fst_match}" PARENT_SCOPE)
message(STATUS "Found font: ${fst_match}")
else()
message_colored(STATUS "Font not found: ${fontname}" "33;1")
endif()
endfunction()
# }}} # }}}
# querylib {{{ # create_imported_target {{{
function(create_imported_target library_name includes libraries)
function(querylib flag type pkg out_library out_include_dirs) add_library(${library_name} INTERFACE IMPORTED)
if(${flag}) set_target_properties(${library_name} PROPERTIES
if(${type} STREQUAL "cmake") INTERFACE_LINK_LIBRARIES "${libraries}"
find_package(${pkg} REQUIRED) INTERFACE_INCLUDE_DIRECTORIES "${includes}"
string(TOUPPER ${pkg} pkg_upper) )
list(APPEND ${out_library} ${${pkg_upper}_LIBRARY})
list(APPEND ${out_include_dirs} ${${pkg_upper}_INCLUDE_DIR})
elseif(${type} STREQUAL "pkg-config")
find_package(PkgConfig REQUIRED)
pkg_check_modules(PKG_${flag} REQUIRED ${pkg})
# Set packet version so that it can be used in the summary
set(${flag}_VERSION ${PKG_${flag}_VERSION} PARENT_SCOPE)
list(APPEND ${out_library} ${PKG_${flag}_LIBRARIES})
list(APPEND ${out_include_dirs} ${PKG_${flag}_INCLUDE_DIRS})
else()
message(FATAL_ERROR "Invalid lookup type '${type}'")
endif()
set(${out_library} ${${out_library}} PARENT_SCOPE)
set(${out_include_dirs} ${${out_include_dirs}} PARENT_SCOPE)
endif()
endfunction() endfunction()
# }}} # }}}
# checklib {{{ # checklib {{{
@ -114,7 +96,21 @@ function(checklib flag type pkg)
else() else()
message(FATAL_ERROR "Invalid lookup type '${type}'") message(FATAL_ERROR "Invalid lookup type '${type}'")
endif() endif()
mark_as_advanced(${flag})
endif() endif()
endfunction() endfunction()
function(get_include_dirs output)
get_filename_component(generated_sources_dir ${CMAKE_BINARY_DIR}/generated-sources ABSOLUTE)
get_filename_component(include_dir ${CMAKE_SOURCE_DIR}/include ABSOLUTE)
set(${output} ${include_dir} ${generated_sources_dir} PARENT_SCOPE)
endfunction()
function(get_sources_dirs output)
get_filename_component(src_dir ${CMAKE_SOURCE_DIR}/src ABSOLUTE)
set(${output} ${src_dir} PARENT_SCOPE)
endfunction()
# }}} # }}}

111
cmake/cxx.cmake Normal file
View File

@ -0,0 +1,111 @@
option(ENABLE_CCACHE "Enable ccache support" ON)
if(ENABLE_CCACHE)
find_program(BIN_CCACHE ccache)
mark_as_advanced(BIN_CCACHE)
if(NOT BIN_CCACHE)
message_colored(STATUS "Couldn't locate ccache, disabling ccache..." "33")
else()
# Enable only if the binary is found
message_colored(STATUS "Using compiler cache ${BIN_CCACHE}" "32")
set(CMAKE_CXX_COMPILER_LAUNCHER ${BIN_CCACHE} CACHE STRING "")
endif()
endif()
option(CXXLIB_CLANG "Link against libc++" OFF)
option(CXXLIB_GCC "Link against stdlibc++" OFF)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(THREADS_PREFER_PTHREAD_FLAG ON)
set(POLYBAR_FLAGS "" CACHE STRING "C++ compiler flags used for compiling polybar")
list(APPEND cxx_base -Wall -Wextra -Wpedantic)
list(APPEND cxx_debug -DDEBUG -g2)
list(APPEND cxx_minsizerel "")
list(APPEND cxx_sanitize -O0 -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls)
list(APPEND cxx_coverage --coverage)
list(APPEND cxx_linker_base "")
list(APPEND cxx_linker_minsizerel "")
# Compiler flags
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-Wsuggest-override" HAS_SUGGEST_OVERRIDE)
if (HAS_SUGGEST_OVERRIDE)
list(APPEND cxx_base -Wsuggest-override)
endif()
unset(HAS_SUGGEST_OVERRIDE)
if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
# Need dprintf() for FreeBSD 11.1 and older
# libinotify uses c99 extension, so suppress this error
list(APPEND cxx_base -D_WITH_DPRINTF -Wno-c99-extensions)
# Ensures that libraries from dependencies in LOCALBASE are used
list(APPEND cxx_linker_base -L/usr/local/lib)
endif()
# Check compiler
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
list(APPEND cxx_base -Wno-error=parentheses-equality -Wno-zero-length-array)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.4.0")
message_colored(FATAL_ERROR "Compiler not supported (Requires clang-3.4+ or gcc-5.1+)" 31)
else()
message_colored(STATUS "Using supported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 32)
endif()
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
list(APPEND cxx_minsizerel -fdata-sections -ffunction-sections -flto)
list(APPEND cxx_linker_minsizerel -Wl,--gc-sections)
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1.0")
message_colored(FATAL_ERROR "Compiler not supported (Requires clang-3.4+ or gcc-5.1+)" 31)
else()
message_colored(STATUS "Using supported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 32)
endif()
else()
message_colored(WARNING "Using unsupported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION} !" 31)
endif()
# Set compiler and linker flags for preferred C++ library
if(CXXLIB_CLANG)
message_colored(STATUS "Linking against libc++" 32)
list(APPEND cxx_base -stdlib=libc++)
list(APPEND cxx_linker_base -lc++ -lc++abi)
elseif(CXXLIB_GCC)
message_colored(STATUS "Linking against libstdc++" 32)
list(APPEND cxx_linker_base -lstdc++)
endif()
# Custom build type 'Coverage', inherits the debug flags
list(APPEND cxx_coverage ${cxx_debug} ${cxx_coverage})
SET(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_COVERAGE}")
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${CMAKE_EXE_LINKER_FLAGS_COVERAGE}")
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${CMAKE_SHARED_LINKER_FLAGS_COVERAGE}")
list(APPEND cxx_flags ${cxx_base})
list(APPEND cxx_linker_flags ${cxx_linker_base})
if (CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG")
list(APPEND cxx_flags ${cxx_debug})
elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "MINSIZEREL")
list(APPEND cxx_flags ${cxx_minsizerel})
list(APPEND cxx_linker_flags ${cxx_linker_minsizerel})
elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "SANITIZE")
list(APPEND cxx_flags ${cxx_sanitize})
elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "COVERAGE")
list(APPEND cxx_flags ${cxx_coverage})
endif()
string(REPLACE " " ";" polybar_flags_list "${POLYBAR_FLAGS}")
list(APPEND cxx_flags ${polybar_flags_list})
list(APPEND cxx_linker_flags ${cxx_flags})
string(REPLACE ";" " " cxx_flags_str "${cxx_flags}")
string(REPLACE ";" " " cxx_linker_flags_str "${cxx_linker_flags}")
# TODO use target_link_options once min cmake version is >= 3.13
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${cxx_linker_flags_str}")

107
cmake/libpoly.cmake Normal file
View File

@ -0,0 +1,107 @@
# Sets up options and dependencies for libpoly
# Automatically enable all optional dependencies that are available on the machine
checklib(ENABLE_ALSA "pkg-config" alsa)
checklib(ENABLE_CURL "pkg-config" libcurl)
checklib(ENABLE_I3 "binary" i3)
checklib(ENABLE_MPD "pkg-config" libmpdclient)
checklib(WITH_LIBNL "pkg-config" libnl-genl-3.0)
if(WITH_LIBNL)
checklib(ENABLE_NETWORK "pkg-config" libnl-genl-3.0)
set(WIRELESS_LIB "libnl")
else()
checklib(ENABLE_NETWORK "cmake" Libiw)
set(WIRELESS_LIB "wireless-tools")
endif()
checklib(ENABLE_PULSEAUDIO "pkg-config" libpulse)
checklib(WITH_XKB "pkg-config" xcb-xkb)
checklib(WITH_XRM "pkg-config" xcb-xrm)
checklib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12")
checklib(WITH_XCURSOR "pkg-config" "xcb-cursor")
option(ENABLE_ALSA "Enable alsa support" ON)
option(ENABLE_CURL "Enable curl support" ON)
option(ENABLE_DWM "Enable dwm support" ON)
option(ENABLE_I3 "Enable i3 support" ON)
option(ENABLE_MPD "Enable mpd support" ON)
option(WITH_LIBNL "Use netlink interface for wireless" ON)
option(ENABLE_NETWORK "Enable network support" ON)
option(ENABLE_XKEYBOARD "Enable xkeyboard support" ON)
option(ENABLE_PULSEAUDIO "Enable PulseAudio support" ON)
option(WITH_XRANDR_MONITORS "xcb-randr monitor support" ON)
option(WITH_XKB "xcb-xkb support" ON)
option(WITH_XRM "xcb-xrm support" ON)
option(WITH_XCURSOR "xcb-cursor support" ON)
option(DEBUG_LOGGER "Trace logging" ON)
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
option(DEBUG_LOGGER_VERBOSE "Trace logging (verbose)" OFF)
option(DEBUG_HINTS "Debug clickable areas" OFF)
option(DEBUG_WHITESPACE "Debug whitespace" OFF)
option(DEBUG_FONTCONFIG "Debug fontconfig" OFF)
endif()
# Load all packages for enabled components
find_package(Threads REQUIRED)
find_package(CairoFC REQUIRED)
find_package(LibUV 1.3.0 REQUIRED)
if (ENABLE_ALSA)
find_package(ALSA REQUIRED)
endif()
if (ENABLE_CURL)
find_package(CURL REQUIRED)
endif()
if (ENABLE_MPD)
find_package(LibMPDClient REQUIRED)
set(MPD_VERSION ${LibMPDClient_VERSION})
endif()
if (ENABLE_NETWORK)
if(WITH_LIBNL)
find_package(LibNlGenl3 REQUIRED)
set(NETWORK_LIBRARY_VERSION ${LibNlGenl3_VERSION})
else()
find_package(Libiw REQUIRED)
endif()
endif()
if (ENABLE_PULSEAUDIO)
find_package(LibPulse REQUIRED)
set(PULSEAUDIO_VERSION ${LibPulse_VERSION})
endif()
# xcomposite is required
list(APPEND XORG_EXTENSIONS COMPOSITE)
if (WITH_XKB)
list(APPEND XORG_EXTENSIONS XKB)
endif()
if (WITH_XCURSOR)
list(APPEND XORG_EXTENSIONS CURSOR)
endif()
if (WITH_XRM)
list(APPEND XORG_EXTENSIONS XRM)
endif()
# Set min xrandr version required
if (WITH_XRANDR_MONITORS)
set(XRANDR_VERSION "1.12")
else ()
set(XRANDR_VERSION "")
endif()
# Randr is required. Searches for randr only because we may do a version check
find_package(Xcb ${XRANDR_VERSION} REQUIRED COMPONENTS RANDR)
find_package(Xcb REQUIRED COMPONENTS ${XORG_EXTENSIONS})
# FreeBSD Support
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
find_package(LibInotify REQUIRED)
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `ALSA::ALSA` if alsa is found
#
# Defines the following Variables (see find_package_impl for more info):
# ALSA_FOUND
# ALSA_INCLUDE_DIR
# ALSA_INCLUDE_DIRS
# ALSA_LIBRARY
# ALSA_LIBRARIES
# ALSA_VERSION
find_package_impl("alsa" "ALSA" "alsa/asoundlib.h")
if(ALSA_FOUND AND NOT TARGET ALSA::ALSA)
create_imported_target("ALSA::ALSA" "${ALSA_INCLUDE_DIR}" "${ALSA_LIBRARY}")
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `CURL::libcurl` if libcurl is found
#
# Defines the following Variables (see find_package_impl for more info):
# CURL_FOUND
# CURL_INCLUDE_DIR
# CURL_INCLUDE_DIRS
# CURL_LIBRARY
# CURL_LIBRARIES
# CURL_VERSION
find_package_impl("libcurl" "CURL" "curl/curl.h")
if(CURL_FOUND AND NOT TARGET CURL::libcurl)
create_imported_target("CURL::libcurl" "${CURL_INCLUDE_DIR}" "${CURL_LIBRARY}")
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `Cairo::CairoFC` if cairo-fc is found
#
# Defines the following Variables (see find_package_impl for more info):
# CairoFC_FOUND
# CairoFC_INCLUDE_DIR
# CairoFC_INCLUDE_DIRS
# CairoFC_LIBRARY
# CairoFC_LIBRARIES
# CairoFC_VERSION
find_package_impl("cairo-fc" "CairoFC" "")
if(CairoFC_FOUND AND NOT TARGET Cairo::CairoFC)
create_imported_target("Cairo::CairoFC" "${CairoFC_INCLUDE_DIR}" "${CairoFC_LIBRARY}")
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `LibInotify::LibInotify` if libinotify is found
#
# Defines the following Variables (see find_package_impl for more info):
# LibInotify_FOUND
# LibInotify_INCLUDE_DIR
# LibInotify_INCLUDE_DIRS
# LibInotify_LIBRARY
# LibInotify_LIBRARIES
# LibInotify_VERSION
find_package_impl("libinotify" "LibInotify" "")
if(LibInotify_FOUND AND NOT TARGET LibInotify::LibInotify)
create_imported_target("LibInotify::LibInotify" "${LibInotify_INCLUDE_DIR}" "${LibInotify_LIBRARY}")
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `LibMPDClient::LibMPDClient` if libmpdclient is found
#
# Defines the following Variables (see find_package_impl for more info):
# LibMPDClient_FOUND
# LibMPDClient_INCLUDE_DIR
# LibMPDClient_INCLUDE_DIRS
# LibMPDClient_LIBRARY
# LibMPDClient_LIBRARIES
# LibMPDClient_VERSION
find_package_impl("libmpdclient" "LibMPDClient" "mpd/player.h")
if(LibMPDClient_FOUND AND NOT TARGET LibMPDClient::LibMPDClient)
create_imported_target("LibMPDClient::LibMPDClient" "${LibMPDClient_INCLUDE_DIR}" "${LibMPDClient_LIBRARY}")
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `LibNlGenl3::LibNlGenl3` if libnl-genl-3.0 is found
#
# Defines the following Variables (see find_package_impl for more info):
# LibNlGenl3_FOUND
# LibNlGenl3_INCLUDE_DIR
# LibNlGenl3_INCLUDE_DIRS
# LibNlGenl3_LIBRARY
# LibNlGenl3_LIBRARIES
# LibNlGenl3_VERSION
find_package_impl("libnl-genl-3.0" "LibNlGenl3" "")
if(LibNlGenl3_FOUND AND NOT TARGET LibNlGenl3::LibNlGenl3)
create_imported_target("LibNlGenl3::LibNlGenl3" "${LibNlGenl3_INCLUDE_DIR}" "${LibNlGenl3_LIBRARY}")
endif()

View File

@ -0,0 +1,14 @@
# This module defines an imported target `LibPulse::LibPulse` if libpulse is found
#
# Defines the following Variables (see find_package_impl for more info):
# LibPulse_FOUND
# LibPulse_INCLUDE_DIR
# LibPulse_INCLUDE_DIRS
# LibPulse_LIBRARY
# LibPulse_LIBRARIES
# LibPulse_VERSION
find_package_impl("libpulse" "LibPulse" "pulse/version.h")
if(LibPulse_FOUND AND NOT TARGET LibPulse::LibPulse)
create_imported_target("LibPulse::LibPulse" "${LibPulse_INCLUDE_DIR}" "${LibPulse_LIBRARY}")
endif()

View File

@ -0,0 +1,13 @@
# This module defines
# LibUV_FOUND
# LibUV_INCLUDE_DIR
# LibUV_INCLUDE_DIRS
# LibUV_LIBRARY
# LibUV_LIBRARIES
# LibUV_VERSION
find_package_impl("libuv" "LibUV" "uv.h")
if(LibUV_FOUND AND NOT TARGET LibUV::LibUV)
create_imported_target("LibUV::LibUV" "${LibUV_INCLUDE_DIR}" "${LibUV_LIBRARY}")
endif()

View File

@ -6,7 +6,7 @@
find_library(LIBIW_LIBRARY iw) find_library(LIBIW_LIBRARY iw)
if(LIBIW_LIBRARY) if(LIBIW_LIBRARY)
set(LIBIW_LIBRARIES ${LIBIW_LIBRARY}) set(LIBIW_LIBRARIES ${LIBIW_LIBRARY})
endif(LIBIW_LIBRARY) endif(LIBIW_LIBRARY)
find_path(LIBIW_INCLUDE_DIR NAMES iwlib.h) find_path(LIBIW_INCLUDE_DIR NAMES iwlib.h)
@ -15,3 +15,7 @@ include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libiw DEFAULT_MSG LIBIW_LIBRARY LIBIW_INCLUDE_DIR) find_package_handle_standard_args(Libiw DEFAULT_MSG LIBIW_LIBRARY LIBIW_INCLUDE_DIR)
mark_as_advanced(LIBIW_INCLUDE_DIR LIBIW_LIBRARY) mark_as_advanced(LIBIW_INCLUDE_DIR LIBIW_LIBRARY)
if(Libiw_FOUND AND NOT TARGET Libiw::Libiw)
create_imported_target("Libiw::Libiw" "${LIBIW_INCLUDE_DIR}" "${LIBIW_LIBRARIES}")
endif()

View File

@ -0,0 +1,59 @@
# Loads multiple XCB components
# Version checks will be made against all requested components
#
# For each component ${comp} it does the following:
#
# Defines an imported target `Xcb::${comp}` if xcb-${comp} is found
#
# Defines the following Variables (see find_package_impl for more info):
# Xcb_${comp}_FOUND
# Xcb_${comp}_INCLUDE_DIR
# Xcb_${comp}_INCLUDE_DIRS
# Xcb_${comp}_LIBRARY
# Xcb_${comp}_LIBRARIES
# Xcb_${comp}_VERSION
# This script only supports the following components of XCB
set(XCB_known_components
XCB
RANDR
COMPOSITE
XKB
XRM
CURSOR)
# Deducing header from the name of the component
foreach(_comp ${XCB_known_components})
string(TOLOWER "${_comp}" _lc_comp)
set(XCB_${_comp}_pkg_config "xcb-${_lc_comp}")
set(XCB_${_comp}_header "xcb/${_lc_comp}.h")
endforeach()
# Exception cases
set(XCB_XRM_header "xcb/xcb_xrm.h")
set(XCB_CURSOR_header "xcb/xcb_cursor.h")
foreach(_comp ${Xcb_FIND_COMPONENTS})
if (NOT ${_comp} IN_LIST XCB_known_components)
message(FATAL_ERROR "Unknow component \"${_comp}\" of XCB")
endif()
# Forward the different find options set for FindXcb to the individual
# components. This is required because find_package_handle_standard_args in
# find_package_impl uses these variables for version checks and other things.
set(Xcb_${_comp}_FIND_VERSION ${Xcb_FIND_VERSION})
set(Xcb_${_comp}_FIND_QUIETLY ${Xcb_FIND_QUIETLY})
set(Xcb_${_comp}_FIND_REQUIRED ${Xcb_FIND_REQUIRED})
# Bypass developer warning that the first argument to
# find_package_handle_standard_args (Xcb_...) does not match the name of the
# calling package (Xcb)
# https://cmake.org/cmake/help/v3.17/module/FindPackageHandleStandardArgs.html
set(FPHSA_NAME_MISMATCHED TRUE)
find_package_impl(${XCB_${_comp}_pkg_config} "Xcb_${_comp}" "${XCB_${_comp}_header}")
if(Xcb_${_comp}_FOUND AND NOT TARGET Xcb::${_comp})
create_imported_target("Xcb::${_comp}" "${Xcb_${_comp}_INCLUDE_DIRS}" "${Xcb_${_comp}_LIBRARIES}")
elseif(NOT Xcb_${_comp}_FOUND AND Xcb_FIND_REQUIRED)
message(FATAL_ERROR "Xcb: Required component \"${_comp}\" was not found")
endif()
endforeach()

View File

@ -1,8 +0,0 @@
set(USER_CONFIG_HOME "$ENV{XDG_CONFIG_HOME}")
if(NOT USER_CONFIG_HOME)
set(USER_CONFIG_HOME "$ENV{HOME}/.config")
endif()
set(USER_CONFIG_HOME "${USER_CONFIG_HOME}/polybar")
file(INSTALL "@CMAKE_SOURCE_DIR@/config"
DESTINATION "${USER_CONFIG_HOME}")

View File

@ -29,11 +29,10 @@ fi
cmake \ cmake \
-DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_CXX_COMPILER="${CXX}" \
-DCMAKE_CXX_FLAGS="${CXXFLAGS} -Werror" \ -DPOLYBAR_FLAGS="${CXXFLAGS} -Werror" \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \ -DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \
-DBUILD_DOC:BOOL="${BUILD_DOC:-OFF}" \ -DBUILD_DOC:BOOL=OFF \
-DWITH_XRANDR=ON \
-DENABLE_PULSEAUDIO="${ENABLE_PULSEAUDIO:-OFF}" \ -DENABLE_PULSEAUDIO="${ENABLE_PULSEAUDIO:-OFF}" \
-DENABLE_NETWORK="${ENABLE_NETWORK:-OFF}" \ -DENABLE_NETWORK="${ENABLE_NETWORK:-OFF}" \
-DENABLE_MPD="${ENABLE_MPD:-OFF}" \ -DENABLE_MPD="${ENABLE_MPD:-OFF}" \

View File

@ -1,503 +0,0 @@
;==========================================================
;
;
;
;
;
;
;
;
;
;
; To learn more about how to configure Polybar
; go to https://github.com/polybar/polybar
;
; The README contains a lot of information
;
;==========================================================
[colors]
;background = ${xrdb:color0:#222}
background = #222
background-alt = #444
;foreground = ${xrdb:color7:#222}
foreground = #dfdfdf
foreground-alt = #555
primary = #ffb52a
secondary = #e60053
alert = #bd2c40
[bar/example]
;monitor = ${env:MONITOR:HDMI-1}
width = 100%
height = 27
;offset-x = 1%
;offset-y = 1%
radius = 6.0
fixed-center = false
background = ${colors.background}
foreground = ${colors.foreground}
line-size = 3
line-color = #f00
border-size = 4
border-color = #00000000
padding-left = 0
padding-right = 2
module-margin-left = 1
module-margin-right = 2
font-0 = @FONT_FIXED@;1
font-1 = @FONT_UNIFONT@:size=8:antialias=false;0
font-2 = @FONT_SIJI@;1
modules-left = @MODULES_LEFT@
modules-center = @MODULES_CENTER@
modules-right = @MODULES_RIGHT@
tray-position = right
tray-padding = 2
;tray-background = #0063ff
;wm-restack = bspwm
;wm-restack = i3
;override-redirect = true
;scroll-up = bspwm-desknext
;scroll-down = bspwm-deskprev
;scroll-up = i3wm-wsnext
;scroll-down = i3wm-wsprev
cursor-click = pointer
cursor-scroll = ns-resize
[module/xwindow]
type = internal/xwindow
label = %title:0:30:...%
[module/xkeyboard]
type = internal/xkeyboard
blacklist-0 = num lock
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-prefix-underline = ${colors.secondary}
label-layout = %layout%
label-layout-underline = ${colors.secondary}
label-indicator-padding = 2
label-indicator-margin = 1
label-indicator-background = ${colors.secondary}
label-indicator-underline = ${colors.secondary}
[module/filesystem]
type = internal/fs
interval = 25
mount-0 = /
label-mounted = %{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%
label-unmounted = %mountpoint% not mounted
label-unmounted-foreground = ${colors.foreground-alt}
[module/bspwm]
type = internal/bspwm
label-focused = %index%
label-focused-background = ${colors.background-alt}
label-focused-underline= ${colors.primary}
label-focused-padding = 2
label-occupied = %index%
label-occupied-padding = 2
label-urgent = %index%!
label-urgent-background = ${colors.alert}
label-urgent-padding = 2
label-empty = %index%
label-empty-foreground = ${colors.foreground-alt}
label-empty-padding = 2
; Separator in between workspaces
; label-separator = |
[module/i3]
type = internal/i3
format = <label-state> <label-mode>
index-sort = true
wrapping-scroll = false
; Only show workspaces on the same output as the bar
;pin-workspaces = true
label-mode-padding = 2
label-mode-foreground = #000
label-mode-background = ${colors.primary}
; focused = Active workspace on focused monitor
label-focused = %index%
label-focused-background = ${colors.background-alt}
label-focused-underline= ${colors.primary}
label-focused-padding = 2
; unfocused = Inactive workspace on any monitor
label-unfocused = %index%
label-unfocused-padding = 2
; visible = Active workspace on unfocused monitor
label-visible = %index%
label-visible-background = ${self.label-focused-background}
label-visible-underline = ${self.label-focused-underline}
label-visible-padding = ${self.label-focused-padding}
; urgent = Workspace with urgency hint set
label-urgent = %index%
label-urgent-background = ${colors.alert}
label-urgent-padding = 2
; Separator in between workspaces
; label-separator = |
[module/dwm]
type = internal/dwm
format = <label-tags> <label-layout> <label-floating> <label-title>
; Path to dwm socket (default: /tmp/dwm.sock)
; socket-path = /tmp/dwm.sock
; Left-click to view tag, right-click to toggle tag view
enable-tags-click = false
; Scroll to cycle between available tags
enable-tags-scroll = false
; If true and enable-tags-scroll = true, scrolling will view all tags regardless if occupied
tags-scroll-empty = false
; If true and enable-tags-scroll = true, scrolling will cycle through tags backwards
tags-scroll-reverse = false
; If true and enable-tags-scroll = true, wrap active tag when scrolling
tags-scroll-wrap = false
; Left-click to set secondary layout, right-click to switch to previous layout
enable-layout-click = false
; Scroll to cycle between available layouts
enable-layout-scroll = false
; Wrap when scrolling and reaching begining/end of layouts
layout-scroll-wrap = false
; Reverse scroll direction
layout-scroll-reverse = false
; If enable-layout-click = true, clicking the layout symbol will switch to this layout
secondary-layout-symbol = [M]
; Separator in between shown tags
; label-separator = |
; Title of currently focused window
; Available tokens:
; %title%
label-title = %title%
label-title-padding = 2
label-title-forefround = ${colors.primary}
label-title-maxlen = 30
; Symbol of current layout
; Available tokens:
; %symbol%
label-layout = %symbol%
label-layout-padding = 2
label-layout-foreground = #000
label-layout-background = ${colors.primary}
; Text to show when currently focused window is floating
label-floating = F
; States: focused, unfocused, visible, urgent, empty
; Available tokens:
; %name%
; focused = Selected tag on focused monitor
label-focused = %name%
label-focused-background = ${colors.background-alt}
label-focused-underline= ${colors.primary}
label-focused-padding = 2
; unfocused = Unselected tag on unselected monitor
label-unfocused = %name%
label-unfocused-padding = 2
; visible = Unselected tag, but occupied tag on any monitor
label-visible = %name%
label-visible-background = ${self.label-focused-background}
label-visible-underline = ${self.label-focused-underline}
label-visible-padding = ${self.label-focused-padding}
; urgent = Unselected tag with window that has urgency hint set
label-urgent = %name%
label-urgent-background = ${colors.alert}
label-urgent-padding = 2
; empty = Unselected and unoccupied tag
; This can be set to an empty string to hide empty tags
label-empty = %name%
label-empty-background = ${colors.primary}
label-empty-padding = 2
[module/mpd]
type = internal/mpd
format-online = <label-song> <icon-prev> <icon-stop> <toggle> <icon-next>
icon-prev =
icon-stop =
icon-play =
icon-pause =
icon-next =
label-song-maxlen = 25
label-song-ellipsis = true
[module/xbacklight]
type = internal/xbacklight
format = <label> <bar>
label = BL
bar-width = 10
bar-indicator = |
bar-indicator-foreground = #fff
bar-indicator-font = 2
bar-fill =
bar-fill-font = 2
bar-fill-foreground = #9f78e1
bar-empty =
bar-empty-font = 2
bar-empty-foreground = ${colors.foreground-alt}
[module/backlight-acpi]
inherit = module/xbacklight
type = internal/backlight
card = intel_backlight
[module/cpu]
type = internal/cpu
interval = 2
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-underline = #f90000
label = %percentage:2%%
[module/memory]
type = internal/memory
interval = 2
format-prefix = " "
format-prefix-foreground = ${colors.foreground-alt}
format-underline = #4bffdc
label = %percentage_used%%
[module/wlan]
type = internal/network
interface = @INTERFACE_WLAN@
interval = 3.0
format-connected = <ramp-signal> <label-connected>
format-connected-underline = #9f78e1
label-connected = %essid%
format-disconnected =
;format-disconnected = <label-disconnected>
;format-disconnected-underline = ${self.format-connected-underline}
;label-disconnected = %ifname% disconnected
;label-disconnected-foreground = ${colors.foreground-alt}
ramp-signal-0 =
ramp-signal-1 =
ramp-signal-2 =
ramp-signal-3 =
ramp-signal-4 =
ramp-signal-foreground = ${colors.foreground-alt}
[module/eth]
type = internal/network
interface = @INTERFACE_ETH@
interval = 3.0
format-connected-underline = #55aa55
format-connected-prefix = " "
format-connected-prefix-foreground = ${colors.foreground-alt}
label-connected = %local_ip%
format-disconnected =
;format-disconnected = <label-disconnected>
;format-disconnected-underline = ${self.format-connected-underline}
;label-disconnected = %ifname% disconnected
;label-disconnected-foreground = ${colors.foreground-alt}
[module/date]
type = internal/date
interval = 5
date =
date-alt = " %Y-%m-%d"
time = %H:%M
time-alt = %H:%M:%S
format-prefix =
format-prefix-foreground = ${colors.foreground-alt}
format-underline = #0a6cf5
label = %date% %time%
[module/pulseaudio]
type = internal/pulseaudio
format-volume = <label-volume> <bar-volume>
label-volume = VOL %percentage%%
label-volume-foreground = ${root.foreground}
label-muted = 🔇 muted
label-muted-foreground = #666
bar-volume-width = 10
bar-volume-foreground-0 = #55aa55
bar-volume-foreground-1 = #55aa55
bar-volume-foreground-2 = #55aa55
bar-volume-foreground-3 = #55aa55
bar-volume-foreground-4 = #55aa55
bar-volume-foreground-5 = #f5a70a
bar-volume-foreground-6 = #ff5555
bar-volume-gradient = false
bar-volume-indicator = |
bar-volume-indicator-font = 2
bar-volume-fill =
bar-volume-fill-font = 2
bar-volume-empty =
bar-volume-empty-font = 2
bar-volume-empty-foreground = ${colors.foreground-alt}
[module/alsa]
type = internal/alsa
format-volume = <label-volume> <bar-volume>
label-volume = VOL
label-volume-foreground = ${root.foreground}
format-muted-prefix = " "
format-muted-foreground = ${colors.foreground-alt}
label-muted = sound muted
bar-volume-width = 10
bar-volume-foreground-0 = #55aa55
bar-volume-foreground-1 = #55aa55
bar-volume-foreground-2 = #55aa55
bar-volume-foreground-3 = #55aa55
bar-volume-foreground-4 = #55aa55
bar-volume-foreground-5 = #f5a70a
bar-volume-foreground-6 = #ff5555
bar-volume-gradient = false
bar-volume-indicator = |
bar-volume-indicator-font = 2
bar-volume-fill =
bar-volume-fill-font = 2
bar-volume-empty =
bar-volume-empty-font = 2
bar-volume-empty-foreground = ${colors.foreground-alt}
[module/battery]
type = internal/battery
battery = @BATTERY@
adapter = @ADAPTER@
full-at = 98
format-charging = <animation-charging> <label-charging>
format-charging-underline = #ffb52a
format-discharging = <animation-discharging> <label-discharging>
format-discharging-underline = ${self.format-charging-underline}
format-full-prefix = " "
format-full-prefix-foreground = ${colors.foreground-alt}
format-full-underline = ${self.format-charging-underline}
ramp-capacity-0 =
ramp-capacity-1 =
ramp-capacity-2 =
ramp-capacity-foreground = ${colors.foreground-alt}
animation-charging-0 =
animation-charging-1 =
animation-charging-2 =
animation-charging-foreground = ${colors.foreground-alt}
animation-charging-framerate = 750
animation-discharging-0 =
animation-discharging-1 =
animation-discharging-2 =
animation-discharging-foreground = ${colors.foreground-alt}
animation-discharging-framerate = 750
[module/temperature]
type = internal/temperature
thermal-zone = 0
warn-temperature = 60
format = <ramp> <label>
format-underline = #f50a4d
format-warn = <ramp> <label-warn>
format-warn-underline = ${self.format-underline}
label = %temperature-c%
label-warn = %temperature-c%
label-warn-foreground = ${colors.secondary}
ramp-0 =
ramp-1 =
ramp-2 =
ramp-foreground = ${colors.foreground-alt}
[module/powermenu]
type = custom/menu
expand-right = true
format-spacing = 1
label-open =
label-open-foreground = ${colors.secondary}
label-close = cancel
label-close-foreground = ${colors.secondary}
label-separator = |
label-separator-foreground = ${colors.foreground-alt}
menu-0-0 = reboot
menu-0-0-exec = menu-open-1
menu-0-1 = power off
menu-0-1-exec = menu-open-2
menu-1-0 = cancel
menu-1-0-exec = menu-open-0
menu-1-1 = reboot
menu-1-1-exec = sudo reboot
menu-2-0 = power off
menu-2-0-exec = sudo poweroff
menu-2-1 = cancel
menu-2-1-exec = menu-open-0
[settings]
screenchange-reload = true
;compositing-background = xor
;compositing-background = screen
;compositing-foreground = source
;compositing-border = over
;pseudo-transparency = false
[global/wm]
margin-top = 5
margin-bottom = 5
; vim:ft=dosini

View File

@ -1,28 +1,41 @@
_polybar_config_file() { _polybar_default_file() {
local config_path=${XDG_CONFIG_HOME:-$HOME/.config}/polybar/config local suffix=/polybar/config.ini
local home_path=${XDG_CONFIG_HOME:-$HOME/.config}${suffix}
local etc_xdg_path=${XDG_CONFIG_DIRS:-/etc/xdg}${suffix}
local etc_path=/etc${suffix}
if [ -r "$home_path" ]; then
echo "$home_path"
elif [ -r "$etc_xdg_path" ]; then
echo "$etc_xdg_path"
elif [ -r "$etc_path" ]; then
echo "$etc_path"
fi
}
_polybar_config_file() {
for ((i = 0; i < COMP_CWORD; i++)); do for ((i = 0; i < COMP_CWORD; i++)); do
case ${COMP_WORDS[i]} in case ${COMP_WORDS[i]} in
--config) --config)
config_path=${COMP_WORDS[i + 2]} echo "${COMP_WORDS[i + 2]}"
break return
;; ;;
-c) -c)
config_path=${COMP_WORDS[i + 1]} echo "${COMP_WORDS[i + 1]}"
break return
;; ;;
esac esac
done done
# Use eval + cd for to get bash's parameter/tilde expansion etc _polybar_default_file
(eval cd $(dirname "$config_path"); echo $PWD/$(basename "$config_path"))
} }
_polybar_bars() { _polybar_bars() {
local config_file=$(_polybar_config_file) local config_file=$(_polybar_config_file)
if [ -r "$config_file" ]; then if [ -r "$config_file" ]; then
grep -Po '\[bar/\K(.*)(?=\])' "$config_file" sed -nE 's|[[:space:]]*\[bar/([^\]+)\][[:space:]]*$|\1|p' "$config_file"
fi fi
} }
@ -72,7 +85,6 @@ _polybar() {
COMPREPLY=( $(compgen -f -X "!*.png" "$cur") ) COMPREPLY=( $(compgen -f -X "!*.png" "$cur") )
return 0 return 0
;; ;;
# TODO: read properties of the selected bar from config
-d|--dump) -d|--dump)
return 0 return 0
;; ;;

View File

@ -1,19 +1,21 @@
# Maintainer: Mihir Lad <mihirlad55 gmail> # Maintainer: Patrick Ziegler <p.ziegler96@gmail.com>
_pkgname=polybar-dwm-module _pkgname=polybar
pkgname="${_pkgname}" pkgname="${_pkgname}-git"
pkgver=3.5.2.r98.ga0e9d48d pkgver=3.5.7
pkgrel=1 pkgrel=1
pkgdesc="polybar fork with a dwm module" pkgdesc="A fast and easy-to-use status bar"
arch=("i686" "x86_64") arch=("i686" "x86_64")
url="https://github.com/mihirlad55/polybar-dwm-module" url="https://github.com/polybar/polybar"
license=("MIT") license=("MIT")
depends=("cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm" "xcb-util-cursor" depends=("libuv" "cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm"
"alsa-lib" "libpulse" "libmpdclient" "libnl" "jsoncpp" "curl") "xcb-util-cursor" "alsa-lib" "libpulse" "libmpdclient" "libnl"
"jsoncpp" "curl")
optdepends=("i3-wm: i3 module support" optdepends=("i3-wm: i3 module support"
"ttf-unifont: Font used in example config" "ttf-unifont: Font used in example config"
"siji-git: Font used in example config" "siji-git: Font used in example config"
"xorg-fonts-misc: Font used in example config") "xorg-fonts-misc: Font used in example config")
makedepends=("cmake" "git" "python" "pkg-config" "python-sphinx" "i3-wm") makedepends=("cmake" "git" "python" "pkg-config" "python-sphinx"
"python-packaging" "i3-wm")
provides=("polybar") provides=("polybar")
conflicts=("polybar") conflicts=("polybar")
install="${_pkgname}.install" install="${_pkgname}.install"

View File

@ -1,12 +0,0 @@
post_install() {
cat << EOF
Get started with the example configuration:
$ install -Dm644 /usr/share/doc/polybar/config \$HOME/.config/polybar/config
$ polybar example
For more information, see https://github.com/polybar/polybar/wiki
EOF
}

View File

@ -0,0 +1,36 @@
# Maintainer: Patrick Ziegler <p.ziegler96@gmail.com>
pkgname=polybar
pkgver=3.5.7
pkgrel=1
pkgdesc="A fast and easy-to-use status bar"
arch=("i686" "x86_64")
url="https://github.com/polybar/polybar"
license=("MIT")
depends=("cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm" "xcb-util-cursor"
"alsa-lib" "libpulse" "libmpdclient" "libnl" "jsoncpp" "curl")
optdepends=("i3-wm: i3 module support"
"ttf-unifont: Font used in example config"
"siji-git: Font used in example config"
"xorg-fonts-misc: Font used in example config")
makedepends=("cmake" "python" "pkg-config" "python-sphinx" "python-packaging" "i3-wm")
conflicts=("polybar-git")
install="${pkgname}.install"
source=(${url}/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.gz)
sha256sums=('73210e6d74217acb953b253990b4302343b7b6a7870fe1da9a1855daa44123db')
_dir="${pkgname}-${pkgver}"
prepare() {
mkdir -p "${_dir}/build"
}
build() {
cd "${_dir}/build" || exit 1
# Force cmake to use system python (to detect xcbgen)
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DPYTHON_EXECUTABLE=/usr/bin/python3 ..
cmake --build .
}
package() {
cmake --build "${_dir}/build" --target install -- DESTDIR="${pkgdir}"
install -Dm644 "${_dir}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}

View File

@ -29,6 +29,22 @@ _polybar() {
'::bar name:_polybar_list_names' '::bar name:_polybar_list_names'
} }
(( $+functions[_polybar_default_file] )) || _polybar_default_file() {
local suffix=/polybar/config.ini
local home_path=${XDG_CONFIG_HOME:-$HOME/.config}${suffix}
local etc_xdg_path=${XDG_CONFIG_DIRS:-/etc/xdg}${suffix}
local etc_path=/etc${suffix}
if [ -r "$home_path" ]; then
echo "$home_path"
elif [ -r "$etc_xdg_path" ]; then
echo "$etc_xdg_path"
elif [ -r "$etc_path" ]; then
echo "$etc_path"
fi
}
(( $+functions[_polybar_list_names] )) || _polybar_list_names() { (( $+functions[_polybar_list_names] )) || _polybar_list_names() {
local conf local conf
if (( $+opt_args[-c] )); then if (( $+opt_args[-c] )); then
@ -36,9 +52,9 @@ _polybar() {
elif (( $+opt_args[--config] )); then elif (( $+opt_args[--config] )); then
conf=${(e)opt_args[--config]} conf=${(e)opt_args[--config]}
else else
conf=${XDG_CONFIG_HOME:-$HOME/.config}/polybar/config conf=$(_polybar_default_file)
fi fi
local names; names=(${(f)"$(sed -nr 's|\[bar/([^\]+)\]$|\1|p' ${conf} 2>/dev/null)"}) local names; names=(${(f)"$(sed -nE 's|[[:space:]]*\[bar/([^\]+)\][[:space:]]*$|\1|p' ${conf} 2>/dev/null)"})
_describe -t names 'configuration name' names _describe -t names 'configuration name' names
} }

View File

@ -1,13 +1,12 @@
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) set(SPHINX_BUILD "sphinx-build" CACHE STRING "Name/Path of the sphinx-build executable to use.")
set(SPHINX_FLAGS "" CACHE STRING "Flags to pass to sphinx-build")
# Only used if documentation is built on its own find_program(BIN_SPHINX "${SPHINX_BUILD}")
project(polybar-doc NONE)
if(NOT SPHINX_BUILD) if(NOT BIN_SPHINX)
set(SPHINX_BUILD "sphinx-build") message(FATAL_ERROR "sphinx-build executable '${SPHINX_BUILD}' not found.")
endif() endif()
set(SPHINX_FLAGS "" CACHE STRING "Flags to pass to sphinx-build")
separate_arguments(sphinx_flags UNIX_COMMAND "${SPHINX_FLAGS}") separate_arguments(sphinx_flags UNIX_COMMAND "${SPHINX_FLAGS}")
set(doc_path "${CMAKE_CURRENT_SOURCE_DIR}") set(doc_path "${CMAKE_CURRENT_SOURCE_DIR}")
@ -16,7 +15,13 @@ set(doc_path "${CMAKE_CURRENT_SOURCE_DIR}")
configure_file(conf.py conf.py @ONLY) configure_file(conf.py conf.py @ONLY)
# We want to run `sphinx-build` with the following builders # We want to run `sphinx-build` with the following builders
set(doc_builders "html" "man") if (BUILD_DOC_HTML)
list(APPEND doc_builders "html")
endif()
if (BUILD_DOC_MAN)
list(APPEND doc_builders "man")
endif()
# Name of all documentation targets # Name of all documentation targets
set(doc_targets "") set(doc_targets "")
@ -25,11 +30,12 @@ foreach(builder ${doc_builders})
set(doc_target "doc_${builder}") set(doc_target "doc_${builder}")
set(builder_log "builder-${builder}.log") set(builder_log "builder-${builder}.log")
add_custom_target(${doc_target} add_custom_target(${doc_target}
COMMAND ${SPHINX_BUILD} COMMAND ${BIN_SPHINX}
-b ${builder} -b ${builder}
# conf.py dir # conf.py dir
-c "${CMAKE_CURRENT_BINARY_DIR}" -c "${CMAKE_CURRENT_BINARY_DIR}"
-d "${CMAKE_CURRENT_BINARY_DIR}/doctrees" -d "${CMAKE_CURRENT_BINARY_DIR}/doctrees"
-n
${sphinx_flags} ${sphinx_flags}
# Documentation source file dir # Documentation source file dir
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}"
@ -43,27 +49,32 @@ endforeach()
# Dummy target that depends on all documentation targets # Dummy target that depends on all documentation targets
add_custom_target(doc ALL DEPENDS ${doc_targets}) add_custom_target(doc ALL DEPENDS ${doc_targets})
# This is needed for the case where only the doc target is built if (BUILD_DOC_HTML)
# CMAKE_INSTALL_DOCDIR uses PROJECT_NAME which is now polybar-doc, to be install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
# consistent with a regular install we temporarily override it with "polybar" DESTINATION ${CMAKE_INSTALL_DOCDIR}
# before including GNUInstallDirs COMPONENT doc
# Also since no language is set and GNUInstallDirs cannot set PATTERN ".buildinfo" EXCLUDE)
# CMAKE_INSTALL_LIBDIR, so we set it to a dummy value to suppress a warning
if(${CMAKE_PROJECT_NAME} STREQUAL "polybar-doc")
set(PROJECT_NAME "polybar")
set(CMAKE_INSTALL_LIBDIR "")
include(GNUInstallDirs)
set(PROJECT_NAME "polybar-doc")
endif() endif()
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ install(FILES ${CMAKE_SOURCE_DIR}/CHANGELOG.md
DESTINATION ${CMAKE_INSTALL_DOCDIR} DESTINATION ${CMAKE_INSTALL_DOCDIR}
COMPONENT doc) COMPONENT doc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar.1 install(FILES ${CMAKE_CURRENT_LIST_DIR}/config.ini
DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples
COMPONENT doc)
if (BUILD_DOC_MAN)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
COMPONENT doc) COMPONENT doc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar.5 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar-msg.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
COMPONENT doc)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar.5
DESTINATION ${CMAKE_INSTALL_MANDIR}/man5 DESTINATION ${CMAKE_INSTALL_MANDIR}/man5
COMPONENT doc) COMPONENT doc)
endif()

View File

@ -13,9 +13,6 @@ have that installed.
If you build polybar normally while having Sphinx installed during configuration, the documentation will be enabled and If you build polybar normally while having Sphinx installed during configuration, the documentation will be enabled and
built as well. Building the documentation can be disabled by passing `-DBUILD_DOC=OFF` to `cmake`. built as well. Building the documentation can be disabled by passing `-DBUILD_DOC=OFF` to `cmake`.
Alternatively the documentation can be built without the rest of polybar, for that run `cmake` only on the `doc`
directory. For example, create a `build` directory in `doc` and then run `cmake ..` in there.
Once configured, all of the documentation can be generated with `make doc` or use `make doc_html` or `make doc_man` to Once configured, all of the documentation can be generated with `make doc` or use `make doc_html` or `make doc_man` to
only generate the html documentation or the man pages respectively. only generate the html documentation or the man pages respectively.

BIN
doc/_static/default.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -26,7 +26,9 @@ def get_version(root_path):
with open(path, "r") as f: with open(path, "r") as f:
for line in f.readlines(): for line in f.readlines():
if not line.startswith("#"): if not line.startswith("#"):
return packaging.version.parse(line) # NB: we can't parse it yet since sphinx could import
# pkg_resources later on and it could patch packaging.version
return line
raise RuntimeError("No version found in {}".format(path)) raise RuntimeError("No version found in {}".format(path))
@ -182,6 +184,7 @@ latex_documents = [
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('man/polybar.1', 'polybar', 'A fast and easy-to-use tool status bar', [], 1), ('man/polybar.1', 'polybar', 'A fast and easy-to-use tool status bar', [], 1),
('man/polybar-msg.1', 'polybar-msg', 'Send IPC messages to polybar', [], 1),
('man/polybar.5', 'polybar', 'configuration file for polybar(1)', [], 5) ('man/polybar.5', 'polybar', 'configuration file for polybar(1)', [], 5)
] ]
@ -244,8 +247,9 @@ if packaging.version.parse(sphinx.__version__) >= packaging.version.parse("1.8.5
""" """
def run(self) -> List[Node]: def run(self) -> List[Node]:
directive_version = packaging.version.parse(self.arguments[0]) directive_version = packaging.version.parse(self.arguments[0])
parsed_version_txt = packaging.version.parse(version_txt)
if directive_version > version_txt: if directive_version > parsed_version_txt:
self.arguments[0] += " (unreleased)" self.arguments[0] += " (unreleased)"
return super().run() return super().run()

172
doc/config.ini Normal file
View File

@ -0,0 +1,172 @@
;==========================================================
;
;
; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
;
;
; To learn more about how to configure Polybar
; go to https://github.com/polybar/polybar
;
; The README contains a lot of information
;
;==========================================================
[colors]
background = #282A2E
background-alt = #373B41
foreground = #C5C8C6
primary = #F0C674
secondary = #8ABEB7
alert = #A54242
disabled = #707880
[bar/example]
width = 100%
height = 24pt
radius = 6
; dpi = 96
background = ${colors.background}
foreground = ${colors.foreground}
line-size = 3pt
border-size = 4pt
border-color = #00000000
padding-left = 0
padding-right = 1
module-margin = 1
separator = |
separator-foreground = ${colors.disabled}
font-0 = monospace;2
modules-left = xworkspaces xwindow
modules-right = filesystem pulseaudio xkeyboard memory cpu wlan eth date
cursor-click = pointer
cursor-scroll = ns-resize
enable-ipc = true
; tray-position = right
; wm-restack = generic
; wm-restack = bspwm
; wm-restack = i3
; override-redirect = true
[module/xworkspaces]
type = internal/xworkspaces
label-active = %name%
label-active-background = ${colors.background-alt}
label-active-underline= ${colors.primary}
label-active-padding = 1
label-occupied = %name%
label-occupied-padding = 1
label-urgent = %name%
label-urgent-background = ${colors.alert}
label-urgent-padding = 1
label-empty = %name%
label-empty-foreground = ${colors.disabled}
label-empty-padding = 1
[module/xwindow]
type = internal/xwindow
label = %title:0:60:...%
[module/filesystem]
type = internal/fs
interval = 25
mount-0 = /
label-mounted = %{F#F0C674}%mountpoint%%{F-} %percentage_used%%
label-unmounted = %mountpoint% not mounted
label-unmounted-foreground = ${colors.disabled}
[module/pulseaudio]
type = internal/pulseaudio
format-volume-prefix = "VOL "
format-volume-prefix-foreground = ${colors.primary}
format-volume = <label-volume>
label-volume = %percentage%%
label-muted = muted
label-muted-foreground = ${colors.disabled}
[module/xkeyboard]
type = internal/xkeyboard
blacklist-0 = num lock
label-layout = %layout%
label-layout-foreground = ${colors.primary}
label-indicator-padding = 2
label-indicator-margin = 1
label-indicator-foreground = ${colors.background}
label-indicator-background = ${colors.secondary}
[module/memory]
type = internal/memory
interval = 2
format-prefix = "RAM "
format-prefix-foreground = ${colors.primary}
label = %percentage_used:2%%
[module/cpu]
type = internal/cpu
interval = 2
format-prefix = "CPU "
format-prefix-foreground = ${colors.primary}
label = %percentage:2%%
[network-base]
type = internal/network
interval = 5
format-connected = <label-connected>
format-disconnected = <label-disconnected>
label-disconnected = %{F#F0C674}%ifname%%{F#707880} disconnected
[module/wlan]
inherit = network-base
interface-type = wireless
label-connected = %{F#F0C674}%ifname%%{F-} %essid% %local_ip%
[module/eth]
inherit = network-base
interface-type = wired
label-connected = %{F#F0C674}%ifname%%{F-} %local_ip%
[module/date]
type = internal/date
interval = 1
date = %H:%M
date-alt = %Y-%m-%d %H:%M:%S
label = %date%
label-foreground = ${colors.primary}
[settings]
screenchange-reload = true
pseudo-transparency = true
; vim:ft=dosini

View File

@ -114,6 +114,7 @@ as follows:
* A draft PR is opened for the release branch. This PR MUST NOT be merged in * A draft PR is opened for the release branch. This PR MUST NOT be merged in
GitHub's interface, it is only here for review, merging happens at the GitHub's interface, it is only here for review, merging happens at the
commandline. commandline.
* A `draft release`_ is created in GitHub's release publishing tools
* After approval, the GitHub release publishing tool is used to publish the * After approval, the GitHub release publishing tool is used to publish the
release and tag the tip of the release branch (the release commit). release and tag the tip of the release branch (the release commit).
* After the tag is created, the release branch is manually merged into * After the tag is created, the release branch is manually merged into
@ -158,7 +159,7 @@ anything.
For all releases, a new section of the following form should be created below For all releases, a new section of the following form should be created below
the ``Unreleased`` section: the ``Unreleased`` section:
.. code-block:: .. code-block:: md
## [X.Y.Z] - YYYY-MM-DD ## [X.Y.Z] - YYYY-MM-DD
@ -166,7 +167,7 @@ In addition, the reference link for the release should be added and the
reference link for the unreleased section should be updated at the bottom of the reference link for the unreleased section should be updated at the bottom of the
document: document:
.. code-block:: .. code-block:: md
[Unreleased]: https://github.com/polybar/polybar/compare/X.Y.Z...HEAD [Unreleased]: https://github.com/polybar/polybar/compare/X.Y.Z...HEAD
[X.Y.Z]: https://github.com/polybar/polybar/releases/tag/X.Y.Z [X.Y.Z]: https://github.com/polybar/polybar/releases/tag/X.Y.Z
@ -187,6 +188,20 @@ changelog should also prominently feature precisely what breaking changes were
introduced. If suitable, maybe even separate documentation dedicated to the introduced. If suitable, maybe even separate documentation dedicated to the
migration should be written. migration should be written.
Draft Release
~~~~~~~~~~~~~
On `GitHub <https://github.com/polybar/polybar/releases/new>`_ a new release
should be drafted.
The release targets the tip of the release branch (the release commit), the
name of the release and the tag is simply the release number.
The content of the release message should contain the changelog copied from
``CHANGELOG.md`` under the heading ``## Changelog``.
In addition using GitHub's "Auto-generate release notes" feature, the list of
new contributors should be generated and put at the end of the release notes.
The generated list of PRs can be removed.
After-Release Checklist After-Release Checklist
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
@ -201,9 +216,15 @@ After-Release Checklist
We have a GitHub action workflow called 'Release Workflow' that on every We have a GitHub action workflow called 'Release Workflow' that on every
release automatically creates a release archive, uploads it to the release, release automatically creates a release archive, uploads it to the release,
and adds a 'Download' section to the release body. and adds a 'Download' section to the release body.
If this fails for some reason, it should be triggered be triggered manually. If this fails for some reason, it should be triggered manually.
* Create a PR that updates the AUR ``PKGBUILD`` files for the ``polybar`` and * Create a PR that updates the AUR ``PKGBUILD`` files for the ``polybar`` and
``polybar-git`` packages (push after the release archive is uploaded). ``polybar-git`` packages (push after the release archive is uploaded).
* Close the `GitHub Milestone <https://github.com/polybar/polybar/milestones>`_
for the new release and move open issues (if any) to a later release.
* Activate the version on `Read the Docs
<https://readthedocs.org/projects/polybar/versions/>`_ and deactivate all
previous versions for the same minor release (e.g. for 3.5.4, deactivate all
other 3.5.X versions).
Deprecations Deprecations
~~~~~~~~~~~~ ~~~~~~~~~~~~

View File

@ -13,12 +13,14 @@ Welcome to the official polybar documentation.
:caption: Content: :caption: Content:
user/actions user/actions
user/ipc
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
:caption: Manual Pages: :caption: Manual Pages:
man/polybar.1 man/polybar.1
man/polybar-msg.1
man/polybar.5 man/polybar.5
.. toctree:: .. toctree::
@ -39,5 +41,5 @@ Getting Help
* `Polybar Wiki <https://github.com/polybar/polybar/wiki>`_ * `Polybar Wiki <https://github.com/polybar/polybar/wiki>`_
* `Gitter <https://gitter.im/polybar/polybar>`_ * `Gitter <https://gitter.im/polybar/polybar>`_
* `/r/polybar <https://reddit.com/r/polybar>`_ on reddit * `/r/polybar <https://reddit.com/r/polybar>`_ on reddit
* ``#polybar`` on ``chat.freenode.net`` * ``#polybar`` on `irc.libera.chat:6697 <https://libera.chat/>`_

75
doc/man/polybar-msg.1.rst Normal file
View File

@ -0,0 +1,75 @@
polybar-msg(1)
==============
SYNOPSIS
--------
| **polybar-msg** [*OPTIONS*] **action** *action-string*
| **polybar-msg** [*OPTIONS*] **action** *module* *action* [*data*]
| **polybar-msg** [*OPTIONS*] **cmd** *command*
DESCRIPTION
-----------
Polybar allows external control through *actions* and *commands*.
Actions control individual modules and commands control the bar itself.
The full IPC documentation is linked at the end of this document.
The available actions depend on the target module.
For actions, the payload is either a single action string or the module name,
the action name, and the optional data string specified separately.
In order for **polybar-msg** being able to send a message to a running
**polybar** process, the bar must have IPC enabled and both **polybar-msg** and
**polybar** must run under the same user.
OPTIONS
-------
.. program:: polybar-msg
.. option:: -h, --help
Display help text and exit
.. option:: -p PID
Send message only to **polybar** process running under the given process ID.
If not specified, the message is sent to all running **polybar** processes.
EXAMPLES
--------
**polybar-msg** **cmd** *quit*
Terminate all running **polybar** instances.
**polybar-msg** **action** *mymodule* *module_hide*
**polybar-msg** **action** "*#mymodule.module_hide*"
Hide the module named *mymodule*.
The first variant specifies the module and action names separately, the second uses an action string.
AUTHORS
-------
| Polybar was created by Michael Carlberg and is currently maintained by Patrick Ziegler.
| Contributors can be listed on GitHub.
REPORTING BUGS
--------------
Report issues on GitHub <https://github.com/polybar/polybar>
SEE ALSO
--------
.. only:: man
:manpage:`polybar`\(1),
:manpage:`polybar`\(5)
| IPC documentation: <https://polybar.rtfd.org/en/stable/user/ipc.html>
.. only:: not man
:doc:`polybar.1`,
:doc:`polybar.5`
:doc:`/user/ipc`

View File

@ -3,11 +3,12 @@ polybar(1)
SYNOPSIS SYNOPSIS
-------- --------
**polybar** [*OPTIONS*]... *BAR* **polybar** [*OPTIONS*]... [*BAR*]
DESCRIPTION DESCRIPTION
----------- -----------
Polybar aims to help users build beautiful and highly customizable status bars for their desktop environment, without the need of having a black belt in shell scripting. Polybar aims to help users build beautiful and highly customizable status bars for their desktop environment, without the need of having a black belt in shell scripting.
If the *BAR* argument is not provided and the configuration file only contains one bar definition, polybar will display this bar.
OPTIONS OPTIONS
------- -------
@ -32,9 +33,13 @@ OPTIONS
Specify the path to the configuration file. By default, the configuration file is loaded from: Specify the path to the configuration file. By default, the configuration file is loaded from:
| * ``$XDG_CONFIG_HOME/polybar/config``
| **$XDG_CONFIG_HOME/polybar/config** * ``$XDG_CONFIG_HOME/polybar/config.ini``
| **$HOME/.config/polybar/config** * ``$HOME/.config/polybar/config``
* ``$HOME/.config/polybar/config.ini``
* ``$XDG_CONFIG_DIRS/polybar/config.ini``
* ``/etc/xdg/polybar/config.ini`` (only if ``XDG_CONFIG_DIRS`` is not set)
* ``/etc/polybar/config.ini``
.. option:: -r, --reload .. option:: -r, --reload
Reload the application when the config file has been modified Reload the application when the config file has been modified
@ -43,14 +48,14 @@ OPTIONS
Print the value of the specified parameter *PARAM* in bar section and exit Print the value of the specified parameter *PARAM* in bar section and exit
.. option:: -m, --list-monitors .. option:: -m, --list-monitors
Print list of available monitors and exit | Print list of available monitors and exit.
| If some monitors are cloned, this will exclude all but one of them.
If some monitors are cloned, this will exclude all but one of them | If polybar was compiled with RandR monitor support, only monitors are listed and not physical outputs.
.. option:: -M, --list-all-monitors .. option:: -M, --list-all-monitors
Print list of available monitors and exit | Print list of all available monitors and exit.
| This includes cloned monitors as well as both physical outputs and RandR monitors (if supported).
This will also include all cloned monitors. | Only the names listed here can be used as monitor names in polybar.
.. option:: -w, --print-wmname .. option:: -w, --print-wmname
Print the generated *WM_NAME* and exit Print the generated *WM_NAME* and exit
@ -61,9 +66,9 @@ OPTIONS
Save png snapshot to *FILE* after running for 3 seconds Save png snapshot to *FILE* after running for 3 seconds
AUTHOR AUTHORS
------ -------
| Michael Carlberg <c@rlberg.se> | Polybar was created by Michael Carlberg and is currently maintained by Patrick Ziegler.
| Contributors can be listed on GitHub. | Contributors can be listed on GitHub.
REPORTING BUGS REPORTING BUGS
@ -72,13 +77,16 @@ Report issues on GitHub <https://github.com/polybar/polybar>
SEE ALSO SEE ALSO
-------- --------
| Full documentation at: <https://github.com/polybar/polybar>
| Project wiki: <https://github.com/polybar/polybar/wiki>
.. only:: man .. only:: man
:manpage:`polybar(5)` :manpage:`polybar-msg`\(1),
:manpage:`polybar`\(5)
.. only:: not man .. only:: not man
:doc:`polybar-msg.1`,
:doc:`polybar.5` :doc:`polybar.5`
| Full documentation at: <https://github.com/polybar/polybar>
| Project wiki: <https://github.com/polybar/polybar/wiki>

View File

@ -32,7 +32,12 @@ places in the following order:
* If the ``-c`` or ``--config`` command line argument is specified, it will use * If the ``-c`` or ``--config`` command line argument is specified, it will use
the path given there. the path given there.
* ``$XDG_CONFIG_HOME/polybar/config`` * ``$XDG_CONFIG_HOME/polybar/config``
* ``$XDG_CONFIG_HOME/polybar/config.ini``
* ``$HOME/.config/polybar/config`` * ``$HOME/.config/polybar/config``
* ``$HOME/.config/polybar/config.ini``
* ``$XDG_CONFIG_DIRS/polybar/config.ini``
* ``/etc/xdg/polybar/config.ini`` (only if ``XDG_CONFIG_DIRS`` is not set)
* ``/etc/polybar/config.ini``
Syntax Syntax
------ ------
@ -126,7 +131,22 @@ in double-quotes:
name = " value " name = " value "
Here ``name`` has a leading and trailing whitespace. Here the value of the ``name`` key has a leading and trailing whitespace.
To treat characters with special meaning as literal characters, you need to
prepend them with the backslash (``\``) escape character:
::
name = "value\\value\\value"
Value of this key ``name`` results in ``value\value\value``.
.. note::
The only character with a special meaning right now is the backslash character
(``\``), which serves as the escape character.
More will be added in the future.
Empty Lines & Comments Empty Lines & Comments
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
@ -144,13 +164,21 @@ not affect polybar's behavior. Comment lines start with either the ``;`` or the
name = value ; comment name = value ; comment
AUTHORS
-------
| Polybar was created by Michael Carlberg and is currently maintained by Patrick Ziegler.
| Contributors can be listed on GitHub.
SEE ALSO SEE ALSO
-------- --------
.. only:: man .. only:: man
:manpage:`polybar(1)` :manpage:`polybar`\(1),
:manpage:`polybar-msg`\(1)
.. only:: not man .. only:: not man
:doc:`polybar.1` :doc:`polybar.1`,
:doc:`polybar-msg.1`

View File

@ -121,6 +121,23 @@ Available Actions
The following modules have actions available. Most of them are already used by The following modules have actions available. Most of them are already used by
the module by default for click and scroll events. the module by default for click and scroll events.
All Modules
^^^^^^^^^^^
These actions are available to all modules and are prefixed with ``module_``.
:``module_show``, ``module_hide``:
Shows/Hides a module. The module is still running in the background when
hidden, it is just not drawn. The starting state can be configured with the
`hidden` configuration option.
.. versionadded:: 3.6.0
:``module_toggle``:
Toggles the visibility of a module.
.. versionadded:: 3.6.0
internal/date internal/date
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -241,6 +258,23 @@ custom/menu
The data has the form ``N-M`` and the action will execute the command The data has the form ``N-M`` and the action will execute the command
in ``menu-N-M-exec``. in ``menu-N-M-exec``.
.. _actions-ipc:
custom/ipc
^^^^^^^^^^
.. versionadded:: 3.6.0
:``send``: *(Has Data)* Replace the contents of the module with the data passed in this action.
:``hook``: *(Has Data)* Trigger the given hook.
The data is the 0-based index of the hook to trigger.
:``next``: Switches to the next hook and wrap around when the last hook was displayed.
:``prev``: Switches to the previous hook and wrap around when the first hook was displayed.
:``reset``: Reset the module to its startup state: either empty or according to the ``initial`` setting.
Deprecated Action Names Deprecated Action Names
----------------------- -----------------------
@ -372,20 +406,22 @@ Below you can see an example of a menu module:
[module/apps] [module/apps]
type = custom/menu type = custom/menu
label-open = Apps
menu-0-0 = Browsers menu-0-0 = Browsers
menu-0-0-exec = menu-open-1 menu-0-0-exec = menu-open-1
menu-0-1 = Multimedia menu-0-1 = Multimedia
menu-0-1-exec = menu-open-2 menu-0-1-exec = menu-open-2
menu-1-0 = Firefox menu-1-0 = Firefox
menu-1-0-exec = firefox & menu-1-0-exec = firefox
menu-1-1 = Chromium menu-1-1 = Chromium
menu-1-1-exec = chromium & menu-1-1-exec = chromium
menu-2-0 = Gimp menu-2-0 = Gimp
menu-2-0-exec = gimp & menu-2-0-exec = gimp
menu-2-1 = Scrot menu-2-1 = Scrot
menu-2-1-exec = scrot & menu-2-1-exec = scrot
This module uses two actions: ``menu-open-1`` and ``menu-open-2``. This module uses two actions: ``menu-open-1`` and ``menu-open-2``.
These are actions with data, the data specifies which level of the menu should These are actions with data, the data specifies which level of the menu should
@ -403,17 +439,19 @@ likely not use ``apps``, but the name of your module.
[module/apps] [module/apps]
type = custom/menu type = custom/menu
label-open = Apps
menu-0-0 = Browsers menu-0-0 = Browsers
menu-0-0-exec = #apps.open.1 menu-0-0-exec = #apps.open.1
menu-0-1 = Multimedia menu-0-1 = Multimedia
menu-0-1-exec = #apps.open.2 menu-0-1-exec = #apps.open.2
menu-1-0 = Firefox menu-1-0 = Firefox
menu-1-0-exec = firefox & menu-1-0-exec = firefox
menu-1-1 = Chromium menu-1-1 = Chromium
menu-1-1-exec = chromium & menu-1-1-exec = chromium
menu-2-0 = Gimp menu-2-0 = Gimp
menu-2-0-exec = gimp & menu-2-0-exec = gimp
menu-2-1 = Scrot menu-2-1 = Scrot
menu-2-1-exec = scrot & menu-2-1-exec = scrot

120
doc/user/ipc.rst Normal file
View File

@ -0,0 +1,120 @@
Inter-process-messaging
=======================
Polybar supports controlling parts of the bar and its modules from the outside
through inter-process-messaging (IPC).
IPC is disabled by default and can be enabled by setting ``enable-ipc = true``
in the bar section.
By default polybar ships with the ``polybar-msg`` tool that is needed to send
messages to polybar.
.. note:: Starting with version 3.6.0, the underlying IPC mechanism has been
completely changed.
Writing directly to the named pipe to send IPC messages has been
deprecated, ``polybar-msg`` should be used exclusively
Everything you could do by directly writing to the named pipe, you
can also do using ``polybar-msg``.
In addition, hook messages are also deprecated; they are replaced by
actions on the :ref:`ipc module <actions-ipc>`.
Unless noted otherwise, everything in this guide is still valid for
older versions.
Sending Messages
----------------
``polybar-msg`` can be called on the commandline like this:
.. code-block:: shell
polybar-msg [-p <pid>] <type> <payload>
If the ``-p`` argument is specified, the message is only sent to the running
polybar instance with the given process ID.
Otherwise, the message is sent to all running polybar processes that have IPC
enabled.
.. note:: IPC messages are only sent to polybar instances running under the
same user as ``polybar-msg`` is running as.
Concretely, ``polybar`` and ``polybar-msg`` use the
``$XDG_RUNTIME_DIR`` environment variable in accordance with the `XDG
Base Directory Specification`_ to determine where to find the socket
to communicate.
If ``polybar`` and ``polybar-msg`` don't have the same value for
``$XDG_RUNTIME_DIR``, they will likely not be able to communicate.
The variable may not be set if you use ``su`` or ``sudo`` to execute
``polybar-msg`` as a different user, often a full user session is
required.
.. _XDG Base Directory Specification: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
The ``<type>`` argument is either :ref:`action <ipc-actions>` or
:ref:`cmd <ipc-commands>`.
The allowed values for ``<payload>`` depend on the type.
Message Types
-------------
.. _ipc-commands:
Commands
^^^^^^^^
Using ``cmd`` for ``<type>``, you can control certain aspects of the bar.
Available values for ``<payload>`` are:
* ``quit``: Terminates the bar
* ``restart``: Restarts the bar in-place
* ``hide``: Hides the bar
* ``show``: Makes the bar visible again, if it was hidden
* ``toggle``: Toggles between the hidden and visible state.
.. _ipc-actions:
Module Actions
^^^^^^^^^^^^^^
For the ``<type>`` ``action``, ``polybar-msg`` can execute
:doc:`module actions <actions>` in the bar.
An action consists of the name of the target module, the name of the action and an optional data string:
::
#<modulename>.<actionname>[.<data>]
More information about action strings and available actions can be found in
:doc:`actions`
For example, if you have a date module named ``date``, you can toggle between
the regular and alternative label with:
.. code-block:: shell
polybar-msg action "#date.toggle"
As an example for an action with data, say you have a menu module named
``powermenu``, you can open the menu level 0 using:
.. code-block:: shell
polybar-msg action "#powermenu.open.0"
.. note::
For convenience, ``polybar-msg`` also allows you to pass the module name,
action name, and data as separate arguments:
.. code-block:: shell
polybar-msg action date toggle
polybar-msg action powermenu open 0
.. versionadded:: 3.6.0

View File

@ -2,14 +2,8 @@
# Generate settings.hpp # Generate settings.hpp
# #
list(APPEND dirs ${CMAKE_CURRENT_LIST_DIR}) list(APPEND XPP_EXTENSION_LIST xpp::randr::extension)
list(APPEND XPP_EXTENSION_LIST xpp::composite::extension)
if(WITH_XRANDR)
list(APPEND XPP_EXTENSION_LIST xpp::randr::extension)
endif()
if(WITH_XCOMPOSITE)
list(APPEND XPP_EXTENSION_LIST xpp::composite::extension)
endif()
if(WITH_XKB) if(WITH_XKB)
list(APPEND XPP_EXTENSION_LIST xpp::xkb::extension) list(APPEND XPP_EXTENSION_LIST xpp::xkb::extension)
endif() endif()
@ -19,7 +13,3 @@ configure_file(
${CMAKE_CURRENT_LIST_DIR}/settings.hpp.cmake ${CMAKE_CURRENT_LIST_DIR}/settings.hpp.cmake
${CMAKE_BINARY_DIR}/generated-sources/settings.hpp ${CMAKE_BINARY_DIR}/generated-sources/settings.hpp
ESCAPE_QUOTES) ESCAPE_QUOTES)
list(APPEND dirs ${CMAKE_BINARY_DIR}/generated-sources/)
set(APP_VERSION ${APP_VERSION} PARENT_SCOPE)
set(dirs ${dirs} PARENT_SCOPE)

View File

@ -162,7 +162,6 @@ namespace mpd {
mpd_status_t m_status{}; mpd_status_t m_status{};
unique_ptr<mpdsong> m_song{}; unique_ptr<mpdsong> m_song{};
mpdstate m_state{mpdstate::UNKNOWN}; mpdstate m_state{mpdstate::UNKNOWN};
chrono::system_clock::time_point m_updated_at{};
bool m_random{false}; bool m_random{false};
bool m_repeat{false}; bool m_repeat{false};

View File

@ -1,15 +1,15 @@
#pragma once #pragma once
#include <chrono>
#include <cstdlib>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <chrono>
#include <cstdlib>
#include "common.hpp" #include "common.hpp"
#include "settings.hpp"
#include "errors.hpp"
#include "components/logger.hpp" #include "components/logger.hpp"
#include "errors.hpp"
#include "settings.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
#if WITH_LIBNL #if WITH_LIBNL
@ -37,7 +37,11 @@ class file_descriptor;
namespace net { namespace net {
DEFINE_ERROR(network_error); DEFINE_ERROR(network_error);
bool is_interface_valid(const string& ifname);
std::pair<string, bool> get_canonical_interface(const string& ifname);
bool is_wireless_interface(const string& ifname); bool is_wireless_interface(const string& ifname);
std::string find_wireless_interface();
std::string find_wired_interface();
// types {{{ // types {{{
@ -58,12 +62,13 @@ namespace net {
struct link_activity { struct link_activity {
bytes_t transmitted{0}; bytes_t transmitted{0};
bytes_t received{0}; bytes_t received{0};
std::chrono::system_clock::time_point time; std::chrono::steady_clock::time_point time;
}; };
struct link_status { struct link_status {
string ip; string ip;
string ip6; string ip6;
string mac;
link_activity previous{}; link_activity previous{};
link_activity current{}; link_activity current{};
}; };
@ -82,8 +87,10 @@ namespace net {
string ip() const; string ip() const;
string ip6() const; string ip6() const;
string mac() const;
string downspeed(int minwidth = 3, const string& unit = "B/s") const; string downspeed(int minwidth = 3, const string& unit = "B/s") const;
string upspeed(int minwidth = 3, const string& unit = "B/s") const; string upspeed(int minwidth = 3, const string& unit = "B/s") const;
string netspeed(int minwidth = 3, const string& unit = "B/s") const;
void set_unknown_up(bool unknown = true); void set_unknown_up(bool unknown = true);
protected: protected:

View File

@ -1,12 +1,13 @@
#pragma once #pragma once
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
#include <atomic>
#include <queue> #include <queue>
#include "common.hpp" #include "common.hpp"
#include "settings.hpp"
#include "errors.hpp" #include "errors.hpp"
#include "settings.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
// fwd // fwd
struct pa_context; struct pa_context;
@ -25,57 +26,62 @@ class pulseaudio {
enum class evtype { NEW = 0, CHANGE, REMOVE, SERVER }; enum class evtype { NEW = 0, CHANGE, REMOVE, SERVER };
using queue = std::queue<evtype>; using queue = std::queue<evtype>;
public: public:
explicit pulseaudio(const logger& logger, string&& sink_name, bool m_max_volume); explicit pulseaudio(const logger& logger, string&& sink_name, bool m_max_volume);
~pulseaudio(); ~pulseaudio();
pulseaudio(const pulseaudio& o) = delete; pulseaudio(const pulseaudio& o) = delete;
pulseaudio& operator=(const pulseaudio& o) = delete; pulseaudio& operator=(const pulseaudio& o) = delete;
const string& get_name(); const string& get_name();
bool wait(); bool wait();
int process_events(); int process_events();
int get_volume(); int get_volume();
double get_decibels(); double get_decibels();
void set_volume(float percentage); void set_volume(float percentage);
void inc_volume(int delta_perc); void inc_volume(int delta_perc);
void set_mute(bool mode); void set_mute(bool mode);
void toggle_mute(); void toggle_mute();
bool is_muted(); bool is_muted();
private: private:
void update_volume(pa_operation *o); void update_volume(pa_operation* o);
static void check_mute_callback(pa_context *context, const pa_sink_info *info, int eol, void *userdata); static void check_mute_callback(pa_context* context, const pa_sink_info* info, int eol, void* userdata);
static void get_sink_volume_callback(pa_context *context, const pa_sink_info *info, int is_last, void *userdata); static void get_sink_volume_callback(pa_context* context, const pa_sink_info* info, int is_last, void* userdata);
static void subscribe_callback(pa_context* context, pa_subscription_event_type_t t, uint32_t idx, void* userdata); static void subscribe_callback(pa_context* context, pa_subscription_event_type_t t, uint32_t idx, void* userdata);
static void simple_callback(pa_context *context, int success, void *userdata); static void simple_callback(pa_context* context, int success, void* userdata);
static void sink_info_callback(pa_context *context, const pa_sink_info *info, int eol, void *userdata); static void sink_info_callback(pa_context* context, const pa_sink_info* info, int eol, void* userdata);
static void context_state_callback(pa_context *context, void *userdata); static void context_state_callback(pa_context* context, void* userdata);
inline void wait_loop(pa_operation *op, pa_threaded_mainloop *loop); inline void wait_loop(pa_operation* op, pa_threaded_mainloop* loop);
const logger& m_log; const logger& m_log;
// used for temporary callback results /**
int success{0}; * Has context_state_callback signalled the mainloop during connection.
pa_cvolume cv; */
bool muted{false}; std::atomic_bool m_state_callback_signal{false};
// default sink name
static constexpr auto DEFAULT_SINK = "@DEFAULT_SINK@";
pa_context* m_context{nullptr}; // used for temporary callback results
pa_threaded_mainloop* m_mainloop{nullptr}; int success{0};
pa_cvolume cv{};
bool muted{false};
// default sink name
static constexpr auto DEFAULT_SINK = "@DEFAULT_SINK@";
queue m_events; pa_context* m_context{nullptr};
pa_threaded_mainloop* m_mainloop{nullptr};
// specified sink name queue m_events;
string spec_s_name;
string s_name;
uint32_t m_index{0};
pa_volume_t m_max_volume{PA_VOLUME_UI_MAX}; // specified sink name
string spec_s_name;
string s_name;
uint32_t m_index{0};
pa_volume_t m_max_volume{PA_VOLUME_UI_MAX};
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -0,0 +1,58 @@
#pragma once
#include <atomic>
#include <chrono>
#include <mutex>
#include "common.hpp"
#include "components/logger.hpp"
POLYBAR_NS
class script_runner {
public:
struct data {
int counter{0};
int pid{-1};
int exit_status{0};
string output;
};
using on_update = std::function<void(const data&)>;
using interval = std::chrono::duration<double>;
script_runner(on_update on_update, const string& exec, const string& exec_if, bool tail, interval interval,
const vector<pair<string, string>>& env);
bool check_condition() const;
interval process();
void clear_output();
void stop();
bool is_stopping() const;
protected:
bool set_output(string&&);
bool set_exit_status(int);
interval run_tail();
interval run();
private:
const logger& m_log;
const on_update m_on_update;
const string m_exec;
const string m_exec_if;
const bool m_tail;
const interval m_interval;
const vector<pair<string, string>> m_env;
data m_data;
std::atomic_bool m_stopping{false};
};
POLYBAR_NS_END

View File

@ -5,6 +5,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <deque> #include <deque>
#include <iterator>
#include "cairo/font.hpp" #include "cairo/font.hpp"
#include "cairo/surface.hpp" #include "cairo/surface.hpp"
@ -21,7 +22,7 @@ POLYBAR_NS
namespace cairo { namespace cairo {
/** /**
* \brief Cairo context * @brief Cairo context
*/ */
class context { class context {
public: public:
@ -116,12 +117,37 @@ namespace cairo {
} }
context& operator<<(const rounded_corners& c) { context& operator<<(const rounded_corners& c) {
double d = M_PI / 180.0;
cairo_new_sub_path(m_c); cairo_new_sub_path(m_c);
cairo_arc(m_c, c.x + c.w - c.radius.top_right, c.y + c.radius.top_right, c.radius.top_right, -90 * d, 0 * d); cairo_arc(
cairo_arc(m_c, c.x + c.w - c.radius.bottom_right, c.y + c.h - c.radius.bottom_right, c.radius.bottom_right, 0 * d, 90 * d); m_c, c.x + c.w - c.radius.top_right, c.y + c.radius.top_right, c.radius.top_right, -90 * degree, 0 * degree);
cairo_arc(m_c, c.x + c.radius.bottom_left, c.y + c.h - c.radius.bottom_left, c.radius.bottom_left, 90 * d, 180 * d); cairo_arc(m_c, c.x + c.w - c.radius.bottom_right, c.y + c.h - c.radius.bottom_right, c.radius.bottom_right,
cairo_arc(m_c, c.x + c.radius.top_left, c.y + c.radius.top_left, c.radius.top_left, 180 * d, 270 * d); 0 * degree, 90 * degree);
cairo_arc(m_c, c.x + c.radius.bottom_left, c.y + c.h - c.radius.bottom_left, c.radius.bottom_left, 90 * degree,
180 * degree);
cairo_arc(m_c, c.x + c.radius.top_left, c.y + c.radius.top_left, c.radius.top_left, 180 * degree, 270 * degree);
cairo_close_path(m_c);
return *this;
}
context& operator<<(const circle_segment& segment) {
cairo_new_sub_path(m_c);
cairo_arc(m_c, segment.x, segment.y, segment.radius, segment.angle_from * degree, segment.angle_to * degree);
switch ((int)segment.angle_to) {
case 0:
cairo_rel_line_to(m_c, -segment.w, 0);
break;
case 90:
cairo_rel_line_to(m_c, 0, -segment.w);
break;
case 180:
cairo_rel_line_to(m_c, segment.w, 0);
break;
default:
cairo_rel_line_to(m_c, 0, segment.w);
break;
}
cairo_arc_negative(m_c, segment.x, segment.y, segment.radius - segment.w, segment.angle_to * degree,
segment.angle_from * degree);
cairo_close_path(m_c); cairo_close_path(m_c);
return *this; return *this;
} }
@ -338,7 +364,10 @@ namespace cairo {
vector<shared_ptr<font>> m_fonts; vector<shared_ptr<font>> m_fonts;
std::deque<pair<double, double>> m_points; std::deque<pair<double, double>> m_points;
int m_activegroups{0}; int m_activegroups{0};
private:
const double degree = M_PI / 180.0;
}; };
} // namespace cairo } // namespace cairo
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -5,6 +5,7 @@
#include "cairo/types.hpp" #include "cairo/types.hpp"
#include "cairo/utils.hpp" #include "cairo/utils.hpp"
#include "common.hpp" #include "common.hpp"
#include "components/logger.hpp"
#include "errors.hpp" #include "errors.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
@ -15,12 +16,12 @@ POLYBAR_NS
namespace cairo { namespace cairo {
/** /**
* \brief Global pointer to the Freetype library handler * @brief Global pointer to the Freetype library handler
*/ */
static FT_Library g_ftlib; static FT_Library g_ftlib;
/** /**
* \brief Abstract font face * @brief Abstract font face
*/ */
class font { class font {
public: public:
@ -51,11 +52,12 @@ namespace cairo {
}; };
/** /**
* \brief Font based on fontconfig/freetype * @brief Font based on fontconfig/freetype
*/ */
class font_fc : public font { class font_fc : public font {
public: public:
explicit font_fc(cairo_t* cairo, FcPattern* pattern, double offset, double dpi_x, double dpi_y) : font(cairo, offset), m_pattern(pattern) { explicit font_fc(cairo_t* cairo, FcPattern* pattern, double offset, double dpi_x, double dpi_y)
: font(cairo, offset), m_pattern(pattern) {
cairo_matrix_t fm; cairo_matrix_t fm;
cairo_matrix_t ctm; cairo_matrix_t ctm;
cairo_matrix_init_scale(&fm, size(dpi_x), size(dpi_y)); cairo_matrix_init_scale(&fm, size(dpi_x), size(dpi_y));
@ -139,8 +141,8 @@ namespace cairo {
property(FC_PIXEL_SIZE, &fc_pixelsize); property(FC_PIXEL_SIZE, &fc_pixelsize);
// Fall back to a default value if the size is 0 // Fall back to a default value if the size is 0
double pixelsize = fc_pixelsize == 0? 10 : fc_pixelsize; double pixelsize = fc_pixelsize == 0 ? 10 : fc_pixelsize;
double size = fc_size == 0? 10 : fc_size; double size = fc_size == 0 ? 10 : fc_size;
// Font size in pixels if we use the pixelsize property // Font size in pixels if we use the pixelsize property
int px_pixelsize = pixelsize + 0.5; int px_pixelsize = pixelsize + 0.5;
@ -155,7 +157,7 @@ namespace cairo {
int px_size = size / 72.0 * dpi + 0.5; int px_size = size / 72.0 * dpi + 0.5;
if (fc_size == 0 && fc_pixelsize == 0) { if (fc_size == 0 && fc_pixelsize == 0) {
return scalable? px_size : px_pixelsize; return scalable ? px_size : px_pixelsize;
} }
if (scalable) { if (scalable) {
@ -165,8 +167,7 @@ namespace cairo {
*/ */
if (fc_size != 0) { if (fc_size != 0) {
return px_size; return px_size;
} } else {
else {
return px_pixelsize; return px_pixelsize;
} }
} else { } else {
@ -176,8 +177,7 @@ namespace cairo {
*/ */
if (fc_pixelsize != 0) { if (fc_pixelsize != 0) {
return px_pixelsize; return px_pixelsize;
} } else {
else {
return px_size; return px_size;
} }
} }
@ -314,7 +314,7 @@ namespace cairo {
auto pattern = FcNameParse((FcChar8*)fontname.c_str()); auto pattern = FcNameParse((FcChar8*)fontname.c_str());
if(!pattern) { if (!pattern) {
logger::make().err("Could not parse font \"%s\"", fontname); logger::make().err("Could not parse font \"%s\"", fontname);
throw application_error("Could not parse font \"" + fontname + "\""); throw application_error("Could not parse font \"" + fontname + "\"");
} }
@ -336,6 +336,6 @@ namespace cairo {
return make_shared<font_fc>(cairo, match, offset, dpi_x, dpi_y); return make_shared<font_fc>(cairo, match, offset, dpi_x, dpi_y);
} }
} } // namespace cairo
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -12,7 +12,7 @@ POLYBAR_NS
namespace cairo { namespace cairo {
/** /**
* \brief Base surface * @brief Base surface
*/ */
class surface { class surface {
public: public:
@ -57,7 +57,7 @@ namespace cairo {
}; };
/** /**
* \brief Surface for xcb * @brief Surface for xcb
*/ */
class xcb_surface : public surface { class xcb_surface : public surface {
public: public:

View File

@ -54,6 +54,14 @@ namespace cairo {
double h; double h;
struct radius radius; struct radius radius;
}; };
struct circle_segment {
double x;
double y;
double w;
double angle_from;
double angle_to;
double radius;
};
struct textblock { struct textblock {
alignment align; alignment align;
string contents; string contents;

View File

@ -10,7 +10,7 @@ POLYBAR_NS
namespace cairo { namespace cairo {
namespace utils { namespace utils {
/** /**
* \brief RAII wrapper used acquire cairo_device_t * @brief RAII wrapper used acquire cairo_device_t
*/ */
class device_lock { class device_lock {
public: public:
@ -24,7 +24,7 @@ namespace cairo {
}; };
/** /**
* \brief RAII wrapper used to access the underlying * @brief RAII wrapper used to access the underlying
* FT_Face of a scaled font face * FT_Face of a scaled font face
*/ */
class ft_face_lock { class ft_face_lock {
@ -39,7 +39,7 @@ namespace cairo {
}; };
/** /**
* \brief Unicode character containing converted codepoint * @brief Unicode character containing converted codepoint
* and details on where its position in the source string * and details on where its position in the source string
*/ */
struct unicode_character { struct unicode_character {
@ -51,17 +51,17 @@ namespace cairo {
using unicode_charlist = std::list<unicode_character>; using unicode_charlist = std::list<unicode_character>;
/** /**
* \see <cairo/cairo.h> * @see <cairo/cairo.h>
*/ */
cairo_operator_t str2operator(const string& mode, cairo_operator_t fallback); cairo_operator_t str2operator(const string& mode, cairo_operator_t fallback);
/** /**
* \brief Create a UCS-4 codepoint from a utf-8 encoded string * @brief Create a UCS-4 codepoint from a utf-8 encoded string
*/ */
bool utf8_to_ucs4(const unsigned char* src, unicode_charlist& result_list); bool utf8_to_ucs4(const unsigned char* src, unicode_charlist& result_list);
/** /**
* \brief Convert a UCS-4 codepoint to a utf-8 encoded string * @brief Convert a UCS-4 codepoint to a utf-8 encoded string
*/ */
size_t ucs4_to_utf8(char* utf8, unsigned int ucs); size_t ucs4_to_utf8(char* utf8, unsigned int ucs);
} }

View File

@ -1,16 +1,15 @@
#pragma once #pragma once
#include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
#include <functional>
#include "settings.hpp" #include "settings.hpp"
#define POLYBAR_NS \ #define POLYBAR_NS namespace polybar {
namespace polybar { #define POLYBAR_NS_END }
#define POLYBAR_NS_END \
}
#ifndef PIPE_READ #ifndef PIPE_READ
#define PIPE_READ 0 #define PIPE_READ 0
@ -21,20 +20,20 @@
POLYBAR_NS POLYBAR_NS
using std::string;
using std::size_t;
using std::move;
using std::forward;
using std::pair;
using std::function;
using std::shared_ptr;
using std::unique_ptr;
using std::make_unique;
using std::make_shared;
using std::make_pair;
using std::array; using std::array;
using std::vector; using std::forward;
using std::function;
using std::make_pair;
using std::make_shared;
using std::make_unique;
using std::move;
using std::pair;
using std::shared_ptr;
using std::size_t;
using std::string;
using std::to_string; using std::to_string;
using std::unique_ptr;
using std::vector;
using namespace std::string_literals; using namespace std::string_literals;
@ -42,4 +41,13 @@ constexpr size_t operator"" _z(unsigned long long n) {
return n; return n;
} }
/**
* Convert an enum to its underlying type.
*/
template <typename E>
constexpr auto to_integral(E e) {
static_assert(std::is_enum<E>::value, "only enums are supported");
return static_cast<typename std::underlying_type_t<E>>(e);
}
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -1,15 +1,15 @@
#pragma once #pragma once
#include <atomic>
#include <cstdlib> #include <cstdlib>
#include <mutex>
#include "common.hpp" #include "common.hpp"
#include "components/eventloop.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "errors.hpp" #include "errors.hpp"
#include "events/signal_fwd.hpp" #include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp" #include "events/signal_receiver.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "tags/action_context.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
#include "x11/types.hpp" #include "x11/types.hpp"
#include "x11/window.hpp" #include "x11/window.hpp"
@ -22,7 +22,6 @@ class connection;
class logger; class logger;
class renderer; class renderer;
class screen; class screen;
class taskqueue;
class tray_manager; class tray_manager;
namespace tags { namespace tags {
@ -30,46 +29,21 @@ namespace tags {
} }
// }}} // }}}
/**
* Allows a new format for pixel sizes (like width in the bar section)
*
* The new format is X%:Z, where X is in [0, 100], and Z is any real value
* describing a pixel offset. The actual value is calculated by X% * max + Z
*/
inline double geom_format_to_pixels(std::string str, double max) {
size_t i;
if ((i = str.find(':')) != std::string::npos) {
std::string a = str.substr(0, i - 1);
std::string b = str.substr(i + 1);
return math_util::max<double>(
0, math_util::percentage_to_value<double>(strtod(a.c_str(), nullptr), max) + strtod(b.c_str(), nullptr));
} else {
if (str.find('%') != std::string::npos) {
return math_util::percentage_to_value<double>(strtod(str.c_str(), nullptr), max);
} else {
return strtod(str.c_str(), nullptr);
}
}
}
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify, class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message, evt::configure_notify>, evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message, evt::configure_notify>,
public signal_receiver<SIGN_PRIORITY_BAR, signals::eventqueue::start, signals::ui::tick, public signal_receiver<SIGN_PRIORITY_BAR, signals::ui::dim_window> {
signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window
#if WITH_XCURSOR
,
signals::ui::cursor_change
#endif
> {
public: public:
using make_type = unique_ptr<bar>; using make_type = unique_ptr<bar>;
static make_type make(bool only_initialize_values = false); static make_type make(eventloop::loop&, bool only_initialize_values = false);
explicit bar(connection&, signal_emitter&, const config&, const logger&, unique_ptr<screen>&&, explicit bar(connection&, signal_emitter&, const config&, const logger&, eventloop::loop&, unique_ptr<screen>&&,
unique_ptr<tray_manager>&&, unique_ptr<tags::dispatch>&&, unique_ptr<taskqueue>&&, bool only_initialize_values); unique_ptr<tray_manager>&&, unique_ptr<tags::dispatch>&&, unique_ptr<tags::action_context>&&,
bool only_initialize_values);
~bar(); ~bar();
const bar_settings settings() const; const bar_settings& settings() const;
void start();
void parse(string&& data, bool force = false); void parse(string&& data, bool force = false);
@ -79,30 +53,36 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
protected: protected:
void restack_window(); void restack_window();
void reconfigue_window(); void reconfigure_window();
void reconfigure_geom(); void reconfigure_geom();
void reconfigure_pos(); void reconfigure_pos();
void reconfigure_struts(); void reconfigure_struts();
void reconfigure_wm_hints(); void reconfigure_wm_hints();
void broadcast_visibility(); void broadcast_visibility();
void handle(const evt::client_message& evt); void map_window();
void handle(const evt::destroy_notify& evt);
void handle(const evt::enter_notify& evt); void trigger_click(mousebtn btn, int pos);
void handle(const evt::leave_notify& evt);
void handle(const evt::motion_notify& evt); void handle(const evt::client_message& evt) override;
void handle(const evt::button_press& evt); void handle(const evt::destroy_notify& evt) override;
void handle(const evt::expose& evt); void handle(const evt::enter_notify& evt) override;
void handle(const evt::property_notify& evt); void handle(const evt::leave_notify& evt) override;
void handle(const evt::configure_notify& evt); void handle(const evt::motion_notify& evt) override;
void handle(const evt::button_press& evt) override;
void handle(const evt::expose& evt) override;
void handle(const evt::property_notify& evt) override;
void handle(const evt::configure_notify& evt) override;
bool on(const signals::ui::dim_window&) override;
bool on(const signals::eventqueue::start&);
bool on(const signals::ui::unshade_window&);
bool on(const signals::ui::shade_window&);
bool on(const signals::ui::tick&);
bool on(const signals::ui::dim_window&);
#if WITH_XCURSOR #if WITH_XCURSOR
bool on(const signals::ui::cursor_change&); /**
* Change cursor to the given cursor name.
*
* The cursor name must be valid (cursor_util::valid)
*/
void change_cursor(const string& name);
#endif #endif
private: private:
@ -110,28 +90,27 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
signal_emitter& m_sig; signal_emitter& m_sig;
const config& m_conf; const config& m_conf;
const logger& m_log; const logger& m_log;
eventloop::loop& m_loop;
unique_ptr<screen> m_screen; unique_ptr<screen> m_screen;
unique_ptr<tray_manager> m_tray; unique_ptr<tray_manager> m_tray;
unique_ptr<renderer> m_renderer; unique_ptr<renderer> m_renderer;
unique_ptr<tags::dispatch> m_dispatch; unique_ptr<tags::dispatch> m_dispatch;
unique_ptr<taskqueue> m_taskqueue; unique_ptr<tags::action_context> m_action_ctxt;
bar_settings m_opts{}; bar_settings m_opts{};
/**
* Name of currently active cursor
*/
string m_cursor{};
string m_lastinput{}; string m_lastinput{};
std::mutex m_mutex{}; bool m_dblclicks{false};
std::atomic<bool> m_dblclicks{false};
mousebtn m_buttonpress_btn{mousebtn::NONE}; eventloop::TimerHandle& m_leftclick_timer{m_loop.handle<eventloop::TimerHandle>()};
int m_buttonpress_pos{0}; eventloop::TimerHandle& m_middleclick_timer{m_loop.handle<eventloop::TimerHandle>()};
#if WITH_XCURSOR eventloop::TimerHandle& m_rightclick_timer{m_loop.handle<eventloop::TimerHandle>()};
int m_motion_pos{0}; eventloop::TimerHandle& m_dim_timer{m_loop.handle<eventloop::TimerHandle>()};
#endif
event_timer m_buttonpress{0L, 5L};
event_timer m_doubleclick{0L, 150L};
double m_anim_step{0.0};
bool m_visible{true}; bool m_visible{true};
}; };

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <map> #include <map>
#include <unordered_set>
#include "common.hpp" #include "common.hpp"
#include "components/types.hpp" #include "components/types.hpp"
@ -21,32 +22,21 @@ class builder {
void reset(); void reset();
string flush(); string flush();
void append(string text); void node(const string& str);
void node(string str); void node(const string& str, int font_index);
void node(string str, int font_index);
void node(const label_t& label); void node(const label_t& label);
void node_repeat(const string& str, size_t n);
void node_repeat(const label_t& label, size_t n); void node_repeat(const label_t& label, size_t n);
void offset(int pixels); void offset(extent_val pixels = ZERO_PX_EXTENT);
void space(size_t width); void spacing(spacing_val size);
void space();
void remove_trailing_space(size_t len);
void remove_trailing_space();
void font(int index); void font(int index);
void font_close(); void font_close();
void background(rgba color); void background(rgba color);
void background_close(); void background_close();
void color(rgba color); void foreground(rgba color);
void color_close(); void foreground_close();
void line_color(const rgba& color); void overline(const rgba& color);
void line_color_close();
void overline_color(rgba color);
void overline_color_close();
void underline_color(rgba color);
void underline_color_close();
void overline(const rgba& color = rgba{});
void overline_close(); void overline_close();
void underline(const rgba& color = rgba{}); void underline(const rgba& color);
void underline_close(); void underline_close();
void control(tags::controltag tag); void control(tags::controltag tag);
void action(mousebtn index, string action); void action(mousebtn index, string action);
@ -55,21 +45,25 @@ class builder {
void action(mousebtn btn, const modules::module_interface& module, string action, string data, const label_t& label); void action(mousebtn btn, const modules::module_interface& module, string action, string data, const label_t& label);
void action_close(); void action_close();
static string get_spacing_format_string(spacing_val space);
protected: protected:
void append(const string& text);
void overline_color_close();
void underline_color_close();
void tag_open(tags::syntaxtag tag, const string& value); void tag_open(tags::syntaxtag tag, const string& value);
void tag_open(tags::attribute attr); void tag_open(tags::attribute attr);
void tag_close(tags::syntaxtag tag); void tag_close(tags::syntaxtag tag);
void tag_close(tags::attribute attr); void tag_close(tags::attribute attr);
private: private:
const bar_settings m_bar; const bar_settings& m_bar;
string m_output; string m_output;
map<tags::syntaxtag, int> m_tags{}; map<tags::syntaxtag, int> m_tags{};
map<tags::syntaxtag, string> m_colors{}; std::unordered_set<tags::attribute> m_attrs{};
map<tags::attribute, bool> m_attrs{};
int m_fontindex{0};
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -33,8 +33,10 @@ class config {
const string& filepath() const; const string& filepath() const;
string section() const; string section() const;
static constexpr const char* BAR_PREFIX = "bar/";
/** /**
* \brief Instruct the config to connect to the xresource manager * @brief Instruct the config to connect to the xresource manager
*/ */
void use_xrm(); void use_xrm();
@ -105,12 +107,38 @@ class config {
return dereference<T>(move(section), move(key), move(string_value), move(result)); return dereference<T>(move(section), move(key), move(string_value), move(result));
} catch (const key_error& err) { } catch (const key_error& err) {
return default_value; return default_value;
} catch (const value_error& err) { } catch (const std::exception& err) {
m_log.err("Invalid value for \"%s.%s\", using default value (reason: %s)", section, key, err.what()); m_log.err("Invalid value for \"%s.%s\", using default value (reason: %s)", section, key, err.what());
return default_value; return default_value;
} }
} }
/**
* Get list of key-value pairs starting with a prefix by section.
*
* Eg: if you have in config `env-FOO = bar`,
* get_with_prefix(section, "env-") will return [{"FOO", "bar"}]
*/
template <typename T = string>
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
auto it = m_sections.find(section);
if (it == m_sections.end()) {
throw key_error("Missing section \"" + section + "\"");
}
vector<pair<string, T>> list;
for (const auto& kv_pair : it->second) {
const auto& key = kv_pair.first;
if (key.substr(0, key_prefix.size()) == key_prefix) {
const T& val = get<T>(section, key);
list.emplace_back(key.substr(key_prefix.size()), val);
}
}
return list;
}
/** /**
* Get list of values for the current bar by name * Get list of values for the current bar by name
*/ */
@ -168,7 +196,7 @@ class config {
} }
} catch (const key_error& err) { } catch (const key_error& err) {
break; break;
} catch (const value_error& err) { } catch (const std::exception& err) {
m_log.err("Invalid value in list \"%s.%s\", using list as-is (reason: %s)", section, key, err.what()); m_log.err("Invalid value in list \"%s.%s\", using list as-is (reason: %s)", section, key, err.what());
return default_value; return default_value;
} }
@ -182,6 +210,8 @@ class config {
return default_value; return default_value;
} }
void ignore_key(const string& section, const string& key) const;
/** /**
* Attempt to load value using the deprecated key name. If successful show a * Attempt to load value using the deprecated key name. If successful show a
* warning message. If it fails load the value using the new key and given * warning message. If it fails load the value using the new key and given
@ -199,7 +229,7 @@ class config {
} }
/** /**
* \see deprecated<T> * @see deprecated<T>
*/ */
template <typename T = string> template <typename T = string>
T deprecated_list(const string& section, const string& old, const string& newkey, const vector<T>& fallback) const { T deprecated_list(const string& section, const string& old, const string& newkey, const vector<T>& fallback) const {

View File

@ -12,7 +12,7 @@ POLYBAR_NS
DEFINE_ERROR(parser_error); DEFINE_ERROR(parser_error);
/** /**
* \brief Exception object for syntax errors * @brief Exception object for syntax errors
* *
* Contains filepath and line number where syntax error was found * Contains filepath and line number where syntax error was found
*/ */
@ -40,15 +40,18 @@ class invalid_name_error : public syntax_error {
*/ */
invalid_name_error(const string& type, const string& name) invalid_name_error(const string& type, const string& name)
: syntax_error(type + " name '" + name + "' is empty or contains forbidden characters.") {} : syntax_error(type + " name '" + name + "' is empty or contains forbidden characters.") {}
invalid_name_error(const string& type, const string& name, const string& file, int line_no)
: syntax_error(type + " name '" + name + "' is empty or contains forbidden characters.", file, line_no) {}
}; };
/** /**
* \brief All different types a line in a config can be * @brief All different types a line in a config can be
*/ */
enum class line_type { KEY, HEADER, COMMENT, EMPTY, UNKNOWN }; enum class line_type { KEY, HEADER, COMMENT, EMPTY, UNKNOWN };
/** /**
* \brief Storage for a single config line * @brief Storage for a single config line
* *
* More sanitized than the actual string of the comment line, with information * More sanitized than the actual string of the comment line, with information
* about line type and structure * about line type and structure
@ -88,25 +91,30 @@ struct line_t {
class config_parser { class config_parser {
public: public:
config_parser(const logger& logger, string&& file, string&& bar); config_parser(const logger& logger, string&& file, string&& bar);
/**
* This prevents passing a temporary logger to the constructor because that would be UB, as the temporary would be
* destroyed once the constructor returns.
*/
config_parser(logger&& logger, string&& file, string&& bar) = delete;
/** /**
* \brief Performs the parsing of the main config file m_file * @brief Performs the parsing of the main config file m_file
* *
* \returns config class instance populated with the parsed config * @returns config class instance populated with the parsed config
* *
* \throws syntax_error If there was any kind of syntax error * @throws syntax_error If there was any kind of syntax error
* \throws parser_error If aynthing else went wrong * @throws parser_error If aynthing else went wrong
*/ */
config::make_type parse(); config::make_type parse();
protected: protected:
/** /**
* \brief Converts the `lines` vector to a proper sectionmap * @brief Converts the `lines` vector to a proper sectionmap
*/ */
sectionmap_t create_sectionmap(); sectionmap_t create_sectionmap();
/** /**
* \brief Parses the given file, extracts key-value pairs and section * @brief Parses the given file, extracts key-value pairs and section
* headers and adds them onto the `lines` vector * headers and adds them onto the `lines` vector
* *
* This method directly resolves `include-file` directives and checks for * This method directly resolves `include-file` directives and checks for
@ -117,7 +125,7 @@ class config_parser {
void parse_file(const string& file, file_list path); void parse_file(const string& file, file_list path);
/** /**
* \brief Parses the given line string to create a line_t struct * @brief Parses the given line string to the given line_t struct
* *
* We use the INI file syntax (https://en.wikipedia.org/wiki/INI_file) * We use the INI file syntax (https://en.wikipedia.org/wiki/INI_file)
* Whitespaces (tested with isspace()) at the beginning and end of a line are ignored * Whitespaces (tested with isspace()) at the beginning and end of a line are ignored
@ -145,15 +153,15 @@ class config_parser {
* *
* sections are defined as [section], everything inside the square brackets is part of the name * sections are defined as [section], everything inside the square brackets is part of the name
* *
* \throws syntax_error if the line isn't well formed. The syntax error * @throws syntax_error if the line isn't well formed. The syntax error
* does not contain the filename or line numbers because parse_line * does not contain the filename or line numbers because parse_line
* doesn't know about those. Whoever calls parse_line needs to * doesn't know about those. Whoever calls parse_line needs to
* catch those exceptions and set the file path and line number * catch those exceptions and set the file path and line number
*/ */
line_t parse_line(const string& line); void parse_line(line_t& line, const string& line_str);
/** /**
* \brief Determines the type of a line read from a config file * @brief Determines the type of a line read from a config file
* *
* Expects that line is trimmed * Expects that line is trimmed
* This mainly looks at the first character and doesn't check if the line is * This mainly looks at the first character and doesn't check if the line is
@ -166,27 +174,33 @@ class config_parser {
static line_type get_line_type(const string& line); static line_type get_line_type(const string& line);
/** /**
* \brief Parse a line containing a section header and returns the header name * @brief Parse a line containing a section header and returns the header name
* *
* Only assumes that the line starts with '[' and is trimmed * Only assumes that the line starts with '[' and is trimmed
* *
* \throws syntax_error if the line doesn't end with ']' or the header name * @throws syntax_error if the line doesn't end with ']' or the header name
* contains forbidden characters * contains forbidden characters
*/ */
string parse_header(const string& line); string parse_header(const line_t& line, const string& line_str);
/** /**
* \brief Parses a line containing a key-value pair and returns the key name * @brief Parses a line containing a key-value pair and returns the key name
* and the value string inside an std::pair * and the value string inside an std::pair
* *
* Only assumes that the line contains '=' at least once and is trimmed * Only assumes that the line contains '=' at least once and is trimmed
* *
* \throws syntax_error if the key contains forbidden characters * @throws syntax_error if the key contains forbidden characters
*/ */
std::pair<string, string> parse_key(const string& line); std::pair<string, string> parse_key(const line_t& line, const string& line_str);
/** /**
* \brief Name of all the files the config includes values from * @brief Parses the given value, checks if the given value contains
* one or more unescaped backslashes and logs an error if yes
*/
string parse_escaped_value(const line_t& line, string&& value, const string& key);
/**
* @brief Name of all the files the config includes values from
* *
* The line_t struct uses indices to this vector to map lines to their * The line_t struct uses indices to this vector to map lines to their
* original files. This allows us to point the user to the exact location * original files. This allows us to point the user to the exact location
@ -196,13 +210,15 @@ class config_parser {
private: private:
/** /**
* \brief Checks if the given name doesn't contain any spaces or characters * @brief Checks if the given name doesn't contain any spaces or characters
* in config_parser::m_forbidden_chars * in config_parser::m_forbidden_chars
*/ */
bool is_valid_name(const string& name); bool is_valid_name(const string& name);
vector<string> get_bars(const sectionmap_t& sections) const;
/** /**
* \brief Whether or not an xresource manager should be used * @brief Whether or not an xresource manager should be used
* *
* Is set to true if any ${xrdb...} references are found * Is set to true if any ${xrdb...} references are found
*/ */
@ -211,7 +227,7 @@ class config_parser {
const logger& m_log; const logger& m_log;
/** /**
* \brief Absolute path to the main config file * @brief Absolute path to the main config file
*/ */
string m_config; string m_config;
@ -221,7 +237,7 @@ class config_parser {
string m_barname; string m_barname;
/** /**
* \brief List of all the lines in the config (with included files) * @brief List of all the lines in the config (with included files)
* *
* The order here matters, as we have not yet associated key-value pairs * The order here matters, as we have not yet associated key-value pairs
* with sections * with sections
@ -229,12 +245,12 @@ class config_parser {
vector<line_t> m_lines; vector<line_t> m_lines;
/** /**
* \brief None of these characters can be used in the key and section names * @brief None of these characters can be used in the key and section names
*/ */
const string m_forbidden_chars{"\"'=;#[](){}:.$\\%"}; const string m_forbidden_chars{"\"'=;#[](){}:.$\\%"};
/** /**
* \brief List of names that cannot be used as section names * @brief List of names that cannot be used as section names
* *
* These strings have a special meaning inside references and so the * These strings have a special meaning inside references and so the
* section [self] could never be referenced. * section [self] could never be referenced.

View File

@ -1,14 +1,13 @@
#pragma once #pragma once
#include <moodycamel/blockingconcurrentqueue.h> #include <mutex>
#include <queue>
#include <thread>
#include "common.hpp" #include "common.hpp"
#include "components/eventloop.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "events/signal_fwd.hpp" #include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp" #include "events/signal_receiver.hpp"
#include "events/types.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "utils/actions.hpp" #include "utils/actions.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
@ -16,6 +15,8 @@
POLYBAR_NS POLYBAR_NS
using std::queue;
// fwd decl {{{ // fwd decl {{{
enum class alignment; enum class alignment;
@ -23,54 +24,70 @@ class bar;
class config; class config;
class connection; class connection;
class inotify_watch; class inotify_watch;
class ipc;
class logger; class logger;
class signal_emitter; class signal_emitter;
namespace modules { namespace modules {
struct module_interface; struct module_interface;
} // namespace modules } // namespace modules
using module_t = shared_ptr<modules::module_interface>; using module_t = shared_ptr<modules::module_interface>;
using modulemap_t = std::map<alignment, vector<module_t>>; using modulemap_t = std::map<alignment, vector<module_t>>;
// }}} // }}}
class controller class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eventqueue::exit_reload,
: public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eventqueue::exit_terminate, signals::eventqueue::notify_change, signals::eventqueue::notify_forcechange,
signals::eventqueue::exit_reload, signals::eventqueue::notify_change, signals::eventqueue::notify_forcechange, signals::eventqueue::check_state, signals::ipc::action, signals::ipc::command,
signals::eventqueue::check_state, signals::ipc::action, signals::ipc::command, signals::ipc::hook, signals::ipc::hook, signals::ui::button_press, signals::ui::update_background> {
signals::ui::ready, signals::ui::button_press, signals::ui::update_background> {
public: public:
using make_type = unique_ptr<controller>; using make_type = unique_ptr<controller>;
static make_type make(unique_ptr<ipc>&& ipc, unique_ptr<inotify_watch>&& config_watch); static make_type make(bool has_ipc, eventloop::loop&);
explicit controller(connection&, signal_emitter&, const logger&, const config&, unique_ptr<bar>&&, unique_ptr<ipc>&&, explicit controller(connection&, signal_emitter&, const logger&, const config&, bool has_ipc, eventloop::loop&);
unique_ptr<inotify_watch>&&);
~controller(); ~controller();
bool run(bool writeback, string snapshot_dst); bool run(bool writeback, string snapshot_dst, bool confwatch);
bool enqueue(event&& evt); void trigger_action(string&& input_data);
bool enqueue(string&& input_data); void trigger_quit(bool reload);
void trigger_update(bool force);
void stop(bool reload);
void signal_handler(int signum);
void conn_cb();
void confwatch_handler(const char* fname);
void notifier_handler();
void screenshot_handler();
protected: protected:
void read_events(); void trigger_notification();
void process_eventqueue(); void read_events(bool confwatch);
void process_inputdata(); void process_inputdata(string&& cmd);
bool process_update(bool force); bool process_update(bool force);
bool on(const signals::eventqueue::notify_change& evt); void update_reload(bool reload);
bool on(const signals::eventqueue::notify_forcechange& evt);
bool on(const signals::eventqueue::exit_terminate& evt); bool on(const signals::eventqueue::notify_change& evt) override;
bool on(const signals::eventqueue::exit_reload& evt); bool on(const signals::eventqueue::notify_forcechange& evt) override;
bool on(const signals::eventqueue::check_state& evt); bool on(const signals::eventqueue::exit_reload& evt) override;
bool on(const signals::ui::ready& evt); bool on(const signals::eventqueue::check_state& evt) override;
bool on(const signals::ui::button_press& evt); bool on(const signals::ui::button_press& evt) override;
bool on(const signals::ipc::action& evt); bool on(const signals::ipc::action& evt) override;
bool on(const signals::ipc::command& evt); bool on(const signals::ipc::command& evt) override;
bool on(const signals::ipc::hook& evt); bool on(const signals::ipc::hook& evt) override;
bool on(const signals::ui::update_background& evt); bool on(const signals::ui::update_background& evt) override;
private: private:
struct notifications_t {
bool quit;
bool reload;
bool update;
bool force_update;
queue<string> inputdata;
notifications_t() : quit(false), reload(false), update(false), force_update(false), inputdata(queue<string>{}) {}
};
size_t setup_modules(alignment align); size_t setup_modules(alignment align);
bool forward_action(const actions_util::action& cmd); bool forward_action(const actions_util::action& cmd);
@ -80,66 +97,56 @@ class controller
signal_emitter& m_sig; signal_emitter& m_sig;
const logger& m_log; const logger& m_log;
const config& m_conf; const config& m_conf;
eventloop::loop& m_loop;
unique_ptr<bar> m_bar; unique_ptr<bar> m_bar;
unique_ptr<ipc> m_ipc; bool m_has_ipc;
unique_ptr<inotify_watch> m_confwatch;
array<unique_ptr<file_descriptor>, 2> m_queuefd{};
/** /**
* \brief State flag * @brief Async handle to notify the eventloop
*
* This handle is used to notify the eventloop of changes which are not otherwise covered by other handles.
* E.g. click actions.
*/ */
std::atomic<bool> m_process_events{false}; eventloop::AsyncHandle& m_notifier{m_loop.handle<eventloop::AsyncHandle>([this]() { notifier_handler(); })};
/** /**
* \brief Destination path of generated snapshot * Notification data for the controller.
*
* Triggers, potentially from other threads, update this structure and notify the controller through m_notifier.
*/
notifications_t m_notifications{};
/**
* @brief Protected m_notifications.
*
* All accesses to m_notifications must hold this mutex.
*/
std::mutex m_notification_mutex{};
/**
* @brief Destination path of generated snapshot
*/ */
string m_snapshot_dst; string m_snapshot_dst;
/** /**
* \brief Controls weather the output gets printed to stdout * @brief Controls weather the output gets printed to stdout
*/ */
bool m_writeback{false}; bool m_writeback{false};
/** /**
* \brief Internal event queue * @brief Loaded modules
*/
moodycamel::BlockingConcurrentQueue<event> m_queue;
/**
* \brief Loaded modules
*/ */
vector<module_t> m_modules; vector<module_t> m_modules;
/** /**
* \brief Loaded modules grouped by block * @brief Loaded modules grouped by block
*/ */
modulemap_t m_blocks; modulemap_t m_blocks;
/** /**
* \brief Maximum number of subsequent events to swallow * @brief Flag to trigger reload after shutdown
*/ */
size_t m_swallow_limit{5U}; bool m_reload{false};
/**
* \brief Time to wait for subsequent events
*/
std::chrono::milliseconds m_swallow_update{10};
/**
* \brief Input data
*/
string m_inputdata;
/**
* \brief Thread for the eventqueue loop
*/
std::thread m_event_thread;
/**
* \brief Misc threads
*/
vector<std::thread> m_threads;
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -0,0 +1,416 @@
#pragma once
#include <uv.h>
#include <stdexcept>
#include "common.hpp"
#include "components/logger.hpp"
#include "utils/mixins.hpp"
POLYBAR_NS
namespace eventloop {
/**
* Runs any libuv function with an integer error code return value and throws an
* exception on error.
*/
#define UV(fun, ...) \
do { \
int res = fun(__VA_ARGS__); \
if (res < 0) { \
throw std::runtime_error(__FILE__ ":"s + std::to_string(__LINE__) + \
": libuv error for '" #fun "(" #__VA_ARGS__ ")': "s + uv_strerror(res)); \
} \
} while (0);
using cb_void = function<void(void)>;
template <typename Event>
using cb_event = std::function<void(const Event&)>;
template <typename Self, typename H>
class Handle : public non_copyable_mixin, public non_movable_mixin {
public:
Handle(uv_loop_t* l) : uv_loop(l) {
get()->data = this;
}
Self& leak(std::unique_ptr<Self> h) {
lifetime_extender = std::move(h);
return *lifetime_extender;
}
void unleak() {
lifetime_extender.reset();
}
H* raw() {
return get();
}
const H* raw() const {
return get();
}
/**
* Close this handle and free associated memory.
*
* After this function returns, any reference to this object should be considered invalid.
*/
void close() {
if (!is_closing()) {
uv_close((uv_handle_t*)get(), [](uv_handle_t* handle) { close_callback(*static_cast<Self*>(handle->data)); });
}
}
bool is_closing() const {
return uv_is_closing(this->template get<uv_handle_t>());
}
bool is_active() {
return uv_is_active(this->template get<uv_handle_t>()) != 0;
}
protected:
/**
* Generic callback function that can be used for all uv handle callbacks.
*
* @tparam Event Event class/struct. Must have a constructor that takes all arguments passed to the uv callback,
* except for the handle argument.
* @tparam Member Pointer to class member where callback function is stored
* @tparam Args Additional arguments in the uv callback. Inferred by the compiler
*/
template <typename Event, cb_event<Event> Self::*Member, typename... Args>
static void event_cb(H* handle, Args... args) {
Self& This = *static_cast<Self*>(handle->data);
(This.*Member)(Event{std::forward<Args>(args)...});
}
/**
* Same as event_cb except that no event is constructed.
*/
template <cb_void Self::*Member>
static void void_event_cb(H* handle) {
Self& This = *static_cast<Self*>(handle->data);
(This.*Member)();
}
static Self& cast(H* handle) {
return *static_cast<Self*>(handle->data);
}
template <typename T = H>
T* get() {
return reinterpret_cast<T*>(&uv_handle);
}
template <typename T = H>
const T* get() const {
return reinterpret_cast<const T*>(&uv_handle);
}
uv_loop_t* loop() const {
return uv_loop;
}
static void close_callback(Self& self) {
self.unleak();
}
static void alloc_callback(uv_handle_t*, size_t, uv_buf_t* buf) {
buf->base = new char[BUFSIZ];
buf->len = BUFSIZ;
}
private:
H uv_handle;
uv_loop_t* uv_loop;
/**
* The handle stores the unique_ptr to itself so that it effectively leaks memory.
*
* This saves us from having to guarantee that the handle's lifetime extends to at least after it is closed.
*
* Once the handle is closed, either explicitly or by walking all handles when the loop shuts down, this reference
* is reset and the object is explicitly destroyed.
*/
std::unique_ptr<Self> lifetime_extender;
};
struct ErrorEvent {
int status;
};
using cb_error = cb_event<ErrorEvent>;
class WriteRequest : public non_copyable_mixin {
public:
using cb_write = cb_void;
WriteRequest(cb_write user_cb, cb_error err_cb) : write_callback(user_cb), write_err_cb(err_cb) {
get()->data = this;
};
static WriteRequest& create(cb_write user_cb, cb_error err_cb) {
auto r = std::make_unique<WriteRequest>(user_cb, err_cb);
return r->leak(std::move(r));
};
uv_write_t* get() {
return &req;
}
/**
* Trigger the write callback.
*
* After that, this object is destroyed.
*/
void trigger(int status) {
if (status < 0) {
if (write_err_cb) {
write_err_cb(ErrorEvent{status});
}
} else {
if (write_callback) {
write_callback();
}
}
unleak();
}
protected:
WriteRequest& leak(std::unique_ptr<WriteRequest> h) {
lifetime_extender = std::move(h);
return *lifetime_extender;
}
void unleak() {
lifetime_extender.reset();
}
private:
uv_write_t req;
cb_write write_callback;
cb_error write_err_cb;
/**
* The handle stores the unique_ptr to itself so that it effectively leaks memory.
*
* This means that each instance manages its own lifetime.
*/
std::unique_ptr<WriteRequest> lifetime_extender;
};
struct SignalEvent {
int signum;
};
class SignalHandle : public Handle<SignalHandle, uv_signal_t> {
public:
using Handle::Handle;
using cb = cb_event<SignalEvent>;
void init();
void start(int signum, cb user_cb);
private:
cb callback;
};
struct PollEvent {
uv_poll_event event;
};
class PollHandle : public Handle<PollHandle, uv_poll_t> {
public:
using Handle::Handle;
using cb = cb_event<PollEvent>;
void init(int fd);
void start(int events, cb user_cb, cb_error err_cb);
static void poll_callback(uv_poll_t*, int status, int events);
private:
cb callback;
cb_error err_cb;
};
struct FSEvent {
const char* path;
uv_fs_event event;
};
class FSEventHandle : public Handle<FSEventHandle, uv_fs_event_t> {
public:
using Handle::Handle;
using cb = cb_event<FSEvent>;
void init();
void start(const string& path, int flags, cb user_cb, cb_error err_cb);
static void fs_event_callback(uv_fs_event_t*, const char* path, int events, int status);
private:
cb callback;
cb_error err_cb;
};
class TimerHandle : public Handle<TimerHandle, uv_timer_t> {
public:
using Handle::Handle;
using cb = cb_void;
void init();
void start(uint64_t timeout, uint64_t repeat, cb user_cb);
void stop();
private:
cb callback;
};
class AsyncHandle : public Handle<AsyncHandle, uv_async_t> {
public:
using Handle::Handle;
using cb = cb_void;
void init(cb user_cb);
void send();
private:
cb callback;
};
struct ReadEvent {
const char* data;
size_t len;
};
template <typename Self, typename H>
class StreamHandle : public Handle<Self, H> {
public:
using Handle<Self, H>::Handle;
using cb_read = cb_event<ReadEvent>;
using cb_read_eof = cb_void;
using cb_connection = cb_void;
void listen(int backlog, cb_connection user_cb, cb_error err_cb) {
this->connection_callback = user_cb;
this->connection_err_cb = err_cb;
UV(uv_listen, this->template get<uv_stream_t>(), backlog, connection_cb);
};
static void connection_cb(uv_stream_t* server, int status) {
auto& self = Self::cast((H*)server);
if (status == 0) {
self.connection_callback();
} else {
self.connection_err_cb(ErrorEvent{status});
}
}
template <typename ClientSelf, typename ClientH>
void accept(StreamHandle<ClientSelf, ClientH>& client) {
UV(uv_accept, this->template get<uv_stream_t>(), client.template get<uv_stream_t>());
}
void read_start(cb_read fun, cb_void eof_cb, cb_error err_cb) {
this->read_callback = fun;
this->read_eof_cb = eof_cb;
this->read_err_cb = err_cb;
UV(uv_read_start, this->template get<uv_stream_t>(), &this->alloc_callback, read_cb);
};
static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
auto& self = Self::cast((H*)handle);
/*
* Wrap pointer so that it gets automatically freed once the function returns (even with exceptions)
*/
auto buf_ptr = unique_ptr<char[]>(buf->base);
if (nread > 0) {
self.read_callback(ReadEvent{buf->base, (size_t)nread});
} else if (nread < 0) {
if (nread != UV_EOF) {
self.read_err_cb(ErrorEvent{(int)nread});
} else {
self.read_eof_cb();
}
}
};
void write(const vector<uint8_t>& data, WriteRequest::cb_write user_cb = {}, cb_error err_cb = {}) {
WriteRequest& req = WriteRequest::create(user_cb, err_cb);
uv_buf_t buf{(char*)data.data(), data.size()};
UV(uv_write, req.get(), this->template get<uv_stream_t>(), &buf, 1,
[](uv_write_t* r, int status) { static_cast<WriteRequest*>(r->data)->trigger(status); });
}
private:
/**
* Callback for receiving data
*/
cb_read read_callback;
/**
* Callback for receiving EOF.
*
* Called after the associated handle has been closed.
*/
cb_read_eof read_eof_cb;
/**
* Called if an error occurs.
*/
cb_error read_err_cb;
cb_connection connection_callback;
cb_error connection_err_cb;
};
class PipeHandle : public StreamHandle<PipeHandle, uv_pipe_t> {
public:
using StreamHandle::StreamHandle;
using cb_connect = cb_void;
void init(bool ipc = false);
void open(int fd);
void bind(const string& path);
void connect(const string& name, cb_connect user_cb, cb_error err_cb);
private:
static void connect_cb(uv_connect_t* req, int status);
cb_error connect_err_cb;
cb_connect connect_callback;
};
class loop : public non_copyable_mixin, public non_movable_mixin {
public:
loop();
~loop();
void run();
void stop();
template <typename H, typename... Args>
H& handle(Args... args) {
auto ptr = make_unique<H>(get());
ptr->init(std::forward<Args>(args)...);
return ptr->leak(std::move(ptr));
}
protected:
uv_loop_t* get() const;
private:
std::unique_ptr<uv_loop_t> m_loop{nullptr};
};
} // namespace eventloop
POLYBAR_NS_END

View File

@ -1,46 +0,0 @@
#pragma once
#include "common.hpp"
#include "settings.hpp"
#include "utils/concurrency.hpp"
POLYBAR_NS
class file_descriptor;
class logger;
class signal_emitter;
/**
* Message types
*/
static constexpr const char* ipc_command_prefix{"cmd:"};
static constexpr const char* ipc_hook_prefix{"hook:"};
static constexpr const char* ipc_action_prefix{"action:"};
/**
* Component used for inter-process communication.
*
* A unique messaging channel will be setup for each
* running process which will allow messages and
* events to be sent to the process externally.
*/
class ipc {
public:
using make_type = unique_ptr<ipc>;
static make_type make();
explicit ipc(signal_emitter& emitter, const logger& logger);
~ipc();
void receive_message();
int get_file_descriptor() const;
private:
signal_emitter& m_sig;
const logger& m_log;
string m_path{};
unique_ptr<file_descriptor> m_fd;
};
POLYBAR_NS_END

View File

@ -7,6 +7,7 @@
#include "cairo/fwd.hpp" #include "cairo/fwd.hpp"
#include "common.hpp" #include "common.hpp"
#include "components/renderer_interface.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "events/signal_fwd.hpp" #include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp" #include "events/signal_receiver.hpp"
@ -27,66 +28,63 @@ using std::map;
struct alignment_block { struct alignment_block {
cairo_pattern_t* pattern; cairo_pattern_t* pattern;
/**
* The x-position where the next thing will be rendered.
*/
double x; double x;
double y; double y;
/**
* The total width of this block.
*
* This is always >= x, but may be larger because a negative offset may
* decrease x, but the width doesn't change.
*/
double width;
}; };
class renderer class renderer : public renderer_interface,
: public signal_receiver<SIGN_PRIORITY_RENDERER, signals::ui::request_snapshot, signals::parser::change_background, public signal_receiver<SIGN_PRIORITY_RENDERER, signals::ui::request_snapshot> {
signals::parser::change_foreground, signals::parser::change_underline, signals::parser::change_overline,
signals::parser::change_font, signals::parser::change_alignment, signals::parser::reverse_colors,
signals::parser::offset_pixel, signals::parser::attribute_set, signals::parser::attribute_unset,
signals::parser::attribute_toggle, signals::parser::action_begin, signals::parser::action_end,
signals::parser::text, signals::parser::control> {
public: public:
using make_type = unique_ptr<renderer>; using make_type = unique_ptr<renderer>;
static make_type make(const bar_settings& bar); static make_type make(const bar_settings& bar, tags::action_context& action_ctxt);
explicit renderer(connection& conn, signal_emitter& sig, const config&, const logger& logger, const bar_settings& bar, explicit renderer(connection& conn, signal_emitter& sig, const config&, const logger& logger, const bar_settings& bar,
background_manager& background_manager); background_manager& background_manager, tags::action_context& action_ctxt);
~renderer(); ~renderer();
xcb_window_t window() const; xcb_window_t window() const;
const vector<action_block> actions() const;
void begin(xcb_rectangle_t rect); void begin(xcb_rectangle_t rect);
void end(); void end();
void flush(); void flush();
#if 0 void render_offset(const tags::context& ctxt, const extent_val offset) override;
void reserve_space(edge side, unsigned int w); void render_text(const tags::context& ctxt, const string&&) override;
#endif
void fill_background(); void change_alignment(const tags::context& ctxt) override;
void fill_overline(double x, double w);
void fill_underline(double x, double w); double get_x(const tags::context& ctxt) const override;
void fill_borders();
void draw_text(const string& contents); double get_alignment_start(const alignment align) const override;
protected: protected:
void fill_background();
void fill_overline(rgba color, double x, double w);
void fill_underline(rgba color, double x, double w);
void fill_borders();
void draw_offset(const tags::context& ctxt, rgba color, double x, double w);
double block_x(alignment a) const; double block_x(alignment a) const;
double block_y(alignment a) const; double block_y(alignment a) const;
double block_w(alignment a) const; double block_w(alignment a) const;
double block_h(alignment a) const; double block_h(alignment a) const;
void increase_x(double dx);
void flush(alignment a); void flush(alignment a);
void highlight_clickable_areas(); void highlight_clickable_areas();
bool on(const signals::ui::request_snapshot& evt); bool on(const signals::ui::request_snapshot& evt) override;
bool on(const signals::parser::change_background& evt);
bool on(const signals::parser::change_foreground& evt);
bool on(const signals::parser::change_underline& evt);
bool on(const signals::parser::change_overline& evt);
bool on(const signals::parser::change_font& evt);
bool on(const signals::parser::change_alignment& evt);
bool on(const signals::parser::reverse_colors&);
bool on(const signals::parser::offset_pixel& evt);
bool on(const signals::parser::attribute_set& evt);
bool on(const signals::parser::attribute_unset& evt);
bool on(const signals::parser::attribute_toggle& evt);
bool on(const signals::parser::action_begin& evt);
bool on(const signals::parser::action_end& evt);
bool on(const signals::parser::text& evt);
bool on(const signals::parser::control& evt);
protected: protected:
struct reserve_area { struct reserve_area {
@ -127,13 +125,6 @@ class renderer
bool m_pseudo_transparency{false}; bool m_pseudo_transparency{false};
alignment m_align; alignment m_align;
std::bitset<3> m_attr;
int m_font{0};
rgba m_bg{};
rgba m_fg{};
rgba m_ol{};
rgba m_ul{};
vector<action_block> m_actions;
bool m_fixedcenter; bool m_fixedcenter;
string m_snapshot_dst; string m_snapshot_dst;

View File

@ -0,0 +1,43 @@
#pragma once
#include <map>
#include "common.hpp"
#include "tags/action_context.hpp"
#include "tags/context.hpp"
POLYBAR_NS
class renderer_interface {
public:
renderer_interface(const tags::action_context& action_ctxt) : m_action_ctxt(action_ctxt){};
virtual void render_offset(const tags::context& ctxt, const extent_val offset) = 0;
virtual void render_text(const tags::context& ctxt, const string&& str) = 0;
virtual void change_alignment(const tags::context& ctxt) = 0;
/**
* Get the current x-coordinate of the renderer.
*
* This position denotes the coordinate where the next thing will be rendered.
* It is relative to the start of the current alignment because the absolute
* positions may not be known until after the renderer has finished.
*/
virtual double get_x(const tags::context& ctxt) const = 0;
/**
* Get the absolute x-position of the start of an alignment block.
*
* The position is absolute in terms of the bar window.
*
* Only call this after all the rendering is finished as these values change
* when new things are rendered.
*/
virtual double get_alignment_start(const alignment align) const = 0;
protected:
/**
* Stores information about actions in the current render cycle.
*/
const tags::action_context& m_action_ctxt;
};
POLYBAR_NS_END

View File

@ -33,7 +33,7 @@ class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
} }
protected: protected:
void handle(const evt::randr_screen_change_notify& evt); void handle(const evt::randr_screen_change_notify& evt) override;
private: private:
connection& m_connection; connection& m_connection;
@ -45,7 +45,9 @@ class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
xcb_window_t m_proxy{XCB_NONE}; xcb_window_t m_proxy{XCB_NONE};
vector<monitor_t> m_monitors; vector<monitor_t> m_monitors;
struct size m_size {0U, 0U}; struct size m_size {
0U, 0U
};
bool m_sigraised{false}; bool m_sigraised{false};
bool have_monitors_changed() const; bool have_monitors_changed() const;

View File

@ -1,62 +0,0 @@
#pragma once
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
#include "common.hpp"
#include "utils/mixins.hpp"
POLYBAR_NS
namespace chrono = std::chrono;
using namespace std::chrono_literals;
class taskqueue : non_copyable_mixin<taskqueue> {
public:
struct deferred {
using clock = chrono::high_resolution_clock;
using duration = chrono::milliseconds;
using timepoint = chrono::time_point<clock, duration>;
using callback = function<void(size_t remaining)>;
explicit deferred(string id, timepoint now, duration wait, callback fn, size_t count)
: id(move(id)), func(move(fn)), now(move(now)), wait(move(wait)), count(move(count)) {}
const string id;
const callback func;
timepoint now;
duration wait;
size_t count;
};
public:
using make_type = unique_ptr<taskqueue>;
static make_type make();
explicit taskqueue();
~taskqueue();
void defer(
string id, deferred::duration ms, deferred::callback fn, deferred::duration offset = 0ms, size_t count = 1);
void defer_unique(
string id, deferred::duration ms, deferred::callback fn, deferred::duration offset = 0ms, size_t count = 1);
bool exist(const string& id);
bool purge(const string& id);
protected:
void tick();
private:
std::thread m_thread;
std::mutex m_lock{};
std::condition_variable m_hold;
std::atomic_bool m_active{true};
vector<unique_ptr<deferred>> m_deferred;
};
POLYBAR_NS_END

View File

@ -46,6 +46,24 @@ enum class mousebtn {
BTN_COUNT, BTN_COUNT,
}; };
static inline mousebtn mousebtn_get_double(mousebtn btn) {
switch (btn) {
case mousebtn::LEFT:
return mousebtn::DOUBLE_LEFT;
case mousebtn::MIDDLE:
return mousebtn::DOUBLE_MIDDLE;
case mousebtn::RIGHT:
return mousebtn::DOUBLE_RIGHT;
default:
return mousebtn::NONE;
}
}
/**
* Order of values for _NET_WM_STRUT_PARTIAL
*
* https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm45381391268672
*/
enum class strut { enum class strut {
LEFT = 0, LEFT = 0,
RIGHT, RIGHT,
@ -71,16 +89,52 @@ struct size {
unsigned int h{1U}; unsigned int h{1U};
}; };
struct side_values { enum class spacing_type { SPACE, POINT, PIXEL };
unsigned int left{0U};
unsigned int right{0U}; enum class extent_type { POINT, PIXEL };
struct spacing_val {
spacing_type type{spacing_type::SPACE};
/**
* Numerical spacing value. Is truncated to an integer for pixels and spaces.
* Must be non-negative.
*/
float value{0};
/**
* Any non-positive number is interpreted as no spacing.
*/
operator bool() const {
return value > 0;
}
}; };
struct edge_values { static constexpr spacing_val ZERO_SPACE = {spacing_type::SPACE, 0};
unsigned int left{0U};
unsigned int right{0U}; /*
unsigned int top{0U}; * Defines the signed length of something as either a number of pixels or points.
unsigned int bottom{0U}; *
* Used for widths, heights, and offsets
*/
struct extent_val {
extent_type type{extent_type::PIXEL};
float value{0};
operator bool() const {
return value != 0;
}
};
static constexpr extent_val ZERO_PX_EXTENT = {extent_type::PIXEL, 0};
struct side_values {
spacing_val left{ZERO_SPACE};
spacing_val right{ZERO_SPACE};
};
struct percentage_with_offset {
double percentage{0};
extent_val offset{ZERO_PX_EXTENT};
}; };
struct radius { struct radius {
@ -109,21 +163,6 @@ struct action {
string command{}; string command{};
}; };
struct action_block : public action {
alignment align{alignment::NONE};
double start_x{0.0};
double end_x{0.0};
bool active{true};
unsigned int width() const {
return static_cast<unsigned int>(end_x - start_x + 0.5);
}
bool test(int point) const {
return static_cast<int>(start_x) <= point && static_cast<int>(end_x) > point;
}
};
struct bar_settings { struct bar_settings {
explicit bar_settings() = default; explicit bar_settings() = default;
bar_settings(const bar_settings& other) = default; bar_settings(const bar_settings& other) = default;
@ -132,16 +171,22 @@ struct bar_settings {
monitor_t monitor{}; monitor_t monitor{};
bool monitor_strict{false}; bool monitor_strict{false};
bool monitor_exact{true}; bool monitor_exact{true};
edge origin{edge::TOP}; bool bottom{false};
struct size size { struct size size {
1U, 1U 1U, 1U
}; };
double dpi_x{0.};
double dpi_y{0.};
position pos{0, 0}; position pos{0, 0};
position offset{0, 0}; position offset{0, 0};
side_values padding{0U, 0U}; side_values padding{ZERO_SPACE, ZERO_SPACE};
side_values margin{0U, 0U}; side_values module_margin{ZERO_SPACE, ZERO_SPACE};
side_values module_margin{0U, 0U}; struct {
edge_values strut{0U, 0U, 0U, 0U}; int top;
int bottom;
} strut{0, 0};
rgba background{0xFF000000}; rgba background{0xFF000000};
rgba foreground{0xFFFFFFFF}; rgba foreground{0xFFFFFFFF};
@ -153,7 +198,10 @@ struct bar_settings {
std::unordered_map<edge, border_settings, enum_hash> borders{}; std::unordered_map<edge, border_settings, enum_hash> borders{};
struct radius radius {}; struct radius radius {};
int spacing{0}; /**
* TODO deprecated
*/
spacing_val spacing{ZERO_SPACE};
label_t separator{}; label_t separator{};
string wmname{}; string wmname{};
@ -161,8 +209,16 @@ struct bar_settings {
bool override_redirect{false}; bool override_redirect{false};
string cursor{}; int double_click_interval{400};
/**
* Name of cursor to use for clickable areas
*/
string cursor_click{}; string cursor_click{};
/**
* Name of cursor to use for scrollable areas
*/
string cursor_scroll{}; string cursor_scroll{};
vector<action> actions{}; vector<action> actions{};
@ -170,12 +226,6 @@ struct bar_settings {
bool dimmed{false}; bool dimmed{false};
double dimvalue{1.0}; double dimvalue{1.0};
bool shaded{false};
struct size shade_size {
1U, 1U
};
position shade_pos{1U, 1U};
const xcb_rectangle_t inner_area(bool abspos = false) const { const xcb_rectangle_t inner_area(bool abspos = false) const {
xcb_rectangle_t rect = this->outer_area(abspos); xcb_rectangle_t rect = this->outer_area(abspos);

View File

@ -13,7 +13,7 @@ POLYBAR_NS
namespace chrono = std::chrono; namespace chrono = std::chrono;
namespace drawtypes { namespace drawtypes {
class animation : public non_copyable_mixin<animation> { class animation : public non_copyable_mixin {
public: public:
explicit animation(unsigned int framerate_ms) : m_framerate_ms(framerate_ms) {} explicit animation(unsigned int framerate_ms) : m_framerate_ms(framerate_ms) {}
explicit animation(vector<label_t>&& frames, int framerate_ms) explicit animation(vector<label_t>&& frames, int framerate_ms)

View File

@ -9,7 +9,7 @@
POLYBAR_NS POLYBAR_NS
namespace drawtypes { namespace drawtypes {
class iconset : public non_copyable_mixin<iconset> { class iconset : public non_copyable_mixin {
public: public:
void add(string id, label_t&& icon); void add(string id, label_t&& icon);
bool has(const string& id); bool has(const string& id);
@ -21,6 +21,6 @@ namespace drawtypes {
}; };
using iconset_t = shared_ptr<iconset>; using iconset_t = shared_ptr<iconset>;
} } // namespace drawtypes
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -18,15 +18,15 @@ namespace drawtypes {
bool zpad{false}; bool zpad{false};
}; };
class label : public non_copyable_mixin<label> { class label : public non_copyable_mixin {
public: public:
rgba m_foreground{}; rgba m_foreground{};
rgba m_background{}; rgba m_background{};
rgba m_underline{}; rgba m_underline{};
rgba m_overline{}; rgba m_overline{};
int m_font{0}; int m_font{0};
side_values m_padding{0U, 0U}; side_values m_padding{ZERO_SPACE, ZERO_SPACE};
side_values m_margin{0U, 0U}; side_values m_margin{ZERO_SPACE, ZERO_SPACE};
size_t m_minlen{0}; size_t m_minlen{0};
/* /*
@ -40,15 +40,15 @@ namespace drawtypes {
alignment m_alignment{alignment::LEFT}; alignment m_alignment{alignment::LEFT};
bool m_ellipsis{true}; bool m_ellipsis{true};
explicit label(string text, int font) : m_font(font), m_text(text), m_tokenized(m_text) {} explicit label(string text, int font) : m_font(font), m_text(move(text)), m_tokenized(m_text) {}
explicit label(string text, rgba foreground = rgba{}, rgba background = rgba{}, rgba underline = rgba{}, explicit label(string text, rgba foreground = rgba{}, rgba background = rgba{}, rgba underline = rgba{},
rgba overline = rgba{}, int font = 0, struct side_values padding = {0U, 0U}, rgba overline = rgba{}, int font = 0, side_values padding = {ZERO_SPACE, ZERO_SPACE},
struct side_values margin = {0U, 0U}, int minlen = 0, size_t maxlen = 0_z, side_values margin = {ZERO_SPACE, ZERO_SPACE}, int minlen = 0, size_t maxlen = 0_z,
alignment label_alignment = alignment::LEFT, bool ellipsis = true, vector<token>&& tokens = {}) alignment label_alignment = alignment::LEFT, bool ellipsis = true, vector<token>&& tokens = {})
: m_foreground(foreground) : m_foreground(move(foreground))
, m_background(background) , m_background(move(background))
, m_underline(underline) , m_underline(move(underline))
, m_overline(overline) , m_overline(move(overline))
, m_font(font) , m_font(font)
, m_padding(padding) , m_padding(padding)
, m_margin(margin) , m_margin(margin)
@ -56,14 +56,14 @@ namespace drawtypes {
, m_maxlen(maxlen) , m_maxlen(maxlen)
, m_alignment(label_alignment) , m_alignment(label_alignment)
, m_ellipsis(ellipsis) , m_ellipsis(ellipsis)
, m_text(text) , m_text(move(text))
, m_tokenized(m_text) , m_tokenized(m_text)
, m_tokens(forward<vector<token>>(tokens)) { , m_tokens(forward<vector<token>>(tokens)) {
assert(!m_ellipsis || (m_maxlen == 0 || m_maxlen >= 3)); assert(!m_ellipsis || (m_maxlen == 0 || m_maxlen >= 3));
} }
string get() const; string get() const;
operator bool(); explicit operator bool();
label_t clone(); label_t clone();
void clear(); void clear();
void reset_tokens(); void reset_tokens();
@ -81,6 +81,6 @@ namespace drawtypes {
label_t load_label(const config& conf, const string& section, string name, bool required = true, string def = ""s); label_t load_label(const config& conf, const string& section, string name, bool required = true, string def = ""s);
label_t load_optional_label(const config& conf, string section, string name, string def = ""s); label_t load_optional_label(const config& conf, string section, string name, string def = ""s);
} // namespace drawtypes } // namespace drawtypes
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -0,0 +1,33 @@
#pragma once
#include <tuple>
#include <vector>
#include "common.hpp"
#include "drawtypes/label.hpp"
#include "utils/mixins.hpp"
using std::tuple;
POLYBAR_NS
namespace drawtypes {
class layouticonset : public non_copyable_mixin {
public:
explicit layouticonset(label_t&& default_icon);
bool add(const string& layout, const string& variant, label_t&& icon);
label_t get(const string& layout, const string& variant) const;
bool contains(const string& layout, const string& variant) const;
static constexpr const char* VARIANT_ANY = "_";
protected:
label_t m_default_icon;
vector<tuple<string, string, label_t>> m_layout_icons;
};
using layouticonset_t = shared_ptr<layouticonset>;
} // namespace drawtypes
POLYBAR_NS_END

View File

@ -9,7 +9,7 @@
POLYBAR_NS POLYBAR_NS
namespace drawtypes { namespace drawtypes {
class progressbar : public non_copyable_mixin<progressbar> { class progressbar : public non_copyable_mixin {
public: public:
explicit progressbar(const bar_settings& bar, int width, string format); explicit progressbar(const bar_settings& bar, int width, string format);

View File

@ -8,12 +8,13 @@
POLYBAR_NS POLYBAR_NS
namespace drawtypes { namespace drawtypes {
class ramp : public non_copyable_mixin<ramp> { class ramp : public non_copyable_mixin {
public: public:
explicit ramp() = default; explicit ramp() = default;
explicit ramp(vector<label_t>&& icons) : m_icons(forward<decltype(icons)>(icons)) {} explicit ramp(vector<label_t>&& icons) : m_icons(forward<decltype(icons)>(icons)) {}
void add(label_t&& icon); void add(label_t&& icon);
void add(label_t&& icon, unsigned weight);
label_t get(size_t index); label_t get(size_t index);
label_t get_by_percentage(float percentage); label_t get_by_percentage(float percentage);
label_t get_by_percentage_with_borders(float percentage, float min, float max); label_t get_by_percentage_with_borders(float percentage, float min, float max);
@ -27,6 +28,6 @@ namespace drawtypes {
using ramp_t = shared_ptr<ramp>; using ramp_t = shared_ptr<ramp>;
ramp_t load_ramp(const config& conf, const string& section, string name, bool required = true); ramp_t load_ramp(const config& conf, const string& section, string name, bool required = true);
} } // namespace drawtypes
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -1,11 +1,7 @@
#pragma once #pragma once
#include "common.hpp" #include "common.hpp"
#include "components/ipc.hpp"
#include "components/types.hpp" #include "components/types.hpp"
#include "tags/dispatch.hpp"
#include "tags/types.hpp"
#include "utils/functional.hpp"
POLYBAR_NS POLYBAR_NS
@ -37,27 +33,21 @@ namespace signals {
using base_type = value_signal<Derived, ValueType>; using base_type = value_signal<Derived, ValueType>;
explicit value_signal(void* data) : m_ptr(data) {} explicit value_signal(void* data) : m_ptr(data) {}
explicit value_signal(ValueType&& data) : m_ptr(&data) {} explicit value_signal(const ValueType&& data) : m_ptr(&data) {}
explicit value_signal(ValueType& data) : m_ptr(&data) {} explicit value_signal(const ValueType& data) : m_ptr(&data) {}
virtual ~value_signal() {} virtual ~value_signal() {}
inline ValueType cast() const { inline const ValueType cast() const {
return *static_cast<ValueType*>(m_ptr); return *static_cast<const ValueType*>(m_ptr);
} }
private: private:
void* m_ptr; const void* m_ptr;
}; };
} // namespace detail } // namespace detail
namespace eventqueue { namespace eventqueue {
struct start : public detail::base_signal<start> {
using base_type::base_type;
};
struct exit_terminate : public detail::base_signal<exit_terminate> {
using base_type::base_type;
};
struct exit_reload : public detail::base_signal<exit_reload> { struct exit_reload : public detail::base_signal<exit_reload> {
using base_type::base_type; using base_type::base_type;
}; };
@ -70,7 +60,7 @@ namespace signals {
struct check_state : public detail::base_signal<check_state> { struct check_state : public detail::base_signal<check_state> {
using base_type::base_type; using base_type::base_type;
}; };
} // namespace eventqueue } // namespace eventqueue
namespace ipc { namespace ipc {
struct command : public detail::value_signal<command, string> { struct command : public detail::value_signal<command, string> {
@ -82,36 +72,21 @@ namespace signals {
struct action : public detail::value_signal<action, string> { struct action : public detail::value_signal<action, string> {
using base_type::base_type; using base_type::base_type;
}; };
} // namespace ipc } // namespace ipc
namespace ui { namespace ui {
struct ready : public detail::base_signal<ready> {
using base_type::base_type;
};
struct changed : public detail::base_signal<changed> { struct changed : public detail::base_signal<changed> {
using base_type::base_type; using base_type::base_type;
}; };
struct tick : public detail::base_signal<tick> {
using base_type::base_type;
};
struct button_press : public detail::value_signal<button_press, string> { struct button_press : public detail::value_signal<button_press, string> {
using base_type::base_type; using base_type::base_type;
}; };
struct cursor_change : public detail::value_signal<cursor_change, string> {
using base_type::base_type;
};
struct visibility_change : public detail::value_signal<visibility_change, bool> { struct visibility_change : public detail::value_signal<visibility_change, bool> {
using base_type::base_type; using base_type::base_type;
}; };
struct dim_window : public detail::value_signal<dim_window, double> { struct dim_window : public detail::value_signal<dim_window, double> {
using base_type::base_type; using base_type::base_type;
}; };
struct shade_window : public detail::base_signal<shade_window> {
using base_type::base_type;
};
struct unshade_window : public detail::base_signal<unshade_window> {
using base_type::base_type;
};
struct request_snapshot : public detail::value_signal<request_snapshot, string> { struct request_snapshot : public detail::value_signal<request_snapshot, string> {
using base_type::base_type; using base_type::base_type;
}; };
@ -123,61 +98,13 @@ namespace signals {
struct update_geometry : public detail::base_signal<update_geometry> { struct update_geometry : public detail::base_signal<update_geometry> {
using base_type::base_type; using base_type::base_type;
}; };
} // namespace ui } // namespace ui
namespace ui_tray { namespace ui_tray {
struct mapped_clients : public detail::value_signal<mapped_clients, unsigned int> { struct mapped_clients : public detail::value_signal<mapped_clients, unsigned int> {
using base_type::base_type; using base_type::base_type;
}; };
} // namespace ui_tray } // namespace ui_tray
} // namespace signals
namespace parser {
struct change_background : public detail::value_signal<change_background, rgba> {
using base_type::base_type;
};
struct change_foreground : public detail::value_signal<change_foreground, rgba> {
using base_type::base_type;
};
struct change_underline : public detail::value_signal<change_underline, rgba> {
using base_type::base_type;
};
struct change_overline : public detail::value_signal<change_overline, rgba> {
using base_type::base_type;
};
struct change_font : public detail::value_signal<change_font, int> {
using base_type::base_type;
};
struct change_alignment : public detail::value_signal<change_alignment, alignment> {
using base_type::base_type;
};
struct reverse_colors : public detail::base_signal<reverse_colors> {
using base_type::base_type;
};
struct offset_pixel : public detail::value_signal<offset_pixel, int> {
using base_type::base_type;
};
struct attribute_set : public detail::value_signal<attribute_set, tags::attribute> {
using base_type::base_type;
};
struct attribute_unset : public detail::value_signal<attribute_unset, tags::attribute> {
using base_type::base_type;
};
struct attribute_toggle : public detail::value_signal<attribute_toggle, tags::attribute> {
using base_type::base_type;
};
struct action_begin : public detail::value_signal<action_begin, action> {
using base_type::base_type;
};
struct action_end : public detail::value_signal<action_end, mousebtn> {
using base_type::base_type;
};
struct text : public detail::value_signal<text, string> {
using base_type::base_type;
};
struct control : public detail::value_signal<control, tags::controltag> {
using base_type::base_type;
};
} // namespace parser
} // namespace signals
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -7,7 +7,7 @@
POLYBAR_NS POLYBAR_NS
/** /**
* \brief Holds all signal receivers attached to the emitter * @brief Holds all signal receivers attached to the emitter
*/ */
extern signal_receivers_t g_signal_receivers; extern signal_receivers_t g_signal_receivers;

View File

@ -15,52 +15,28 @@ namespace signals {
} }
namespace eventqueue { namespace eventqueue {
struct start;
struct exit_terminate;
struct exit_reload; struct exit_reload;
struct notify_change; struct notify_change;
struct notify_forcechange; struct notify_forcechange;
struct check_state; struct check_state;
} // namespace eventqueue } // namespace eventqueue
namespace ipc { namespace ipc {
struct command; struct command;
struct hook; struct hook;
struct action; struct action;
} // namespace ipc } // namespace ipc
namespace ui { namespace ui {
struct ready;
struct changed; struct changed;
struct tick;
struct button_press; struct button_press;
struct cursor_change;
struct visibility_change; struct visibility_change;
struct dim_window; struct dim_window;
struct shade_window;
struct unshade_window;
struct request_snapshot; struct request_snapshot;
struct update_background; struct update_background;
struct update_geometry; struct update_geometry;
} // namespace ui } // namespace ui
namespace ui_tray { namespace ui_tray {
struct mapped_clients; struct mapped_clients;
} }
namespace parser { } // namespace signals
struct change_background;
struct change_foreground;
struct change_underline;
struct change_overline;
struct change_font;
struct change_alignment;
struct reverse_colors;
struct offset_pixel;
struct attribute_set;
struct attribute_unset;
struct attribute_toggle;
struct action_begin;
struct action_end;
struct text;
struct control;
} // namespace parser
} // namespace signals
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <map> #include <map>
#include <unordered_map>
#include <typeindex> #include <typeindex>
#include <typeinfo> #include <typeinfo>
#include <unordered_map>
#include "common.hpp" #include "common.hpp"
@ -42,7 +42,7 @@ class signal_receiver : public signal_receiver_interface,
public signal_receiver_impl<Signal>, public signal_receiver_impl<Signal>,
public signal_receiver_impl<Signals>... { public signal_receiver_impl<Signals>... {
public: public:
prio priority() const { prio priority() const override {
return Priority; return Priority;
} }
}; };

View File

@ -1,59 +0,0 @@
#pragma once
#include <cstdint>
#include "common.hpp"
POLYBAR_NS
enum class event_type {
NONE = 0,
UPDATE,
CHECK,
INPUT,
QUIT,
};
struct event {
int type{0};
bool flag{false};
};
namespace {
inline bool operator==(int id, event_type type) {
return id == static_cast<int>(type);
}
inline bool operator!=(int id, event_type type) {
return !(id == static_cast<int>(type));
}
/**
* Create QUIT event
*/
inline event make_quit_evt(bool reload = false) {
return event{static_cast<int>(event_type::QUIT), reload};
}
/**
* Create UPDATE event
*/
inline event make_update_evt(bool force = false) {
return event{static_cast<int>(event_type::UPDATE), force};
}
/**
* Create INPUT event
*/
inline event make_input_evt() {
return event{static_cast<int>(event_type::INPUT)};
}
/**
* Create CHECK event
*/
inline event make_check_evt() {
return event{static_cast<int>(event_type::CHECK)};
}
}
POLYBAR_NS_END

61
include/ipc/decoder.hpp Normal file
View File

@ -0,0 +1,61 @@
#pragma once
#include "common.hpp"
#include "components/logger.hpp"
#include "errors.hpp"
#include "ipc/msg.hpp"
POLYBAR_NS
namespace ipc {
/**
* Decoder for the IPC message format.
*/
class decoder {
public:
DEFINE_ERROR(error);
/**
* Callback is called whenever a full message is received.
* The message version, message type, and the data is passed.
*/
using cb = std::function<void(uint8_t, type_t, const std::vector<uint8_t>&)>;
decoder(const logger&, cb callback);
/**
* Call this function whenever new data arrives.
*
* Will throw deocder::error in case of error.
* If an error is thrown, this instance is closed and this function may not be called again.
*/
void on_read(const uint8_t* buf, size_t size);
void close() noexcept;
bool closed() const;
protected:
void process_data(const uint8_t*, size_t size);
ssize_t process_header_data(const uint8_t*, size_t size);
ssize_t process_msg_data(const uint8_t*, size_t size);
ipc::header header;
size_t to_read_header{ipc::HEADER_SIZE};
std::vector<uint8_t> buf;
size_t to_read_buf{0};
cb callback;
private:
enum class state {
// Waiting for header data (header does not contain full header)
HEADER,
// Waiting for message data (header contains valid header)
PAYLOAD,
CLOSED,
} state{state::HEADER};
const logger& m_log;
};
} // namespace ipc
POLYBAR_NS_END

14
include/ipc/encoder.hpp Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include "common.hpp"
#include "errors.hpp"
#include "ipc/msg.hpp"
POLYBAR_NS
namespace ipc {
vector<uint8_t> encode(const type_t type, const vector<uint8_t>& data = {});
vector<uint8_t> encode(const type_t type, const string& data);
} // namespace ipc
POLYBAR_NS_END

97
include/ipc/ipc.hpp Normal file
View File

@ -0,0 +1,97 @@
#pragma once
#include <set>
#include "common.hpp"
#include "components/eventloop.hpp"
#include "ipc/decoder.hpp"
#include "settings.hpp"
#include "utils/concurrency.hpp"
POLYBAR_NS
class signal_emitter;
class logger;
namespace ipc {
/**
* Component used for inter-process communication.
*
* A unique messaging channel will be setup for each
* running process which will allow messages and
* events to be sent to the process externally.
*/
class ipc : public non_copyable_mixin, public non_movable_mixin {
public:
using make_type = unique_ptr<ipc>;
static make_type make(eventloop::loop& loop);
explicit ipc(signal_emitter& emitter, const logger& logger, eventloop::loop& loop);
~ipc();
static string get_socket_path(int pid);
protected:
bool trigger_ipc(v0::ipc_type type, const string& msg);
void trigger_legacy_ipc(const string& msg);
void on_connection();
private:
signal_emitter& m_sig;
const logger& m_log;
eventloop::loop& m_loop;
eventloop::PipeHandle& socket;
class connection : public non_copyable_mixin, public non_movable_mixin {
public:
using cb = std::function<void(connection&, uint8_t, type_t, const std::vector<uint8_t>&)>;
connection(eventloop::loop& loop, cb msg_callback);
~connection();
eventloop::PipeHandle& client_pipe;
decoder dec;
};
void remove_client(connection& conn);
/**
* Custom transparent comparator so that we can lookup and erase connections from their reference.
*/
struct connection_cmp {
using is_transparent = std::true_type;
bool operator()(const unique_ptr<connection>& a, const unique_ptr<connection>& b) const {
return a.get() < b.get();
}
bool operator()(const connection& a, const unique_ptr<connection>& b) const {
return &a < b.get();
}
bool operator()(const unique_ptr<connection>& a, const connection& b) const {
return a.get() < &b;
}
};
std::set<unique_ptr<connection>, connection_cmp> connections;
// Named pipe properties (deprecated)
struct fifo {
fifo(eventloop::loop& loop, ipc& ipc, const string& path);
~fifo();
eventloop::PipeHandle& pipe_handle;
};
unique_ptr<fifo> ipc_pipe;
string m_pipe_path{};
/**
* Buffer for the currently received IPC message over the named pipe
*/
string m_pipe_buffer{};
void receive_data(string buf);
void receive_eof();
};
} // namespace ipc
POLYBAR_NS_END

85
include/ipc/msg.hpp Normal file
View File

@ -0,0 +1,85 @@
#pragma once
#include "common.hpp"
#include <array>
POLYBAR_NS
/**
* Defines the binary message format for IPC communications over the IPC socket.
*
* This is an internal API, do not connect to the socket using 3rd party programs, always use `polybar-msg`.
*/
namespace ipc {
/**
* Magic string prefixed to every ipc message.
*
* THIS MUST NEVER CHANGE.
*/
static constexpr std::array<uint8_t, 7> MAGIC = {'p', 'o', 'l', 'y', 'i', 'p', 'c'};
static const string MAGIC_STR = string(reinterpret_cast<const char*>(MAGIC.data()), MAGIC.size());
static constexpr uint8_t VERSION = 0;
using type_t = uint8_t;
/**
* Message type indicating success.
*/
static constexpr type_t TYPE_OK = 0;
static constexpr type_t TYPE_ERR = 255;
union header {
struct header_data {
uint8_t magic[MAGIC.size()];
/**
* Version number of the message format.
*/
uint8_t version;
/**
* Size of the following message in bytes
*/
uint32_t size;
/**
* Type of the message that follows.
*
* Meaning of the values depend on version.
* Only TYPE_OK(0) indicate success and TYPE_ERR(255) always indicates an error, in which case the entire message
* is a string.
*/
type_t type;
} __attribute__((packed)) s;
uint8_t d[sizeof(header_data)];
};
/**
* Size of the standard header shared by all versions.
*
* THIS MUST NEVER CHANGE.
*/
static constexpr size_t HEADER_SIZE = 13;
static_assert(sizeof(header) == HEADER_SIZE, "");
static_assert(sizeof(header::header_data) == HEADER_SIZE, "");
/**
* Definitions for version 0 of the IPC message format.
*
* The format is very simple. The header defines the type (cmd or action) and the payload is the message for that type
* as a string.
*/
namespace v0 {
enum class ipc_type : type_t {
/**
* Message type for ipc commands
*/
CMD = 1,
/**
* Message type for ipc module actions
*/
ACTION = 2,
};
}
} // namespace ipc
POLYBAR_NS_END

16
include/ipc/util.hpp Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include "common.hpp"
POLYBAR_NS
namespace ipc {
string get_runtime_path();
string ensure_runtime_path();
string get_socket_path(const string& pid_string);
string get_socket_path(int pid);
string get_glob_socket_path();
int get_pid_from_socket(const string& path);
} // namespace ipc
POLYBAR_NS_END

View File

@ -36,7 +36,15 @@ namespace modules {
static constexpr auto EVENT_TOGGLE = "toggle"; static constexpr auto EVENT_TOGGLE = "toggle";
protected: protected:
bool input(const string& action, const string& data); void action_inc();
void action_dec();
void action_toggle();
void change_volume(int interval);
void action_epilogue(const vector<mixer_t>& mixers);
vector<mixer_t> get_mixers();
private: private:
static constexpr auto FORMAT_VOLUME = "format-volume"; static constexpr auto FORMAT_VOLUME = "format-volume";

View File

@ -32,7 +32,10 @@ namespace modules {
static constexpr const char* EVENT_DEC = "dec"; static constexpr const char* EVENT_DEC = "dec";
protected: protected:
bool input(const string& action, const string& data); void action_inc();
void action_dec();
void change_value(int value_mod);
private: private:
static constexpr auto TAG_LABEL = "<label>"; static constexpr auto TAG_LABEL = "<label>";
@ -45,6 +48,7 @@ namespace modules {
string m_path_backlight; string m_path_backlight;
float m_max_brightness; float m_max_brightness;
bool m_scroll{false}; bool m_scroll{false};
bool m_use_actual_brightness{true};
brightness_handle m_val; brightness_handle m_val;
brightness_handle m_max; brightness_handle m_max;

View File

@ -48,7 +48,7 @@ namespace modules {
public: public:
explicit battery_module(const bar_settings&, string); explicit battery_module(const bar_settings&, string);
void start(); void start() override;
void teardown(); void teardown();
void idle(); void idle();
bool on_event(inotify_event* event); bool on_event(inotify_event* event);
@ -112,7 +112,7 @@ namespace modules {
string m_timeformat; string m_timeformat;
size_t m_unchanged{SKIP_N_UNCHANGED}; size_t m_unchanged{SKIP_N_UNCHANGED};
chrono::duration<double> m_interval{}; chrono::duration<double> m_interval{};
chrono::system_clock::time_point m_lastpoll; chrono::steady_clock::time_point m_lastpoll;
thread m_subthread; thread m_subthread;
}; };
} // namespace modules } // namespace modules

View File

@ -41,7 +41,7 @@ namespace modules {
public: public:
explicit bspwm_module(const bar_settings&, string); explicit bspwm_module(const bar_settings&, string);
void stop(); void stop() override;
bool has_event(); bool has_event();
bool update(); bool update();
string get_output(); string get_output();
@ -54,7 +54,12 @@ namespace modules {
static constexpr auto EVENT_PREV = "prev"; static constexpr auto EVENT_PREV = "prev";
protected: protected:
bool input(const string& action, const string& data); void action_focus(const string& data);
void action_next();
void action_prev();
void focus_direction(bool next);
void send_command(const string& payload_cmd, const string& log_info);
private: private:
bool handle_status(string& data); bool handle_status(string& data);
@ -83,6 +88,7 @@ namespace modules {
bool m_click{true}; bool m_click{true};
bool m_scroll{true}; bool m_scroll{true};
bool m_occscroll{false};
bool m_revscroll{true}; bool m_revscroll{true};
bool m_pinworkspaces{true}; bool m_pinworkspaces{true};
bool m_inlinemode{false}; bool m_inlinemode{false};

View File

@ -40,13 +40,12 @@ namespace modules {
static constexpr auto TAG_RAMP_LOAD_PER_CORE = "<ramp-coreload>"; static constexpr auto TAG_RAMP_LOAD_PER_CORE = "<ramp-coreload>";
static constexpr auto FORMAT_WARN = "format-warn"; static constexpr auto FORMAT_WARN = "format-warn";
label_t m_label; label_t m_label;
label_t m_labelwarn; label_t m_labelwarn;
progressbar_t m_barload; progressbar_t m_barload;
ramp_t m_rampload; ramp_t m_rampload;
ramp_t m_rampload_core; ramp_t m_rampload_core;
int m_ramp_padding; spacing_val m_ramp_padding{spacing_type::SPACE, 1U};
vector<cpu_time_t> m_cputimes; vector<cpu_time_t> m_cputimes;
vector<cpu_time_t> m_cputimes_prev; vector<cpu_time_t> m_cputimes_prev;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <atomic>
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
@ -21,12 +22,12 @@ namespace modules {
static constexpr auto EVENT_TOGGLE = "toggle"; static constexpr auto EVENT_TOGGLE = "toggle";
protected: protected:
bool input(const string& action, const string& data); void action_toggle();
private: private:
static constexpr auto TAG_LABEL = "<label>"; static constexpr auto TAG_LABEL = "<label>";
// \deprecated: Use <label> // @deprecated: Use <label>
static constexpr auto TAG_DATE = "<date>"; static constexpr auto TAG_DATE = "<date>";
label_t m_label; label_t m_label;
@ -44,6 +45,6 @@ namespace modules {
std::atomic<bool> m_toggled{false}; std::atomic<bool> m_toggled{false};
}; };
} // namespace modules } // namespace modules
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -70,12 +70,13 @@ namespace modules {
static constexpr const char* EVENT_LAYOUT_SET{"setlayoutsafe"}; static constexpr const char* EVENT_LAYOUT_SET{"setlayoutsafe"};
protected: protected:
bool input(const string& action, const string& data) override; bool generic_action(const string& action, const string& data);
private: private:
static constexpr const char* DEFAULT_FORMAT_TAGS{"<label-tags> <label-layout> <label-floating> <label-title>"}; static constexpr const char* DEFAULT_FORMAT_TAGS{"<label-tags> <label-layout> <label-floating> <label-title>"};
static constexpr const char* DEFAULT_STATE_LABEL{"%name%"}; static constexpr const char* DEFAULT_STATE_LABEL{"%name%"};
/** /**
* The tags label is replaced with the tags. Each tag is displayed using one * The tags label is replaced with the tags. Each tag is displayed using one
* of the following labels based on the tag state: * of the following labels based on the tag state:

Some files were not shown because too many files have changed in this diff Show More