Merge remote-tracking branch 'upstream/master' into tray-child-window
This commit is contained in:
commit
4bbb28baaf
27
CHANGELOG.md
27
CHANGELOG.md
@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Breaking
|
### Breaking
|
||||||
- `custom/script`: 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.
|
- `custom/script`: 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.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
- Respect `CMAKE_INSTALL_PREFIX` when installing default config ([`#2770`](https://github.com/polybar/polybar/pull/2770))
|
||||||
|
|
||||||
### Deprecated
|
### 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))
|
- `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))
|
||||||
|
|
||||||
@ -20,6 +23,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `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))
|
- `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))
|
||||||
- `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))
|
- `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))
|
||||||
- Added experimental support for positioning the tray like a module
|
- 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))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- `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))
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
- 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))
|
||||||
|
|
||||||
|
## [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
|
## [3.6.2] - 2022-04-03
|
||||||
### Fixed
|
### Fixed
|
||||||
@ -184,7 +208,8 @@ 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.6.2...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.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.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.6.0]: https://github.com/polybar/polybar/releases/tag/3.6.0
|
||||||
|
@ -63,7 +63,7 @@ endif()
|
|||||||
|
|
||||||
if(BUILD_CONFIG)
|
if(BUILD_CONFIG)
|
||||||
install(FILES ${CMAKE_SOURCE_DIR}/doc/config.ini
|
install(FILES ${CMAKE_SOURCE_DIR}/doc/config.ini
|
||||||
DESTINATION /etc/${PROJECT_NAME}
|
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME}
|
||||||
COMPONENT config)
|
COMPONENT config)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
31
README.md
31
README.md
@ -1,5 +1,6 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="doc/_static/banner.png" alt="Polybar">
|
<img src="doc/_static/banner.png#gh-light-mode-only" alt="Polybar">
|
||||||
|
<img src="doc/_static/banner-dark-mode.png#gh-dark-mode-only" alt="Polybar">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@ -40,6 +41,7 @@ for their desktop environment, without the need of having a black belt in shell
|
|||||||
* [Sponsors](#sponsors)
|
* [Sponsors](#sponsors)
|
||||||
* [Backers](#backers)
|
* [Backers](#backers)
|
||||||
* [License](#license)
|
* [License](#license)
|
||||||
|
* [Signatures](#signatures)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@ -92,15 +94,17 @@ 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)
|
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)
|
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
|
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`.
|
`sudo apt -t bullseye-backports install polybar`.
|
||||||
|
|
||||||
If you are using **Ubuntu** 20.10 (Groovy Gorilla) or later, you can install polybar
|
If you are using **Ubuntu** 20.10 (Groovy Gorilla) or later, you can install polybar
|
||||||
using `sudo apt install polybar`.
|
using `sudo apt install polybar`.
|
||||||
|
|
||||||
If you are using **Arch Linux**, you can install the AUR package
|
If you are using **Arch Linux**, you can install
|
||||||
[polybar](https://aur.archlinux.org/packages/polybar/) to get the latest
|
[polybar](https://archlinux.org/packages/community/x86_64/polybar/) to get the
|
||||||
version, or [polybar-git](https://aur.archlinux.org/packages/polybar-git/) for
|
latest stable release using `sudo pacman -S polybar`. The latest unstable
|
||||||
the most up-to-date (unstable) changes.
|
changes are also available in the
|
||||||
|
[`polybar-git`](https://aur.archlinux.org/packages/polybar-git) package in the
|
||||||
|
AUR.
|
||||||
|
|
||||||
If you are using **Manjaro**, you can install [polybar](https://software.manjaro.org/package/polybar) to get the latest stable release using `sudo pacman -S polybar`.
|
If you are using **Manjaro**, you can install [polybar](https://software.manjaro.org/package/polybar) to get the latest stable release using `sudo pacman -S polybar`.
|
||||||
|
|
||||||
@ -112,14 +116,11 @@ If you are using **Slackware**, polybar is available from the [SlackBuilds](http
|
|||||||
|
|
||||||
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 **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
|
If you are using **openSUSE Leap** or **openSUSE Tumbleweed**, polybar is available from the
|
||||||
[official
|
[official
|
||||||
repositories](https://build.opensuse.org/package/show/openSUSE%3AFactory/polybar)
|
repositories](https://build.opensuse.org/package/show/X11:Utilities/polybar)
|
||||||
and can be installed via `zypper install polybar`.
|
and can be installed via `zypper install polybar`.
|
||||||
|
The package is available for openSUSE Leap 15.3 and above.
|
||||||
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 **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.
|
||||||
|
|
||||||
@ -233,3 +234,9 @@ Polybar accepts donations through [open collective](https://opencollective.com/p
|
|||||||
## 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).
|
||||||
|
|
||||||
|
## Signatures
|
||||||
|
|
||||||
|
Release archives and tags are signed by a maintainer using GPG. Currently
|
||||||
|
everything is signed by [Patrick Ziegler](https://www.patrickziegler.ch/gpg)
|
||||||
|
with fingerprint `1D5791352D51A228D4DDDBA4521E5E03AEBCA1A7`
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Maintainer: Patrick Ziegler <p.ziegler96@gmail.com>
|
# Maintainer: Patrick Ziegler <p.ziegler96@gmail.com>
|
||||||
_pkgname=polybar
|
_pkgname=polybar
|
||||||
pkgname="${_pkgname}-git"
|
pkgname="${_pkgname}-git"
|
||||||
pkgver=3.6.2
|
pkgver=3.6.3
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="A fast and easy-to-use status bar"
|
pkgdesc="A fast and easy-to-use status bar"
|
||||||
# aarch64 is not officially supported by polybar, it is only listed here for convenience
|
# aarch64 is not officially supported by polybar, it is only listed here for convenience
|
||||||
@ -14,6 +14,7 @@ depends=("libuv" "cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm"
|
|||||||
optdepends=("i3-wm: i3 module support")
|
optdepends=("i3-wm: i3 module support")
|
||||||
makedepends=("cmake" "git" "python" "pkg-config" "python-sphinx"
|
makedepends=("cmake" "git" "python" "pkg-config" "python-sphinx"
|
||||||
"python-packaging" "i3-wm")
|
"python-packaging" "i3-wm")
|
||||||
|
backup=("etc/polybar/config.ini")
|
||||||
provides=("polybar")
|
provides=("polybar")
|
||||||
conflicts=("polybar")
|
conflicts=("polybar")
|
||||||
source=("${_pkgname}::git+${url}.git")
|
source=("${_pkgname}::git+${url}.git")
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
# Maintainer: Patrick Ziegler <p.ziegler96@gmail.com>
|
|
||||||
pkgname=polybar
|
|
||||||
pkgver=3.6.2
|
|
||||||
pkgrel=1
|
|
||||||
pkgdesc="A fast and easy-to-use status bar"
|
|
||||||
# aarch64 is not officially supported by polybar, it is only listed here for convenience
|
|
||||||
arch=("i686" "x86_64" "aarch64")
|
|
||||||
url="https://github.com/polybar/polybar"
|
|
||||||
license=("MIT")
|
|
||||||
depends=("libuv" "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")
|
|
||||||
makedepends=("cmake" "python" "pkg-config" "python-sphinx" "python-packaging" "i3-wm")
|
|
||||||
conflicts=("polybar-git")
|
|
||||||
source=(${url}/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.gz)
|
|
||||||
sha256sums=('73becc942e7d2418bc72bd194f2037a2a86792219fd561b663a8509fd5f547a0')
|
|
||||||
_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"
|
|
||||||
}
|
|
BIN
doc/_static/banner-dark-mode.png
vendored
Normal file
BIN
doc/_static/banner-dark-mode.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -114,9 +114,16 @@ 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, a signed git tag is created locally at the tip of the release
|
||||||
* After approval, the GitHub release publishing tool is used to publish the
|
branch and pushed:
|
||||||
release and tag the tip of the release branch (the release commit).
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
git tag -s X.Y.Z <release-branch>
|
||||||
|
git push --tags
|
||||||
|
|
||||||
|
* A `draft release`_ targetting the new tag is created in GitHub's release
|
||||||
|
publishing tools and published.
|
||||||
* After the tag is created, the release branch is manually merged into
|
* After the tag is created, the release branch is manually merged into
|
||||||
``master``.
|
``master``.
|
||||||
Here it is vitally important that the history of the release branch does not
|
Here it is vitally important that the history of the release branch does not
|
||||||
@ -193,8 +200,8 @@ Draft Release
|
|||||||
|
|
||||||
On `GitHub <https://github.com/polybar/polybar/releases/new>`_ a new release
|
On `GitHub <https://github.com/polybar/polybar/releases/new>`_ a new release
|
||||||
should be drafted.
|
should be drafted.
|
||||||
The release targets the tip of the release branch (the release commit), the
|
The release targets the git tag that was just pushed, the name of the release
|
||||||
name of the release and the tag is simply the release number.
|
and the tag is simply the release number.
|
||||||
|
|
||||||
The content of the release message should contain the changelog copied from
|
The content of the release message should contain the changelog copied from
|
||||||
``CHANGELOG.md`` under the heading ``## Changelog``.
|
``CHANGELOG.md`` under the heading ``## Changelog``.
|
||||||
@ -205,6 +212,7 @@ The generated list of PRs can be removed.
|
|||||||
After-Release Checklist
|
After-Release Checklist
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
* Verify the release archive (see `Verify Release`_)
|
||||||
* Make sure all the new functionality is documented on the wiki
|
* Make sure all the new functionality is documented on the wiki
|
||||||
* Mark deprecated features appropriately (see `Deprecations`_)
|
* Mark deprecated features appropriately (see `Deprecations`_)
|
||||||
* Remove all unreleased notes from the wiki (not for patch releases)
|
* Remove all unreleased notes from the wiki (not for patch releases)
|
||||||
@ -212,13 +220,8 @@ After-Release Checklist
|
|||||||
<https://github.com/polybar/polybar/issues/1971>`_. Mention any dependency
|
<https://github.com/polybar/polybar/issues/1971>`_. Mention any dependency
|
||||||
changes and any changes to the build workflow. Also mention any new files are
|
changes and any changes to the build workflow. Also mention any new files are
|
||||||
created by the installation.
|
created by the installation.
|
||||||
* Confirm that the release archive was added to the release.
|
* Create a PR that updates the AUR ``PKGBUILD`` file for the ``polybar-git``
|
||||||
We have a GitHub action workflow called 'Release Workflow' that on every
|
package (push after the release archive is uploaded).
|
||||||
release automatically creates a release archive, uploads it to the release,
|
|
||||||
and adds a 'Download' section to the release body.
|
|
||||||
If this fails for some reason, it should be triggered manually.
|
|
||||||
* Create a PR that updates the AUR ``PKGBUILD`` files for the ``polybar`` and
|
|
||||||
``polybar-git`` packages (push after the release archive is uploaded).
|
|
||||||
* Close the `GitHub Milestone <https://github.com/polybar/polybar/milestones>`_
|
* Close the `GitHub Milestone <https://github.com/polybar/polybar/milestones>`_
|
||||||
for the new release and move open issues (if any) to a later release.
|
for the new release and move open issues (if any) to a later release.
|
||||||
* Activate the version on `Read the Docs
|
* Activate the version on `Read the Docs
|
||||||
@ -226,6 +229,24 @@ After-Release Checklist
|
|||||||
previous versions for the same minor release (e.g. for 3.5.4, deactivate all
|
previous versions for the same minor release (e.g. for 3.5.4, deactivate all
|
||||||
other 3.5.X versions).
|
other 3.5.X versions).
|
||||||
|
|
||||||
|
Verify Release
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Confirm that the release archive was added to the release.
|
||||||
|
We have a GitHub action workflow called 'Release Workflow' that on every
|
||||||
|
release automatically creates a release archive, uploads it to the release,
|
||||||
|
and adds a 'Download' section to the release body.
|
||||||
|
If this fails for some reason, it should be triggered manually.
|
||||||
|
|
||||||
|
Afterwards, download the archive, verify its hash, and sign it:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
gpg --armor --detach-sign polybar-X.Y.Z.tar.gz
|
||||||
|
|
||||||
|
Finally, upload the generated ``polybar-X.Y.Z.tar.gz.asc`` to the GitHub
|
||||||
|
release.
|
||||||
|
|
||||||
Deprecations
|
Deprecations
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -406,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
|
||||||
@ -437,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
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <pulse/pulseaudio.h>
|
#include <pulse/pulseaudio.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
@ -58,6 +59,11 @@ class pulseaudio {
|
|||||||
|
|
||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has context_state_callback signalled the mainloop during connection.
|
||||||
|
*/
|
||||||
|
std::atomic_bool m_state_callback_signal{false};
|
||||||
|
|
||||||
// used for temporary callback results
|
// used for temporary callback results
|
||||||
int success{0};
|
int success{0};
|
||||||
pa_cvolume cv{};
|
pa_cvolume cv{};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "components/eventloop.hpp"
|
#include "components/eventloop.hpp"
|
||||||
@ -42,7 +43,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
|
|
||||||
const bar_settings& settings() const;
|
const bar_settings& settings() const;
|
||||||
|
|
||||||
void start();
|
void start(const string& tray_module_name);
|
||||||
|
|
||||||
void parse(string&& data, bool force = false);
|
void parse(string&& data, bool force = false);
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
string m_cursor{};
|
string m_cursor{};
|
||||||
|
|
||||||
string m_lastinput{};
|
string m_lastinput{};
|
||||||
bool m_dblclicks{false};
|
std::set<mousebtn> m_dblclicks;
|
||||||
|
|
||||||
eventloop::TimerHandle& m_leftclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
eventloop::TimerHandle& m_leftclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
||||||
eventloop::TimerHandle& m_middleclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
eventloop::TimerHandle& m_middleclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
||||||
|
@ -44,6 +44,8 @@ class config {
|
|||||||
|
|
||||||
void set_included(file_list included);
|
void set_included(file_list included);
|
||||||
|
|
||||||
|
file_list get_included_files() const;
|
||||||
|
|
||||||
void warn_deprecated(const string& section, const string& key, string replacement) const;
|
void warn_deprecated(const string& section, const string& key, string replacement) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -225,6 +227,10 @@ class config {
|
|||||||
return value;
|
return value;
|
||||||
} catch (const key_error& err) {
|
} catch (const key_error& err) {
|
||||||
return get<T>(section, newkey, fallback);
|
return get<T>(section, newkey, fallback);
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
||||||
|
err.what());
|
||||||
|
return get<T>(section, newkey, fallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,12 +90,12 @@ 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);
|
||||||
/**
|
/**
|
||||||
* This prevents passing a temporary logger to the constructor because that would be UB, as the temporary would be
|
* This prevents passing a temporary logger to the constructor because that would be UB, as the temporary would be
|
||||||
* destroyed once the constructor returns.
|
* destroyed once the constructor returns.
|
||||||
*/
|
*/
|
||||||
config_parser(logger&& logger, string&& file, string&& bar) = delete;
|
config_parser(logger&& logger, string&& file) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Performs the parsing of the main config file m_file
|
* @brief Performs the parsing of the main config file m_file
|
||||||
@ -105,7 +105,7 @@ class config_parser {
|
|||||||
* @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(string barname);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -231,11 +231,6 @@ class config_parser {
|
|||||||
*/
|
*/
|
||||||
string m_config;
|
string m_config;
|
||||||
|
|
||||||
/**
|
|
||||||
* Is used to resolve ${root...} references
|
|
||||||
*/
|
|
||||||
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)
|
||||||
*
|
*
|
||||||
|
@ -55,6 +55,7 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eve
|
|||||||
void signal_handler(int signum);
|
void signal_handler(int signum);
|
||||||
|
|
||||||
void conn_cb();
|
void conn_cb();
|
||||||
|
void create_config_watcher(const string& fname);
|
||||||
void confwatch_handler(const char* fname);
|
void confwatch_handler(const char* fname);
|
||||||
void notifier_handler();
|
void notifier_handler();
|
||||||
void screenshot_handler();
|
void screenshot_handler();
|
||||||
@ -100,6 +101,7 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eve
|
|||||||
eventloop::loop& m_loop;
|
eventloop::loop& m_loop;
|
||||||
unique_ptr<bar> m_bar;
|
unique_ptr<bar> m_bar;
|
||||||
bool m_has_ipc;
|
bool m_has_ipc;
|
||||||
|
string m_tray_module_name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Async handle to notify the eventloop
|
* @brief Async handle to notify the eventloop
|
||||||
|
@ -77,7 +77,7 @@ class renderer : public renderer_interface,
|
|||||||
void fill_overline(rgba color, double x, double w);
|
void fill_overline(rgba color, double x, double w);
|
||||||
void fill_underline(rgba color, double x, double w);
|
void fill_underline(rgba color, double x, double w);
|
||||||
void fill_borders();
|
void fill_borders();
|
||||||
void draw_offset(rgba color, double x, double w);
|
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;
|
||||||
|
@ -107,6 +107,9 @@ namespace signals {
|
|||||||
struct tray_pos_change : public detail::value_signal<tray_pos_change, int> {
|
struct tray_pos_change : public detail::value_signal<tray_pos_change, int> {
|
||||||
using base_type::base_type;
|
using base_type::base_type;
|
||||||
};
|
};
|
||||||
|
struct tray_visibility : public detail::value_signal<tray_visibility, bool> {
|
||||||
|
using base_type::base_type;
|
||||||
|
};
|
||||||
} // namespace ui_tray
|
} // namespace ui_tray
|
||||||
} // namespace signals
|
} // namespace signals
|
||||||
|
|
||||||
|
@ -37,7 +37,8 @@ namespace signals {
|
|||||||
namespace ui_tray {
|
namespace ui_tray {
|
||||||
struct tray_width_change;
|
struct tray_width_change;
|
||||||
struct tray_pos_change;
|
struct tray_pos_change;
|
||||||
}
|
struct tray_visibility;
|
||||||
|
} // namespace ui_tray
|
||||||
} // namespace signals
|
} // namespace signals
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <uv.h>
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
@ -94,6 +92,6 @@ namespace ipc {
|
|||||||
void receive_data(string buf);
|
void receive_data(string buf);
|
||||||
void receive_eof();
|
void receive_eof();
|
||||||
};
|
};
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -48,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};
|
||||||
|
int m_scroll_interval{5};
|
||||||
bool m_use_actual_brightness{true};
|
bool m_use_actual_brightness{true};
|
||||||
|
|
||||||
brightness_handle m_val;
|
brightness_handle m_val;
|
||||||
|
@ -39,8 +39,10 @@ class connection;
|
|||||||
class background_manager;
|
class background_manager;
|
||||||
class bg_slice;
|
class bg_slice;
|
||||||
|
|
||||||
|
enum class tray_postition { NONE = 0, LEFT, CENTER, RIGHT, MODULE };
|
||||||
|
|
||||||
struct tray_settings {
|
struct tray_settings {
|
||||||
alignment align{alignment::NONE};
|
tray_postition tray_position{tray_postition::NONE};
|
||||||
bool running{false};
|
bool running{false};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,16 +85,16 @@ struct tray_settings {
|
|||||||
rgba foreground{};
|
rgba foreground{};
|
||||||
bool transparent{false};
|
bool transparent{false};
|
||||||
bool detached{false};
|
bool detached{false};
|
||||||
bool adaptive{false};
|
|
||||||
|
|
||||||
xcb_window_t bar_window;
|
xcb_window_t bar_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify, evt::client_message,
|
class tray_manager
|
||||||
evt::configure_request, evt::resize_request, evt::selection_clear, evt::property_notify,
|
: public xpp::event::sink<evt::expose, evt::visibility_notify, evt::client_message, evt::configure_request,
|
||||||
evt::reparent_notify, evt::destroy_notify, evt::map_notify, evt::unmap_notify>,
|
evt::resize_request, evt::selection_clear, evt::property_notify, evt::reparent_notify, evt::destroy_notify,
|
||||||
public signal_receiver<SIGN_PRIORITY_TRAY, signals::ui::visibility_change, signals::ui::dim_window,
|
evt::map_notify, evt::unmap_notify>,
|
||||||
signals::ui::update_background, signals::ui_tray::tray_pos_change> {
|
public signal_receiver<SIGN_PRIORITY_TRAY, signals::ui::visibility_change, signals::ui::dim_window,
|
||||||
|
signals::ui::update_background, signals::ui_tray::tray_pos_change, signals::ui_tray::tray_visibility> {
|
||||||
public:
|
public:
|
||||||
using make_type = unique_ptr<tray_manager>;
|
using make_type = unique_ptr<tray_manager>;
|
||||||
static make_type make(const bar_settings& bar_opts);
|
static make_type make(const bar_settings& bar_opts);
|
||||||
@ -104,7 +106,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
|
|||||||
|
|
||||||
const tray_settings settings() const;
|
const tray_settings settings() const;
|
||||||
|
|
||||||
void setup();
|
void setup(const string& tray_module_name);
|
||||||
void activate();
|
void activate();
|
||||||
void activate_delayed(chrono::duration<double, std::milli> delay = 1s);
|
void activate_delayed(chrono::duration<double, std::milli> delay = 1s);
|
||||||
void deactivate(bool clear_selection = true);
|
void deactivate(bool clear_selection = true);
|
||||||
@ -144,6 +146,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
|
|||||||
void remove_client(xcb_window_t win, bool reconfigure = true);
|
void remove_client(xcb_window_t win, bool reconfigure = true);
|
||||||
int mapped_clients() const;
|
int mapped_clients() const;
|
||||||
bool has_mapped_clients() const;
|
bool has_mapped_clients() const;
|
||||||
|
bool change_visibility(bool visible);
|
||||||
|
|
||||||
void handle(const evt::expose& evt) override;
|
void handle(const evt::expose& evt) override;
|
||||||
void handle(const evt::visibility_notify& evt) override;
|
void handle(const evt::visibility_notify& evt) override;
|
||||||
@ -161,6 +164,7 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
|
|||||||
bool on(const signals::ui::dim_window& evt) override;
|
bool on(const signals::ui::dim_window& evt) override;
|
||||||
bool on(const signals::ui::update_background& evt) override;
|
bool on(const signals::ui::update_background& evt) override;
|
||||||
bool on(const signals::ui_tray::tray_pos_change& evt) override;
|
bool on(const signals::ui_tray::tray_pos_change& evt) override;
|
||||||
|
bool on(const signals::ui_tray::tray_visibility& evt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
connection& m_connection;
|
connection& m_connection;
|
||||||
|
@ -24,6 +24,8 @@ pulseaudio::pulseaudio(const logger& logger, string&& sink_name, bool max_volume
|
|||||||
|
|
||||||
pa_context_set_state_callback(m_context, context_state_callback, this);
|
pa_context_set_state_callback(m_context, context_state_callback, this);
|
||||||
|
|
||||||
|
m_state_callback_signal = false;
|
||||||
|
|
||||||
if (pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) {
|
if (pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr) < 0) {
|
||||||
pa_context_disconnect(m_context);
|
pa_context_disconnect(m_context);
|
||||||
pa_context_unref(m_context);
|
pa_context_unref(m_context);
|
||||||
@ -42,7 +44,17 @@ pulseaudio::pulseaudio(const logger& logger, string&& sink_name, bool max_volume
|
|||||||
|
|
||||||
m_log.trace("pulseaudio: started mainloop");
|
m_log.trace("pulseaudio: started mainloop");
|
||||||
|
|
||||||
pa_threaded_mainloop_wait(m_mainloop);
|
/*
|
||||||
|
* Only wait for signal from the context state callback, if it has not
|
||||||
|
* already signalled the mainloop since pa_context_connect was called,
|
||||||
|
* otherwise, we would wait forever.
|
||||||
|
*
|
||||||
|
* The while loop ensures spurious wakeups are handled.
|
||||||
|
*/
|
||||||
|
while (!m_state_callback_signal) {
|
||||||
|
pa_threaded_mainloop_wait(m_mainloop);
|
||||||
|
}
|
||||||
|
|
||||||
if (pa_context_get_state(m_context) != PA_CONTEXT_READY) {
|
if (pa_context_get_state(m_context) != PA_CONTEXT_READY) {
|
||||||
pa_threaded_mainloop_unlock(m_mainloop);
|
pa_threaded_mainloop_unlock(m_mainloop);
|
||||||
pa_threaded_mainloop_stop(m_mainloop);
|
pa_threaded_mainloop_stop(m_mainloop);
|
||||||
@ -310,6 +322,7 @@ void pulseaudio::context_state_callback(pa_context* context, void* userdata) {
|
|||||||
case PA_CONTEXT_READY:
|
case PA_CONTEXT_READY:
|
||||||
case PA_CONTEXT_TERMINATED:
|
case PA_CONTEXT_TERMINATED:
|
||||||
case PA_CONTEXT_FAILED:
|
case PA_CONTEXT_FAILED:
|
||||||
|
This->m_state_callback_signal = true;
|
||||||
pa_threaded_mainloop_signal(This->m_mainloop, 0);
|
pa_threaded_mainloop_signal(This->m_mainloop, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -46,7 +46,10 @@ script_runner::interval script_runner::process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void script_runner::clear_output() {
|
void script_runner::clear_output() {
|
||||||
set_output("");
|
auto changed = set_output("");
|
||||||
|
if (changed) {
|
||||||
|
m_on_update(m_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_runner::stop() {
|
void script_runner::stop() {
|
||||||
|
@ -131,12 +131,7 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
|
|||||||
m_log.info("Loaded monitor %s (%ix%i+%i+%i)", m_opts.monitor->name, m_opts.monitor->w, m_opts.monitor->h,
|
m_log.info("Loaded monitor %s (%ix%i+%i+%i)", m_opts.monitor->name, m_opts.monitor->w, m_opts.monitor->h,
|
||||||
m_opts.monitor->x, m_opts.monitor->y);
|
m_opts.monitor->x, m_opts.monitor->y);
|
||||||
|
|
||||||
try {
|
m_opts.override_redirect = m_conf.deprecated(bs, "dock", "override-redirect", m_opts.override_redirect);
|
||||||
m_opts.override_redirect = m_conf.get<bool>(bs, "dock");
|
|
||||||
m_conf.warn_deprecated(bs, "dock", "override-redirect");
|
|
||||||
} catch (const key_error& err) {
|
|
||||||
m_opts.override_redirect = m_conf.get(bs, "override-redirect", m_opts.override_redirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_opts.dimvalue = m_conf.get(bs, "dim-value", 1.0);
|
m_opts.dimvalue = m_conf.get(bs, "dim-value", 1.0);
|
||||||
m_opts.dimvalue = math_util::cap(m_opts.dimvalue, 0.0, 1.0);
|
m_opts.dimvalue = math_util::cap(m_opts.dimvalue, 0.0, 1.0);
|
||||||
@ -393,13 +388,14 @@ void bar::parse(string&& data, bool force) {
|
|||||||
|
|
||||||
auto rect = m_opts.inner_area();
|
auto rect = m_opts.inner_area();
|
||||||
|
|
||||||
if (m_tray && !m_tray->settings().detached && m_tray->settings().num_mapped_clients > 0 && !m_tray->settings().adaptive) {
|
if (m_tray && !m_tray->settings().detached && m_tray->settings().num_mapped_clients > 0 &&
|
||||||
auto trayalign = m_tray->settings().align;
|
m_tray->settings().tray_position != tray_postition::MODULE) {
|
||||||
|
auto tray_pos = m_tray->settings().tray_position;
|
||||||
auto traywidth = m_tray->settings().win_size.w;
|
auto traywidth = m_tray->settings().win_size.w;
|
||||||
if (trayalign == alignment::LEFT) {
|
if (tray_pos == tray_postition::LEFT) {
|
||||||
rect.x += traywidth;
|
rect.x += traywidth;
|
||||||
rect.width -= traywidth;
|
rect.width -= traywidth;
|
||||||
} else if (trayalign == alignment::RIGHT) {
|
} else if (tray_pos == tray_postition::RIGHT) {
|
||||||
rect.width -= traywidth;
|
rect.width -= traywidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,19 +411,12 @@ void bar::parse(string&& data, bool force) {
|
|||||||
|
|
||||||
m_renderer->end();
|
m_renderer->end();
|
||||||
|
|
||||||
const auto check_dblclicks = [&]() -> bool {
|
m_dblclicks.clear();
|
||||||
if (m_action_ctxt->has_double_click()) {
|
for (auto&& action : m_opts.actions) {
|
||||||
return true;
|
if (static_cast<int>(action.button) >= static_cast<int>(mousebtn::DOUBLE_LEFT)) {
|
||||||
|
m_dblclicks.insert(action.button);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (auto&& action : m_opts.actions) {
|
|
||||||
if (static_cast<int>(action.button) >= static_cast<int>(mousebtn::DOUBLE_LEFT)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
m_dblclicks = check_dblclicks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -440,10 +429,11 @@ void bar::hide() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
m_log.info("Hiding bar window");
|
m_log.info("Hiding bar window");
|
||||||
|
m_visible = false;
|
||||||
|
reconfigure_struts();
|
||||||
m_sig.emit(visibility_change{false});
|
m_sig.emit(visibility_change{false});
|
||||||
m_connection.unmap_window_checked(m_opts.x_data.window);
|
m_connection.unmap_window_checked(m_opts.x_data.window);
|
||||||
m_connection.flush();
|
m_connection.flush();
|
||||||
m_visible = false;
|
|
||||||
} catch (const exception& err) {
|
} catch (const exception& err) {
|
||||||
m_log.err("Failed to unmap bar window (err=%s", err.what());
|
m_log.err("Failed to unmap bar window (err=%s", err.what());
|
||||||
}
|
}
|
||||||
@ -556,42 +546,46 @@ void bar::reconfigure_pos() {
|
|||||||
* Reconfigure window strut values
|
* Reconfigure window strut values
|
||||||
*/
|
*/
|
||||||
void bar::reconfigure_struts() {
|
void bar::reconfigure_struts() {
|
||||||
auto geom = m_connection.get_geometry(m_connection.root());
|
window win{m_connection, m_opts.x_data.window};
|
||||||
int h = m_opts.size.h + m_opts.offset.y;
|
if (m_visible) {
|
||||||
|
auto geom = m_connection.get_geometry(m_connection.root());
|
||||||
|
int h = m_opts.size.h + m_opts.offset.y;
|
||||||
|
|
||||||
// Apply user-defined margins
|
// Apply user-defined margins
|
||||||
if (m_opts.bottom) {
|
|
||||||
h += m_opts.strut.top;
|
|
||||||
} else {
|
|
||||||
h += m_opts.strut.bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
h = std::max(h, 0);
|
|
||||||
|
|
||||||
int correction = 0;
|
|
||||||
|
|
||||||
// Only apply correction if any space is requested
|
|
||||||
if (h > 0) {
|
|
||||||
/*
|
|
||||||
* Strut coordinates have to be relative to root window and not any monitor.
|
|
||||||
* If any monitor is not aligned at the top or bottom
|
|
||||||
*/
|
|
||||||
if (m_opts.bottom) {
|
if (m_opts.bottom) {
|
||||||
/*
|
h += m_opts.strut.top;
|
||||||
* For bottom-algined bars, the correction is the number of pixels between
|
|
||||||
* the root window's bottom edge and the monitor's bottom edge
|
|
||||||
*/
|
|
||||||
correction = geom->height - (m_opts.monitor->y + m_opts.monitor->h);
|
|
||||||
} else {
|
} else {
|
||||||
// For top-aligned bars, we simply add the monitor's y-position
|
h += m_opts.strut.bottom;
|
||||||
correction = m_opts.monitor->y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
correction = std::max(correction, 0);
|
h = std::max(h, 0);
|
||||||
}
|
|
||||||
|
|
||||||
window win{m_connection, m_opts.x_data.window};
|
int correction = 0;
|
||||||
win.reconfigure_struts(m_opts.size.w, h + correction, m_opts.pos.x, m_opts.bottom);
|
|
||||||
|
// Only apply correction if any space is requested
|
||||||
|
if (h > 0) {
|
||||||
|
/*
|
||||||
|
* Strut coordinates have to be relative to root window and not any monitor.
|
||||||
|
* If any monitor is not aligned at the top or bottom
|
||||||
|
*/
|
||||||
|
if (m_opts.bottom) {
|
||||||
|
/*
|
||||||
|
* For bottom-algined bars, the correction is the number of pixels between
|
||||||
|
* the root window's bottom edge and the monitor's bottom edge
|
||||||
|
*/
|
||||||
|
correction = geom->height - (m_opts.monitor->y + m_opts.monitor->h);
|
||||||
|
} else {
|
||||||
|
// For top-aligned bars, we simply add the monitor's y-position
|
||||||
|
correction = m_opts.monitor->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
correction = std::max(correction, 0);
|
||||||
|
}
|
||||||
|
win.reconfigure_struts(m_opts.size.w, h + correction, m_opts.pos.x, m_opts.bottom);
|
||||||
|
} else {
|
||||||
|
// Set struts to 0 for invisible bars
|
||||||
|
win.reconfigure_struts(0, 0, 0, m_opts.bottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -634,6 +628,8 @@ void bar::broadcast_visibility() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bar::map_window() {
|
void bar::map_window() {
|
||||||
|
m_visible = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* First reconfigures the window so that WMs that discard some information
|
* First reconfigures the window so that WMs that discard some information
|
||||||
* when unmapping have the correct window properties (geometry etc).
|
* when unmapping have the correct window properties (geometry etc).
|
||||||
@ -648,8 +644,6 @@ void bar::map_window() {
|
|||||||
* mapping. Additionally updating the window position after mapping seems to fix that.
|
* mapping. Additionally updating the window position after mapping seems to fix that.
|
||||||
*/
|
*/
|
||||||
reconfigure_pos();
|
reconfigure_pos();
|
||||||
|
|
||||||
m_visible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bar::trigger_click(mousebtn btn, int pos) {
|
void bar::trigger_click(mousebtn btn, int pos) {
|
||||||
@ -818,9 +812,12 @@ void bar::handle(const evt::button_press& evt) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mousebtn double_btn = mousebtn_get_double(btn);
|
||||||
|
bool has_dblclick = m_dblclicks.count(double_btn) || m_action_ctxt->has_action(double_btn, pos) != tags::NO_ACTION;
|
||||||
|
|
||||||
// If there are no double click handlers defined we can
|
// If there are no double click handlers defined we can
|
||||||
// just by-pass the click timer handling
|
// just by-pass the click timer handling
|
||||||
if (!m_dblclicks) {
|
if (!has_dblclick) {
|
||||||
trigger_click(btn, pos);
|
trigger_click(btn, pos);
|
||||||
} else if (btn == mousebtn::LEFT) {
|
} else if (btn == mousebtn::LEFT) {
|
||||||
check_double(m_leftclick_timer, btn, pos);
|
check_double(m_leftclick_timer, btn, pos);
|
||||||
@ -876,7 +873,7 @@ void bar::handle(const evt::configure_notify&) {
|
|||||||
m_sig.emit(signals::ui::update_geometry{});
|
m_sig.emit(signals::ui::update_geometry{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void bar::start() {
|
void bar::start(const string& tray_module_name) {
|
||||||
m_log.trace("bar: Create renderer");
|
m_log.trace("bar: Create renderer");
|
||||||
m_renderer = renderer::make(m_opts, *m_action_ctxt, *m_tray);
|
m_renderer = renderer::make(m_opts, *m_action_ctxt, *m_tray);
|
||||||
|
|
||||||
@ -907,7 +904,7 @@ void bar::start() {
|
|||||||
m_renderer->end();
|
m_renderer->end();
|
||||||
|
|
||||||
m_log.trace("bar: Setup tray manager");
|
m_log.trace("bar: Setup tray manager");
|
||||||
m_tray->setup();
|
m_tray->setup(tray_module_name);
|
||||||
|
|
||||||
broadcast_visibility();
|
broadcast_visibility();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,10 @@ void config::set_included(file_list included) {
|
|||||||
m_included = move(included);
|
m_included = move(included);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_list config::get_included_files() const {
|
||||||
|
return m_included;
|
||||||
|
}
|
||||||
|
|
||||||
void config::ignore_key(const string& section, const string& key) const {
|
void config::ignore_key(const string& section, const string& key) const {
|
||||||
if (has(section, key)) {
|
if (has(section, key)) {
|
||||||
m_log.warn(
|
m_log.warn(
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
config_parser::config_parser(const logger& logger, string&& file, string&& bar)
|
config_parser::config_parser(const logger& logger, string&& file)
|
||||||
: m_log(logger), m_config(file_util::expand(file)), m_barname(move(bar)) {}
|
: m_log(logger), m_config(file_util::expand(file)) {}
|
||||||
|
|
||||||
config::make_type config_parser::parse() {
|
config::make_type config_parser::parse(string barname) {
|
||||||
m_log.notice("Parsing config file: %s", m_config);
|
m_log.notice("Parsing config file: %s", m_config);
|
||||||
|
|
||||||
parse_file(m_config, {});
|
parse_file(m_config, {});
|
||||||
@ -21,21 +21,21 @@ config::make_type config_parser::parse() {
|
|||||||
sectionmap_t sections = create_sectionmap();
|
sectionmap_t sections = create_sectionmap();
|
||||||
|
|
||||||
vector<string> bars = get_bars(sections);
|
vector<string> bars = get_bars(sections);
|
||||||
if (m_barname.empty()) {
|
if (barname.empty()) {
|
||||||
if (bars.size() == 1) {
|
if (bars.size() == 1) {
|
||||||
m_barname = bars[0];
|
barname = bars[0];
|
||||||
} else if (bars.empty()) {
|
} else if (bars.empty()) {
|
||||||
throw application_error("The config file contains no bar.");
|
throw application_error("The config file contains no bar.");
|
||||||
} else {
|
} else {
|
||||||
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
||||||
string_util::join(bars, ", "));
|
string_util::join(bars, ", "));
|
||||||
}
|
}
|
||||||
} else if (sections.find("bar/" + m_barname) == sections.end()) {
|
} else if (sections.find("bar/" + barname) == sections.end()) {
|
||||||
if (bars.empty()) {
|
if (bars.empty()) {
|
||||||
throw application_error("Undefined bar: " + m_barname + ". The config file contains no bar.");
|
throw application_error("Undefined bar: " + barname + ". The config file contains no bar.");
|
||||||
} else {
|
} else {
|
||||||
throw application_error(
|
throw application_error(
|
||||||
"Undefined bar: " + m_barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
|
"Undefined bar: " + barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ config::make_type config_parser::parse() {
|
|||||||
* second element onwards for the included list
|
* second element onwards for the included list
|
||||||
*/
|
*/
|
||||||
file_list included(m_files.begin() + 1, m_files.end());
|
file_list included(m_files.begin() + 1, m_files.end());
|
||||||
config::make_type result = config::make(m_config, m_barname);
|
config::make_type result = config::make(m_config, barname);
|
||||||
|
|
||||||
// Cast to non-const to set sections, included and xrm
|
// Cast to non-const to set sections, included and xrm
|
||||||
config& m_conf = const_cast<config&>(result);
|
config& m_conf = const_cast<config&>(result);
|
||||||
|
@ -197,6 +197,16 @@ void controller::signal_handler(int signum) {
|
|||||||
stop(signum == SIGUSR1);
|
stop(signum == SIGUSR1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void controller::create_config_watcher(const string& filename) {
|
||||||
|
auto& fs_event_handler = m_loop.handle<FSEventHandle>();
|
||||||
|
fs_event_handler.start(
|
||||||
|
filename, 0, [this](const auto& e) { confwatch_handler(e.path); },
|
||||||
|
[this, &fs_event_handler](const auto& e) {
|
||||||
|
m_log.err("libuv error while watching included file for changes: %s", uv_strerror(e.status));
|
||||||
|
fs_event_handler.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void controller::confwatch_handler(const char* filename) {
|
void controller::confwatch_handler(const char* filename) {
|
||||||
m_log.notice("Watched config file changed %s", filename);
|
m_log.notice("Watched config file changed %s", filename);
|
||||||
stop(true);
|
stop(true);
|
||||||
@ -239,7 +249,7 @@ void controller::read_events(bool confwatch) {
|
|||||||
m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id());
|
m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id());
|
||||||
|
|
||||||
if (!m_writeback) {
|
if (!m_writeback) {
|
||||||
m_bar->start();
|
m_bar->start(m_tray_module_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& poll_handle = m_loop.handle<PollHandle>(m_connection.get_file_descriptor());
|
auto& poll_handle = m_loop.handle<PollHandle>(m_connection.get_file_descriptor());
|
||||||
@ -256,13 +266,11 @@ void controller::read_events(bool confwatch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (confwatch) {
|
if (confwatch) {
|
||||||
auto& fs_event_handle = m_loop.handle<FSEventHandle>();
|
create_config_watcher(m_conf.filepath());
|
||||||
fs_event_handle.start(
|
// also watch the include-files for changes
|
||||||
m_conf.filepath(), 0, [this](const auto& e) { confwatch_handler(e.path); },
|
for (auto& module_path : m_conf.get_included_files()) {
|
||||||
[this, &fs_event_handle](const auto& e) {
|
create_config_watcher(module_path);
|
||||||
m_log.err("libuv error while watching config file for changes: %s", uv_strerror(e.status));
|
}
|
||||||
fs_event_handle.close();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_snapshot_dst.empty()) {
|
if (!m_snapshot_dst.empty()) {
|
||||||
@ -595,6 +603,13 @@ size_t controller::setup_modules(alignment align) {
|
|||||||
try {
|
try {
|
||||||
auto type = m_conf.get("module/" + module_name, "type");
|
auto type = m_conf.get("module/" + module_name, "type");
|
||||||
|
|
||||||
|
if (type == tray_module::TYPE) {
|
||||||
|
if (!m_tray_module_name.empty()) {
|
||||||
|
throw module_error("Multiple trays defined. Using tray `" + m_tray_module_name + "`");
|
||||||
|
}
|
||||||
|
m_tray_module_name = module_name;
|
||||||
|
}
|
||||||
|
|
||||||
if (type == ipc_module::TYPE && !m_has_ipc) {
|
if (type == ipc_module::TYPE && !m_has_ipc) {
|
||||||
throw application_error("Inter-process messaging needs to be enabled");
|
throw application_error("Inter-process messaging needs to be enabled");
|
||||||
}
|
}
|
||||||
|
@ -748,8 +748,12 @@ void renderer::render_text(const tags::context& ctxt, const string&& contents) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer::draw_offset(rgba color, double x, double w) {
|
void renderer::draw_offset(const tags::context& ctxt, rgba color, double x, double w) {
|
||||||
if (w > 0 && color != m_bar.background) {
|
if (w <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color != m_bar.background) {
|
||||||
m_log.trace_x("renderer: offset(x=%f, w=%f)", x, w);
|
m_log.trace_x("renderer: offset(x=%f, w=%f)", x, w);
|
||||||
m_context->save();
|
m_context->save();
|
||||||
*m_context << m_comp_bg;
|
*m_context << m_comp_bg;
|
||||||
@ -759,6 +763,14 @@ void renderer::draw_offset(rgba color, double x, double w) {
|
|||||||
m_context->fill();
|
m_context->fill();
|
||||||
m_context->restore();
|
m_context->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctxt.has_underline()) {
|
||||||
|
fill_underline(ctxt.get_ul(), x, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxt.has_overline()) {
|
||||||
|
fill_overline(ctxt.get_ol(), x, w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer::render_offset(const tags::context& ctxt, const extent_val offset) {
|
void renderer::render_offset(const tags::context& ctxt, const extent_val offset) {
|
||||||
@ -767,7 +779,7 @@ void renderer::render_offset(const tags::context& ctxt, const extent_val offset)
|
|||||||
|
|
||||||
int offset_width = units_utils::extent_to_pixel(offset, m_bar.dpi_x);
|
int offset_width = units_utils::extent_to_pixel(offset, m_bar.dpi_x);
|
||||||
rgba bg = ctxt.get_bg();
|
rgba bg = ctxt.get_bg();
|
||||||
draw_offset(bg, m_blocks[m_align].x, offset_width);
|
draw_offset(ctxt, bg, m_blocks[m_align].x, offset_width);
|
||||||
increase_x(offset_width);
|
increase_x(offset_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,6 +847,9 @@ void renderer::apply_tray_position(const tags::context& context) {
|
|||||||
int absolute_x = static_cast<int>(
|
int absolute_x = static_cast<int>(
|
||||||
block_x(context.get_relative_tray_position().first) + context.get_relative_tray_position().second);
|
block_x(context.get_relative_tray_position().first) + context.get_relative_tray_position().second);
|
||||||
m_sig.emit(signals::ui_tray::tray_pos_change{absolute_x});
|
m_sig.emit(signals::ui_tray::tray_pos_change{absolute_x});
|
||||||
|
m_sig.emit(signals::ui_tray::tray_visibility{true});
|
||||||
|
} else {
|
||||||
|
m_sig.emit(signals::ui_tray::tray_visibility{false});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "ipc/util.hpp"
|
#include "ipc/util.hpp"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include "utils/env.hpp"
|
#include "utils/env.hpp"
|
||||||
@ -12,8 +13,14 @@ POLYBAR_NS
|
|||||||
namespace ipc {
|
namespace ipc {
|
||||||
|
|
||||||
static constexpr auto SUFFIX = ".sock";
|
static constexpr auto SUFFIX = ".sock";
|
||||||
|
static constexpr auto XDG_RUNTIME_DIR = "XDG_RUNTIME_DIR";
|
||||||
|
|
||||||
string get_runtime_path() {
|
string get_runtime_path() {
|
||||||
|
if (env_util::has(XDG_RUNTIME_DIR)) {
|
||||||
|
return env_util::get("XDG_RUNTIME_DIR") + "/polybar";
|
||||||
|
} else {
|
||||||
|
return "/tmp/polybar-" + to_string(getuid());
|
||||||
|
}
|
||||||
return env_util::get("XDG_RUNTIME_DIR", "/tmp") + "/polybar";
|
return env_util::get("XDG_RUNTIME_DIR", "/tmp") + "/polybar";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +66,6 @@ namespace ipc {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -127,8 +127,8 @@ int main(int argc, char** argv) {
|
|||||||
barname = cli->get(0);
|
barname = cli->get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
config_parser parser{logger, move(confpath), move(barname)};
|
config_parser parser{logger, move(confpath)};
|
||||||
config::make_type conf = parser.parse();
|
config::make_type conf = parser.parse(move(barname));
|
||||||
|
|
||||||
//==================================================
|
//==================================================
|
||||||
// Dump requested data
|
// Dump requested data
|
||||||
|
@ -27,12 +27,33 @@ namespace modules {
|
|||||||
: inotify_module<backlight_module>(bar, move(name_)) {
|
: inotify_module<backlight_module>(bar, move(name_)) {
|
||||||
m_router->register_action(EVENT_DEC, [this]() { action_dec(); });
|
m_router->register_action(EVENT_DEC, [this]() { action_dec(); });
|
||||||
m_router->register_action(EVENT_INC, [this]() { action_inc(); });
|
m_router->register_action(EVENT_INC, [this]() { action_inc(); });
|
||||||
|
auto card = m_conf.get(name(), "card", ""s);
|
||||||
|
if (card.empty()) {
|
||||||
|
vector<string> backlight_card_names = file_util::list_files(string_util::replace(PATH_BACKLIGHT, "%card%", ""));
|
||||||
|
backlight_card_names.erase(std::remove_if(backlight_card_names.begin(), backlight_card_names.end(),
|
||||||
|
[&](const string& card) -> bool {
|
||||||
|
auto dir = string_util::replace(PATH_BACKLIGHT, "%card%", card);
|
||||||
|
return !(file_util::is_file(dir + "/actual_brightness") &&
|
||||||
|
file_util::is_file(dir + "/brightness") &&
|
||||||
|
file_util::is_file(dir + "/max_brightness"));
|
||||||
|
}),
|
||||||
|
backlight_card_names.end());
|
||||||
|
|
||||||
auto card = m_conf.get(name(), "card");
|
if (backlight_card_names.empty()) {
|
||||||
|
throw module_error("no viable default backlight found");
|
||||||
|
}
|
||||||
|
card = backlight_card_names.at(0);
|
||||||
|
if (backlight_card_names.size() > 1) {
|
||||||
|
m_log.warn("%s: multiple backlights found, using %s", name(), card);
|
||||||
|
} else {
|
||||||
|
m_log.info("%s: no backlight specified, using `%s`", name(), card);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Get flag to check if we should add scroll handlers for changing value
|
// Get flag to check if we should add scroll handlers for changing value
|
||||||
m_scroll = m_conf.get(name(), "enable-scroll", m_scroll);
|
m_scroll = m_conf.get(name(), "enable-scroll", m_scroll);
|
||||||
|
|
||||||
|
m_scroll_interval = m_conf.get(name(), "scroll-interval", m_scroll_interval);
|
||||||
|
|
||||||
// Add formats and elements
|
// Add formats and elements
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR, TAG_RAMP});
|
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR, TAG_RAMP});
|
||||||
|
|
||||||
@ -120,11 +141,11 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void backlight_module::action_inc() {
|
void backlight_module::action_inc() {
|
||||||
change_value(5);
|
change_value(m_scroll_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backlight_module::action_dec() {
|
void backlight_module::action_dec() {
|
||||||
change_value(-5);
|
change_value(-m_scroll_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backlight_module::change_value(int value_mod) {
|
void backlight_module::change_value(int value_mod) {
|
||||||
|
@ -199,7 +199,7 @@ namespace modules {
|
|||||||
if (chrono::duration_cast<decltype(m_interval)>(now - m_lastpoll) > m_interval) {
|
if (chrono::duration_cast<decltype(m_interval)>(now - m_lastpoll) > m_interval) {
|
||||||
m_lastpoll = now;
|
m_lastpoll = now;
|
||||||
m_log.info("%s: Polling values (inotify fallback)", name());
|
m_log.info("%s: Polling values (inotify fallback)", name());
|
||||||
read(*m_capacity_reader);
|
on_event({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,11 @@ namespace modules {
|
|||||||
* setting up required components
|
* setting up required components
|
||||||
*/
|
*/
|
||||||
fs_module::fs_module(const bar_settings& bar, string name_) : timer_module<fs_module>(bar, move(name_)) {
|
fs_module::fs_module(const bar_settings& bar, string name_) : timer_module<fs_module>(bar, move(name_)) {
|
||||||
m_mountpoints = m_conf.get_list(name(), "mount");
|
m_mountpoints = m_conf.get_list(name(), "mount", {});
|
||||||
|
if (m_mountpoints.empty()) {
|
||||||
|
m_log.info("%s: No mountpoints specified, using fallback \"/\"", name());
|
||||||
|
m_mountpoints.emplace_back("/");
|
||||||
|
}
|
||||||
m_remove_unmounted = m_conf.get(name(), "remove-unmounted", m_remove_unmounted);
|
m_remove_unmounted = m_conf.get(name(), "remove-unmounted", m_remove_unmounted);
|
||||||
m_perc_used_warn = m_conf.get(name(), "warn-percentage", 90);
|
m_perc_used_warn = m_conf.get(name(), "warn-percentage", 90);
|
||||||
m_fixed = m_conf.get(name(), "fixed-values", m_fixed);
|
m_fixed = m_conf.get(name(), "fixed-values", m_fixed);
|
||||||
|
@ -108,7 +108,8 @@ namespace modules {
|
|||||||
if (evt->atom == m_ewmh->_NET_CLIENT_LIST || evt->atom == m_ewmh->_NET_WM_DESKTOP) {
|
if (evt->atom == m_ewmh->_NET_CLIENT_LIST || evt->atom == m_ewmh->_NET_WM_DESKTOP) {
|
||||||
rebuild_clientlist();
|
rebuild_clientlist();
|
||||||
rebuild_desktop_states();
|
rebuild_desktop_states();
|
||||||
} else if (evt->atom == m_ewmh->_NET_DESKTOP_NAMES || evt->atom == m_ewmh->_NET_NUMBER_OF_DESKTOPS) {
|
} else if (evt->atom == m_ewmh->_NET_DESKTOP_NAMES || evt->atom == m_ewmh->_NET_NUMBER_OF_DESKTOPS ||
|
||||||
|
evt->atom == m_ewmh->_NET_DESKTOP_VIEWPORT) {
|
||||||
m_desktop_names = get_desktop_names();
|
m_desktop_names = get_desktop_names();
|
||||||
rebuild_desktops();
|
rebuild_desktops();
|
||||||
rebuild_clientlist();
|
rebuild_clientlist();
|
||||||
|
@ -67,25 +67,26 @@ tray_manager::~tray_manager() {
|
|||||||
deactivate();
|
deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tray_manager::setup() {
|
void tray_manager::setup(const string& tray_module_name) {
|
||||||
const config& conf = config::make();
|
const config& conf = config::make();
|
||||||
auto bs = conf.section();
|
auto bs = conf.section();
|
||||||
string position;
|
string position = conf.get(bs, "tray-position", "none"s);
|
||||||
|
|
||||||
try {
|
if (!position.empty() && position != "none" && !tray_module_name.empty()) {
|
||||||
position = conf.get(bs, "tray-position");
|
m_log.warn(
|
||||||
} catch (const key_error& err) {
|
"The tray position is manually defined (`tray-position`) and also set by the tray module (%s). `tray-position` "
|
||||||
return m_log.info("Disabling tray manager (reason: missing `tray-position`)");
|
"will be ignored",
|
||||||
|
tray_module_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position == "left") {
|
if (!tray_module_name.empty()) {
|
||||||
m_opts.align = alignment::LEFT;
|
m_opts.tray_position = tray_postition::MODULE;
|
||||||
|
} else if (position == "left") {
|
||||||
|
m_opts.tray_position = tray_postition::LEFT;
|
||||||
} else if (position == "right") {
|
} else if (position == "right") {
|
||||||
m_opts.align = alignment::RIGHT;
|
m_opts.tray_position = tray_postition::RIGHT;
|
||||||
} else if (position == "center") {
|
} else if (position == "center") {
|
||||||
m_opts.align = alignment::CENTER;
|
m_opts.tray_position = tray_postition::CENTER;
|
||||||
} else if (position == "adaptive") {
|
|
||||||
m_opts.adaptive = true;
|
|
||||||
} else if (position != "none") {
|
} else if (position != "none") {
|
||||||
return m_log.err("Disabling tray manager (reason: Invalid position \"" + position + "\")");
|
return m_log.err("Disabling tray manager (reason: Invalid position \"" + position + "\")");
|
||||||
} else {
|
} else {
|
||||||
@ -114,12 +115,12 @@ void tray_manager::setup() {
|
|||||||
m_opts.win_size.h *= scale;
|
m_opts.win_size.h *= scale;
|
||||||
|
|
||||||
m_opts.pos.x = inner_area.x + [&]() -> int {
|
m_opts.pos.x = inner_area.x + [&]() -> int {
|
||||||
switch (m_opts.align) {
|
switch (m_opts.tray_position) {
|
||||||
case alignment::LEFT:
|
case tray_postition::LEFT:
|
||||||
return 0;
|
return 0;
|
||||||
case alignment::CENTER:
|
case tray_postition::CENTER:
|
||||||
return inner_area.width / 2 - m_opts.client_size.w / 2;
|
return inner_area.width / 2 - m_opts.client_size.w / 2;
|
||||||
case alignment::RIGHT:
|
case tray_postition::RIGHT:
|
||||||
return inner_area.width;
|
return inner_area.width;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@ -755,9 +756,9 @@ void tray_manager::process_docking_request(xcb_window_t win) {
|
|||||||
*/
|
*/
|
||||||
int tray_manager::calculate_x(unsigned int width) const {
|
int tray_manager::calculate_x(unsigned int width) const {
|
||||||
auto x = m_opts.pos.x;
|
auto x = m_opts.pos.x;
|
||||||
if (m_opts.align == alignment::RIGHT) {
|
if (m_opts.tray_position == tray_postition::RIGHT) {
|
||||||
x -= ((m_opts.client_size.w + m_opts.spacing) * m_clients.size() + m_opts.spacing);
|
x -= ((m_opts.client_size.w + m_opts.spacing) * m_clients.size() + m_opts.spacing);
|
||||||
} else if (m_opts.align == alignment::CENTER) {
|
} else if (m_opts.tray_position == tray_postition::CENTER) {
|
||||||
x -= (width / 2) - (m_opts.client_size.w / 2);
|
x -= (width / 2) - (m_opts.client_size.w / 2);
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
@ -849,6 +850,29 @@ bool tray_manager::has_mapped_clients() const {
|
|||||||
return std::find_if(m_clients.begin(), m_clients.end(), [](const auto& c) { return c.mapped(); }) != m_clients.end();
|
return std::find_if(m_clients.begin(), m_clients.end(), [](const auto& c) { return c.mapped(); }) != m_clients.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tray_manager::change_visibility(bool visible) {
|
||||||
|
bool has_clients = has_mapped_clients();
|
||||||
|
|
||||||
|
m_log.trace("tray: visibility_change (state=%i, activated=%i, mapped=%i, hidden=%i)", visible,
|
||||||
|
static_cast<bool>(m_activated), static_cast<bool>(m_mapped), static_cast<bool>(m_hidden));
|
||||||
|
|
||||||
|
m_hidden = !visible;
|
||||||
|
|
||||||
|
if (!m_activated) {
|
||||||
|
return false;
|
||||||
|
} else if (!m_hidden && !m_mapped && has_clients) {
|
||||||
|
m_connection.map_window(m_tray);
|
||||||
|
} else if ((!has_clients || m_hidden) && m_mapped) {
|
||||||
|
m_connection.unmap_window(m_tray);
|
||||||
|
} else if (m_mapped && !m_hidden && has_clients) {
|
||||||
|
redraw_window();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_connection.flush();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event callback : XCB_EXPOSE
|
* Event callback : XCB_EXPOSE
|
||||||
*/
|
*/
|
||||||
@ -1073,27 +1097,7 @@ void tray_manager::handle(const evt::unmap_notify& evt) {
|
|||||||
* toggle the tray window whenever the visibility of the bar window changes.
|
* toggle the tray window whenever the visibility of the bar window changes.
|
||||||
*/
|
*/
|
||||||
bool tray_manager::on(const signals::ui::visibility_change& evt) {
|
bool tray_manager::on(const signals::ui::visibility_change& evt) {
|
||||||
bool visible{evt.cast()};
|
return change_visibility(evt.cast());
|
||||||
bool has_clients = has_mapped_clients();
|
|
||||||
|
|
||||||
m_log.trace("tray: visibility_change (state=%i, activated=%i, mapped=%i, hidden=%i)", visible,
|
|
||||||
static_cast<bool>(m_activated), static_cast<bool>(m_mapped), static_cast<bool>(m_hidden));
|
|
||||||
|
|
||||||
m_hidden = !visible;
|
|
||||||
|
|
||||||
if (!m_activated) {
|
|
||||||
return false;
|
|
||||||
} else if (!m_hidden && !m_mapped && has_clients) {
|
|
||||||
m_connection.map_window(m_tray);
|
|
||||||
} else if ((!has_clients || m_hidden) && m_mapped) {
|
|
||||||
m_connection.unmap_window(m_tray);
|
|
||||||
} else if (m_mapped && !m_hidden && has_clients) {
|
|
||||||
redraw_window();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_connection.flush();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tray_manager::on(const signals::ui::dim_window& evt) {
|
bool tray_manager::on(const signals::ui::dim_window& evt) {
|
||||||
@ -1112,10 +1116,20 @@ bool tray_manager::on(const signals::ui::update_background&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool tray_manager::on(const signals::ui_tray::tray_pos_change& evt) {
|
bool tray_manager::on(const signals::ui_tray::tray_pos_change& evt) {
|
||||||
m_opts.pos.x = m_bar_opts.inner_area(true).x + evt.cast();
|
m_opts.pos.x =
|
||||||
|
m_bar_opts.inner_area(false).x + std::max(0, std::min(evt.cast(), (int)(m_bar_opts.size.w - calculate_w())));
|
||||||
|
|
||||||
reconfigure_window();
|
reconfigure_window();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tray_manager::on(const signals::ui_tray::tray_visibility& evt) {
|
||||||
|
if (evt.cast() == m_hidden && m_opts.tray_position == tray_postition::MODULE) {
|
||||||
|
return change_visibility(evt.cast());
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -57,14 +57,16 @@ window window::reconfigure_pos(short int x, short int y) {
|
|||||||
window window::reconfigure_struts(uint32_t w, uint32_t strut, uint32_t x, bool bottom) {
|
window window::reconfigure_struts(uint32_t w, uint32_t strut, uint32_t x, bool bottom) {
|
||||||
std::array<uint32_t, 12> values{};
|
std::array<uint32_t, 12> values{};
|
||||||
|
|
||||||
|
uint32_t end_x = std::max<int>(0, x + w - 1);
|
||||||
|
|
||||||
if (bottom) {
|
if (bottom) {
|
||||||
values[to_integral(strut::BOTTOM)] = strut;
|
values[to_integral(strut::BOTTOM)] = strut;
|
||||||
values[to_integral(strut::BOTTOM_START_X)] = x;
|
values[to_integral(strut::BOTTOM_START_X)] = x;
|
||||||
values[to_integral(strut::BOTTOM_END_X)] = x + w - 1;
|
values[to_integral(strut::BOTTOM_END_X)] = end_x;
|
||||||
} else {
|
} else {
|
||||||
values[to_integral(strut::TOP)] = strut;
|
values[to_integral(strut::TOP)] = strut;
|
||||||
values[to_integral(strut::TOP_START_X)] = x;
|
values[to_integral(strut::TOP_START_X)] = x;
|
||||||
values[to_integral(strut::TOP_END_X)] = x + w - 1;
|
values[to_integral(strut::TOP_END_X)] = end_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection().change_property_checked(
|
connection().change_property_checked(
|
||||||
|
@ -13,8 +13,8 @@ class TestableConfigParser : public config_parser {
|
|||||||
using config_parser::config_parser;
|
using config_parser::config_parser;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TestableConfigParser(const logger& logger, string&& file, string&& bar)
|
TestableConfigParser(const logger& logger, string&& file)
|
||||||
: config_parser(logger, move(file), move(bar)) {
|
: config_parser(logger, move(file)) {
|
||||||
m_files.push_back("test_config");
|
m_files.push_back("test_config");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class TestableConfigParser : public config_parser {
|
|||||||
class ConfigParser : public ::testing::Test {
|
class ConfigParser : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
const logger l = logger(loglevel::NONE);
|
const logger l = logger(loglevel::NONE);
|
||||||
unique_ptr<TestableConfigParser> parser = make_unique<TestableConfigParser>(l, "/dev/zero", "TEST");
|
unique_ptr<TestableConfigParser> parser = make_unique<TestableConfigParser>(l, "/dev/zero");
|
||||||
};
|
};
|
||||||
|
|
||||||
// ParseLineTest {{{
|
// ParseLineTest {{{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Polybar version information
|
# Polybar version information
|
||||||
# Update this on every release
|
# Update this on every release
|
||||||
# This is used to create the version string if a git repo is not available
|
# This is used to create the version string if a git repo is not available
|
||||||
3.6.2
|
3.6.3
|
||||||
|
Loading…
Reference in New Issue
Block a user