-----BEGIN PGP SIGNATURE-----
iQEzBAABCAAdFiEEHVeRNS1RoijU3dukUh5eA668oacFAmVkwa4ACgkQUh5eA668 oackXggAtyUMZSVxtxrjS9LLYwSFR0p09a7ns1QYJmGjQo2ZHW3f4hHQuajqFPLE J8icknCPtRge2tm6J7XGQakZ+PUXe7ILLCBFf8DFbgdbCe3YiEvxHtnRa6MCR1yO 4ljwg7MIlS58ynJt92nh3R/7PxigZYKn/DqV2HeMvXqLimLXvXLDbAjVwPbvHNDJ Eq/jJExEyX4ZrXEIIGxq3/QnxeSI+IPbReMbVZbERWG9jZt2RJoPUepRDH6jhWJN 03oUZ6gm5qU8frvhbpGfqZ2hVncnyJRskXR1CJ31OyGGiS2WfGK5viI0geQyRAse LxaRJHdrURVX7x1VSzdah6yzaSo1fA== =Wy/L -----END PGP SIGNATURE----- Merge tag '3.7.1'
This commit is contained in:
commit
6d42ccedd6
@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
Standard: Cpp11
|
Standard: c++17
|
||||||
BasedOnStyle: Google
|
BasedOnStyle: Google
|
||||||
ColumnLimit: 120
|
ColumnLimit: 120
|
||||||
NamespaceIndentation: All
|
NamespaceIndentation: Inner
|
||||||
AlignAfterOpenBracket: DontAlign
|
AlignAfterOpenBracket: DontAlign
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
@ -16,6 +16,7 @@ Checks: '
|
|||||||
-modernize-raw-string-literal,
|
-modernize-raw-string-literal,
|
||||||
-modernize-use-bool-literals,
|
-modernize-use-bool-literals,
|
||||||
-modernize-use-trailing-return-type,
|
-modernize-use-trailing-return-type,
|
||||||
|
-readability-identifier-length,
|
||||||
-readability-implicit-bool-cast,
|
-readability-implicit-bool-cast,
|
||||||
-readability-else-after-return,
|
-readability-else-after-return,
|
||||||
-readability-named-parameter,
|
-readability-named-parameter,
|
||||||
@ -26,7 +27,8 @@ Checks: '
|
|||||||
-cppcoreguidelines-pro-type-reinterpret-cast,
|
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||||
-cppcoreguidelines-pro-type-union-access,
|
-cppcoreguidelines-pro-type-union-access,
|
||||||
-cppcoreguidelines-pro-type-cstyle-cast,
|
-cppcoreguidelines-pro-type-cstyle-cast,
|
||||||
-cppcoreguidelines-pro-bounds-constant-array-index
|
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||||
|
-cppcoreguidelines-owning-memory,
|
||||||
'
|
'
|
||||||
|
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
|
@ -7,6 +7,9 @@ indent_style = space
|
|||||||
indent_size = 2
|
indent_size = 2
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
[Makefile]
|
[Makefile]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Bug Report
|
name: 🐞 Bug Report
|
||||||
description: Create a report for something that misbehaves
|
description: Create a report for something that misbehaves
|
||||||
title: "[Bug]: "
|
title: "[Bug]: "
|
||||||
labels: ["bug", "needs confirmation"]
|
labels: ["bug", "needs confirmation"]
|
||||||
@ -33,7 +33,7 @@ body:
|
|||||||
id: config
|
id: config
|
||||||
attributes:
|
attributes:
|
||||||
label: Minimal config
|
label: Minimal config
|
||||||
description: A minimal but complete config with which the problem occurs.
|
description: A minimal but **complete** config with which the problem occurs.
|
||||||
render: dosini
|
render: dosini
|
||||||
placeholder: |
|
placeholder: |
|
||||||
[bar/example]
|
[bar/example]
|
||||||
@ -103,7 +103,7 @@ body:
|
|||||||
id: context
|
id: context
|
||||||
attributes:
|
attributes:
|
||||||
label: Additional Context / Screenshots
|
label: Additional Context / Screenshots
|
||||||
description: If applicaple, add screenshots and additional context to explain your problem
|
description: If applicable, add screenshots and additional context to explain your problem
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
- type: markdown
|
- type: markdown
|
||||||
|
81
.github/ISSUE_TEMPLATE/build.yml
vendored
81
.github/ISSUE_TEMPLATE/build.yml
vendored
@ -1,81 +0,0 @@
|
|||||||
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
|
|
15
.github/ISSUE_TEMPLATE/config.yml
vendored
15
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,8 +1,11 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Polybar Gitter Room
|
- name: 🙋 Ask a question
|
||||||
url: https://gitter.im/polybar/polybar
|
url: https://github.com/polybar/polybar/blob/master/SUPPORT.md
|
||||||
about: Please ask and answer questions here.
|
about: Have a look at our support resources and channels
|
||||||
- name: Polybar subreddit
|
- name: 💡 Feature request
|
||||||
url: https://www.reddit.com/r/polybar
|
url: https://github.com/polybar/polybar/discussions/categories/ideas
|
||||||
about: Please ask and answer questions here.
|
about: Suggest your idea over in Discussions
|
||||||
|
- name: 🛠️ Build Issues
|
||||||
|
url: https://github.com/polybar/polybar/discussions/categories/build-support
|
||||||
|
about: Get support when building polybar from source
|
||||||
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
labels: feature, needs confirmation
|
|
||||||
---
|
|
||||||
|
|
||||||
## Is your feature request related to a problem? Please describe.
|
|
||||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
|
||||||
|
|
||||||
## Why does polybar need this feature?
|
|
||||||
<!-- Describe why this feature would be useful to a large percentage of users (You need to convince us). -->
|
|
||||||
|
|
||||||
## Describe the solution you'd like
|
|
||||||
<!-- A clear and concise description of how your solution would work. This includes possible config options that should be added. -->
|
|
||||||
|
|
||||||
## Describe alternatives you've considered
|
|
||||||
<!-- A clear and concise description of any alternative solutions or features you've considered, if any. -->
|
|
||||||
|
|
||||||
## Additional context
|
|
||||||
<!-- Add any other context or screenshots about the feature request here. -->
|
|
0
.codecov.yml → .github/codecov.yml
vendored
0
.codecov.yml → .github/codecov.yml
vendored
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
@ -10,11 +10,11 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docs:
|
docs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
COLOR: "ON"
|
COLOR: "ON"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.inputs.ref }}
|
ref: ${{ github.event.inputs.ref }}
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
@ -29,7 +29,7 @@ jobs:
|
|||||||
make doc
|
make doc
|
||||||
|
|
||||||
ipc:
|
ipc:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
COLOR: "ON"
|
COLOR: "ON"
|
||||||
steps:
|
steps:
|
||||||
@ -48,7 +48,7 @@ jobs:
|
|||||||
python3-xcbgen \
|
python3-xcbgen \
|
||||||
libuv1-dev \
|
libuv1-dev \
|
||||||
xcb-proto
|
xcb-proto
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
ref: ${{ github.event.inputs.ref }}
|
ref: ${{ github.event.inputs.ref }}
|
||||||
@ -60,7 +60,7 @@ jobs:
|
|||||||
make polybar-msg
|
make polybar-msg
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
cxx: [g++, clang++]
|
cxx: [g++, clang++]
|
||||||
@ -115,7 +115,7 @@ jobs:
|
|||||||
if [ "$POLYBAR_BUILD_TYPE" = "tests" ]; then
|
if [ "$POLYBAR_BUILD_TYPE" = "tests" ]; then
|
||||||
sudo apt-get install -y lcov
|
sudo apt-get install -y lcov
|
||||||
fi
|
fi
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
ref: ${{ github.event.inputs.ref }}
|
ref: ${{ github.event.inputs.ref }}
|
||||||
@ -125,7 +125,7 @@ jobs:
|
|||||||
run: ./common/ci/configure.sh
|
run: ./common/ci/configure.sh
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd $BUILD_DIR
|
cd "$BUILD_DIR"
|
||||||
make
|
make
|
||||||
- name: Collect initial coverage
|
- name: Collect initial coverage
|
||||||
if: ${{ matrix.polybar_build_type == 'tests' }}
|
if: ${{ matrix.polybar_build_type == 'tests' }}
|
||||||
@ -134,17 +134,17 @@ jobs:
|
|||||||
- 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
|
||||||
- name: Collect coverage
|
- name: Collect coverage
|
||||||
if: ${{ matrix.polybar_build_type == 'tests' }}
|
if: ${{ matrix.polybar_build_type == 'tests' }}
|
||||||
run: |
|
run: |
|
||||||
lcov --capture --no-external --directory . -o cov_tests.info
|
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 --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
|
lcov --remove cov_total.info "${PWD}/build/*" "${PWD}/tests/*" "${PWD}/lib/*" -o cov.info
|
||||||
- name: Upload Coverage
|
- name: Upload Coverage
|
||||||
if: ${{ matrix.polybar_build_type == 'tests' }}
|
if: ${{ matrix.polybar_build_type == 'tests' }}
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
flags: unittests
|
flags: unittests
|
||||||
files: ./cov.info
|
files: ./cov.info
|
||||||
|
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@ -31,9 +31,11 @@ jobs:
|
|||||||
RELEASE_TAG=${GITHUB_REF#refs/tags/}
|
RELEASE_TAG=${GITHUB_REF#refs/tags/}
|
||||||
fi
|
fi
|
||||||
echo "Publishing Version $RELEASE_TAG"
|
echo "Publishing Version $RELEASE_TAG"
|
||||||
echo "RELEASE_TAG=$RELEASE_TAG" >> "$GITHUB_ENV"
|
{
|
||||||
echo "POLYBAR_DIR=polybar-$RELEASE_TAG" >> "$GITHUB_ENV"
|
echo "RELEASE_TAG=$RELEASE_TAG"
|
||||||
echo "POLYBAR_ARCHIVE=polybar-$RELEASE_TAG.tar.gz" >> "$GITHUB_ENV"
|
echo "POLYBAR_DIR=polybar-$RELEASE_TAG"
|
||||||
|
echo "POLYBAR_ARCHIVE=polybar-$RELEASE_TAG.tar.gz"
|
||||||
|
} >> "$GITHUB_ENV"
|
||||||
|
|
||||||
# Checks out the target tag
|
# Checks out the target tag
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@ -91,7 +93,7 @@ jobs:
|
|||||||
const fname = '${{ env.POLYBAR_ARCHIVE }}'
|
const fname = '${{ env.POLYBAR_ARCHIVE }}'
|
||||||
const url = '${{ steps.upload_archive.outputs.browser_download_url }}'
|
const url = '${{ steps.upload_archive.outputs.browser_download_url }}'
|
||||||
const hash = '${{ env.SHA256SUM }}'
|
const hash = '${{ env.SHA256SUM }}'
|
||||||
let body = "## Download:\n\n"
|
let body = "## Download\n\n"
|
||||||
body += `[${fname}](${url}) (**sha256**: \`${hash}\`)\n\n`
|
body += `[${fname}](${url}) (**sha256**: \`${hash}\`)\n\n`
|
||||||
body += process.env.RELEASE_BODY;
|
body += process.env.RELEASE_BODY;
|
||||||
|
|
||||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -8,4 +8,10 @@
|
|||||||
.tags
|
.tags
|
||||||
*.user
|
*.user
|
||||||
|
|
||||||
|
# clangd
|
||||||
|
/.cache
|
||||||
|
|
||||||
polybar-*.tar
|
polybar-*.tar
|
||||||
|
*.cache
|
||||||
|
|
||||||
|
.venv
|
||||||
|
22
.readthedocs.yaml
Normal file
22
.readthedocs.yaml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# .readthedocs.yaml
|
||||||
|
# Read the Docs configuration file
|
||||||
|
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||||
|
|
||||||
|
# Required
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
# Set the version of Python and other tools you might need
|
||||||
|
build:
|
||||||
|
os: ubuntu-22.04
|
||||||
|
tools:
|
||||||
|
python: "3"
|
||||||
|
|
||||||
|
# Build documentation in the docs/ directory with Sphinx
|
||||||
|
sphinx:
|
||||||
|
configuration: doc/conf.py
|
||||||
|
fail_on_warning: true
|
||||||
|
|
||||||
|
python:
|
||||||
|
install:
|
||||||
|
- requirements: doc/requirements.txt
|
@ -1,126 +0,0 @@
|
|||||||
import os
|
|
||||||
import ycm_core
|
|
||||||
|
|
||||||
# Default flags
|
|
||||||
flags = [
|
|
||||||
'-std=c++14',
|
|
||||||
'-Wall',
|
|
||||||
'-Wextra',
|
|
||||||
|
|
||||||
# Relative paths are corrected by MakeRelativePathsInFlagsAbsolute
|
|
||||||
'-Isrc',
|
|
||||||
'-Iinclude',
|
|
||||||
'-Ilib/concurrentqueue/include',
|
|
||||||
'-Ilib/i3ipcpp/include',
|
|
||||||
'-Ilib/xpp/include',
|
|
||||||
'-Itests',
|
|
||||||
|
|
||||||
'-I/usr/include',
|
|
||||||
'-I/usr/include/freetype2',
|
|
||||||
]
|
|
||||||
|
|
||||||
# Base directory of the project, parent directory of all source files
|
|
||||||
project_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
# This assumes that everyone coding for this project builds inside the 'build'
|
|
||||||
# directory
|
|
||||||
compilation_database_folder = project_dir + "/build"
|
|
||||||
|
|
||||||
if os.path.exists(compilation_database_folder):
|
|
||||||
database = ycm_core.CompilationDatabase(compilation_database_folder)
|
|
||||||
else:
|
|
||||||
database = None
|
|
||||||
|
|
||||||
SOURCE_EXTENSIONS = ['.cpp', '.cxx', '.cc', '.c', '.m', '.mm']
|
|
||||||
|
|
||||||
# Converts all relative paths in the given flag list to absolute paths with
|
|
||||||
# working_directory as the base directory
|
|
||||||
def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
|
|
||||||
if not working_directory:
|
|
||||||
return list(flags)
|
|
||||||
new_flags = []
|
|
||||||
make_next_absolute = False
|
|
||||||
path_flags = ['-isystem', '-I', '-iquote', '--sysroot=']
|
|
||||||
for flag in flags:
|
|
||||||
new_flag = flag
|
|
||||||
|
|
||||||
if make_next_absolute:
|
|
||||||
make_next_absolute = False
|
|
||||||
if not flag.startswith('/'):
|
|
||||||
new_flag = os.path.join(working_directory, flag)
|
|
||||||
|
|
||||||
for path_flag in path_flags:
|
|
||||||
if flag == path_flag:
|
|
||||||
make_next_absolute = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if flag.startswith(path_flag):
|
|
||||||
path = flag[len(path_flag):]
|
|
||||||
new_flag = path_flag + os.path.join(working_directory, path)
|
|
||||||
break
|
|
||||||
|
|
||||||
if new_flag:
|
|
||||||
new_flags.append(new_flag)
|
|
||||||
return new_flags
|
|
||||||
|
|
||||||
def IsHeaderFile(filename):
|
|
||||||
extension = os.path.splitext(filename)[1]
|
|
||||||
return extension in ['.h', '.hxx', '.hpp', '.hh', ".inl"]
|
|
||||||
|
|
||||||
# Tries to query the compilation database for flags
|
|
||||||
# For header files it tries to use the flags for a corresponding source file
|
|
||||||
def GetCompilationInfoForFile(filename):
|
|
||||||
if not database:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# The compilation_commands.json file generated by CMake does not have entries
|
|
||||||
# for header files. We try to use the compile flags used for the corresponding
|
|
||||||
# source file.
|
|
||||||
#
|
|
||||||
# For this try to replace the file extension with an extension that
|
|
||||||
# corresponds to a source and we also try to replace the 'include' folder in
|
|
||||||
# the path with 'src'
|
|
||||||
if IsHeaderFile(filename) :
|
|
||||||
basename = os.path.splitext(filename)[0]
|
|
||||||
|
|
||||||
# Absolute path of the include and source directories
|
|
||||||
include_dir = project_dir + "/include"
|
|
||||||
src_dir = project_dir + "/src"
|
|
||||||
|
|
||||||
# Absolute path without file extension, with the 'include' folder replaced
|
|
||||||
# with 'src' in the path
|
|
||||||
src_basename = None
|
|
||||||
# If the header file is inside the include dir, try to search in the src dir
|
|
||||||
if basename.startswith(include_dir):
|
|
||||||
# file path relative to include dir
|
|
||||||
rel_path_include = os.path.relpath(basename, include_dir)
|
|
||||||
src_basename = os.path.join(src_dir, rel_path_include)
|
|
||||||
|
|
||||||
for extension in SOURCE_EXTENSIONS:
|
|
||||||
# A list of all possible replacement files to be searched
|
|
||||||
replacement_files = [basename + extension]
|
|
||||||
|
|
||||||
if src_basename:
|
|
||||||
replacement_files.append(src_basename + extension)
|
|
||||||
|
|
||||||
for replacement_file in replacement_files:
|
|
||||||
if os.path.exists(replacement_file):
|
|
||||||
comp_info = database.GetCompilationInfoForFile(replacement_file)
|
|
||||||
if comp_info.compiler_flags_:
|
|
||||||
return comp_info
|
|
||||||
return database.GetCompilationInfoForFile(filename)
|
|
||||||
|
|
||||||
def FlagsForFile(filename, **kwargs):
|
|
||||||
compilation_info = GetCompilationInfoForFile(filename)
|
|
||||||
if compilation_info and compilation_info.compiler_flags_:
|
|
||||||
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
|
|
||||||
# python list, but a "list-like" StringVec object
|
|
||||||
final_flags = MakeRelativePathsInFlagsAbsolute(
|
|
||||||
[x for x in compilation_info.compiler_flags_ if x != "-Werror"],
|
|
||||||
compilation_info.compiler_working_dir_)
|
|
||||||
else:
|
|
||||||
# We use default flags if GetCompilationInfoForFile can't find any flags
|
|
||||||
relative_to = project_dir
|
|
||||||
final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
|
|
||||||
|
|
||||||
return {'flags': final_flags, 'do_cache': True}
|
|
81
CHANGELOG.md
81
CHANGELOG.md
@ -65,6 +65,81 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `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))
|
- `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))
|
- `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.7.1] - 2023-11-27
|
||||||
|
### Build
|
||||||
|
- Fixed missing header when using `libc++` in clang 15 and below
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- `internal/tray`: The module must use the `<tray>` tag (this is the default) ([`#3037`](https://github.com/polybar/polybar/pull/3037))
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Modules did not validate that all tags (e.g. `<label>`) used in a format were valid for that format ([`#3043`](https://github.com/polybar/polybar/issues/3043), [`#3045`](https://github.com/polybar/polybar/pull/3045))
|
||||||
|
- `internal/tray`: Fixed `module-margin` and `separator` being applied to completely empty tray module ([`#3036`](https://github.com/polybar/polybar/issues/3036), [`#3037`](https://github.com/polybar/polybar/pull/3037))
|
||||||
|
|
||||||
|
## [3.7.0] - 2023-11-05
|
||||||
|
### Breaking
|
||||||
|
- `custom/script`:
|
||||||
|
- No longer hides the module if the `exec` command failed and did not change the output from the previous run ([`#2636`](https://github.com/polybar/polybar/issues/2636)). Somewhat similar original behaviour can be imitated with `format-fail`, if necessary.
|
||||||
|
- 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))
|
||||||
|
|
||||||
|
### Build
|
||||||
|
- Respect `CMAKE_INSTALL_PREFIX` when installing default config ([`#2770`](https://github.com/polybar/polybar/pull/2770), [`#2917`](https://github.com/polybar/polybar/pull/2917))
|
||||||
|
- 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))
|
||||||
|
- 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))
|
||||||
|
- tray: All tray-related settings in the bar section are deprecated. They are replaced by the new tray module ([`#3002`](https://github.com/polybar/polybar/pull/3002))
|
||||||
|
- `tray-position`, `tray-detached`, `tray-maxsize`, `tray-scale`, `tray-transparent`, `tray-background`, `tray-foreground`, `tray-padding`, `tray-offset-x`, `tray-offset-y`
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- A tray module with type `internal/tray` for positioning the tray like a module ([`#2689`](https://github.com/polybar/polybar/issues/2689))
|
||||||
|
- `internal/temperature`: `%temperature-k%` token displays the temperature in degrees Kelvin ([`#2774`](https://github.com/polybar/polybar/discussions/2774), [`#2784`](https://github.com/polybar/polybar/pull/2784))
|
||||||
|
- `internal/pulseaudio`: `reverse-scroll` option ([`#2664`](https://github.com/polybar/polybar/pull/2664))
|
||||||
|
- `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/ipc`:
|
||||||
|
- Added support for `<label>` in `format` ([`#2841`](https://github.com/polybar/polybar/pull/2841)) by [@madhavpcm](https://github.com/madhavpcm).
|
||||||
|
- Added support for `format-i` for each defined `hook-i` ([`#2775`](https://github.com/polybar/polybar/issues/2775), [`#2810`](https://github.com/polybar/polybar/pull/2810)) by [@madhavpcm](https://github.com/madhavpcm).
|
||||||
|
- `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))
|
||||||
|
- `internal/backlight`:
|
||||||
|
- `scroll-interval` option ([`#2696`](https://github.com/polybar/polybar/issues/2696), [`#2700`](https://github.com/polybar/polybar/pull/2700))
|
||||||
|
- `poll-interval` setting controls how often the module is updated (in case it does not happen when the brightness changes) ([`#2835`](https://github.com/polybar/polybar/issues/2835), [`#3028`](https://github.com/polybar/polybar/pull/3028))
|
||||||
|
- `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))
|
||||||
|
- `internal/xworkspaces`: `group-by-monitor` setting to decide whether `_NET_DESKTOP_VIEWPORT` should be used to group workspaces by monitor; ([`#2603`](https://github.com/polybar/polybar/issues/2603), [`#2926`](https://github.com/polybar/polybar/pull/2926)) by [@slotThe](https://github.com/slotThe/).
|
||||||
|
|
||||||
|
### 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` now always defaults to `true` (even 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`: Will restack above the topmost bspwm root window instead of the root window associated with the monitor polybar is on ([`#3019`](https://github.com/polybar/polybar/pull/3019))
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
- `internal/backlight`: Fix module being one step behind every update ([`#2835`](https://github.com/polybar/polybar/issues/2835), [`#3028`](https://github.com/polybar/polybar/pull/3028))
|
||||||
|
- `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
|
## [3.6.3] - 2022-05-04
|
||||||
### Fixed
|
### Fixed
|
||||||
- `custom/script`: Output clearing when `exec-if` fails ([`#2674`](https://github.com/polybar/polybar/issues/2674))
|
- `custom/script`: Output clearing when `exec-if` fails ([`#2674`](https://github.com/polybar/polybar/issues/2674))
|
||||||
@ -101,7 +176,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- 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 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).
|
- 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.
|
- 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.
|
- 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/user/ipc.html) for what exactly this means.
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
- New dependency: [libuv](https://github.com/libuv/libuv). At least version 1.3 is required.
|
- New dependency: [libuv](https://github.com/libuv/libuv). At least version 1.3 is required.
|
||||||
@ -238,7 +313,9 @@ 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.3...HEAD
|
[Unreleased]: https://github.com/polybar/polybar/compare/3.7.1...HEAD
|
||||||
|
[3.7.1]: https://github.com/polybar/polybar/releases/tag/3.7.1
|
||||||
|
[3.7.0]: https://github.com/polybar/polybar/releases/tag/3.7.0
|
||||||
[3.6.3]: https://github.com/polybar/polybar/releases/tag/3.6.3
|
[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
|
||||||
|
@ -22,6 +22,14 @@ else()
|
|||||||
set(APP_VERSION "${version_txt}")
|
set(APP_VERSION "${version_txt}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Set the default installation prefix to /usr
|
||||||
|
# Otherwise the default value is /usr/local which causes the default config
|
||||||
|
# file to be installed to /usr/local/etc, with /usr, cmake has special handling
|
||||||
|
# for this.
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Project-default installation prefix" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH
|
list(APPEND CMAKE_MODULE_PATH
|
||||||
${PROJECT_SOURCE_DIR}/cmake
|
${PROJECT_SOURCE_DIR}/cmake
|
||||||
${PROJECT_SOURCE_DIR}/cmake/common
|
${PROJECT_SOURCE_DIR}/cmake/common
|
||||||
@ -60,10 +68,9 @@ if(BUILD_TESTS)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
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_FULL_SYSCONFDIR}/${PROJECT_NAME}
|
||||||
COMPONENT config)
|
COMPONENT config)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ PR being rejected because the feature you implemented was not actually something
|
|||||||
we want in polybar.
|
we want in polybar.
|
||||||
|
|
||||||
Issues with any of the following labels are generally safe to start working on,
|
Issues with any of the following labels are generally safe to start working on,
|
||||||
unless someone else has already claimed them:
|
unless they also have the `needs confirmation` label or someone else has
|
||||||
|
already claimed them:
|
||||||
|
|
||||||
* [bug](https://github.com/polybar/polybar/labels/bug)
|
* [bug](https://github.com/polybar/polybar/labels/bug)
|
||||||
* [confirmed](https://github.com/polybar/polybar/labels/confirmed)
|
* [confirmed](https://github.com/polybar/polybar/labels/confirmed)
|
||||||
@ -98,8 +99,9 @@ If possible, you should also add tests for the things you write.
|
|||||||
However, this is not always possible, for example when working on modules.
|
However, this is not always possible, for example when working on modules.
|
||||||
But at least isolated components should be tested.
|
But at least isolated components should be tested.
|
||||||
|
|
||||||
See the [testing page](https://github.com/polybar/polybar/wiki/Testing) on the
|
See the [testing
|
||||||
wiki for more information.
|
page](https://polybar.readthedocs.io/en/latest/dev/testing.html) in the
|
||||||
|
documentation.
|
||||||
Also don't hesitate to ask for help, testing isn't that mature in polybar yet
|
Also don't hesitate to ask for help, testing isn't that mature in polybar yet
|
||||||
and some things may be harder/impossible to test right now.
|
and some things may be harder/impossible to test right now.
|
||||||
|
|
||||||
@ -153,7 +155,8 @@ repo.
|
|||||||
|
|
||||||
### Style
|
### Style
|
||||||
|
|
||||||
Please read our [style guide](https://github.com/polybar/polybar/wiki/Style-Guide).
|
Please read our [style
|
||||||
|
guide](https://polybar.readthedocs.io/en/latest/dev/style-guide.html).
|
||||||
|
|
||||||
## Donations
|
## Donations
|
||||||
|
|
||||||
|
49
README.md
49
README.md
@ -1,5 +1,6 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="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,19 @@ 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 **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 **Void Linux**, you can install [polybar](https://github.com/void-linux/void-packages/blob/master/srcpkgs/polybar/template) using `xbps-install -S polybar`.
|
||||||
|
|
||||||
@ -110,16 +116,13 @@ 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
|
If you are using **FreeBSD**, [polybar](https://www.freshports.org/x11/polybar) can be installed using `pkg install polybar`. Make sure you are using the `latest` package branch.
|
||||||
[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 **Gentoo**, both release and git-master versions are available in the [main](https://packages.gentoo.org/packages/x11-misc/polybar) repository.
|
||||||
|
|
||||||
@ -133,19 +136,23 @@ If you can't find your distro here, you will have to [build from source](https:/
|
|||||||
## Community
|
## Community
|
||||||
Want to get in touch?
|
Want to get in touch?
|
||||||
|
|
||||||
* Join our Gitter room at [gitter.im/polybar/polybar](https://gitter.im/polybar/polybar)
|
* Visit our [Discussion page](https://github.com/polybar/polybar/discussions)
|
||||||
* We have our own subreddit at [r/polybar](https://www.reddit.com/r/polybar).
|
* Join our Gitter room at [`gitter.im/polybar/polybar`](https://gitter.im/polybar/polybar)
|
||||||
* Chat with us in the `#polybar` IRC channel on the [`irc.libera.chat:6697`](https://libera.chat/) server.
|
* 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
|
## Contributors
|
||||||
|
|
||||||
|
### Maintainers
|
||||||
|
* Patrick Ziegler [**@patrick96**](https://github.com/patrick96)
|
||||||
|
|
||||||
### Owner
|
### Owner
|
||||||
* Michael Carlberg [**@jaagr**](https://github.com/jaagr/)
|
* Michael Carlberg [**@jaagr**](https://github.com/jaagr/)
|
||||||
|
|
||||||
### Maintainers
|
### Former Maintainers
|
||||||
|
* [**@Lomadriel**](https://github.com/Lomadriel)
|
||||||
* [**@NBonaparte**](https://github.com/NBonaparte)
|
* [**@NBonaparte**](https://github.com/NBonaparte)
|
||||||
* Chase Geigle [**@skystrife**](https://github.com/skystrife)
|
* Chase Geigle [**@skystrife**](https://github.com/skystrife)
|
||||||
* Patrick Ziegler [**@patrick96**](https://github.com/patrick96)
|
|
||||||
|
|
||||||
### Logo Design by
|
### Logo Design by
|
||||||
* [**@Tobaloidee**](https://github.com/Tobaloidee)
|
* [**@Tobaloidee**](https://github.com/Tobaloidee)
|
||||||
@ -227,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`
|
||||||
|
32
SUPPORT.md
32
SUPPORT.md
@ -1,14 +1,34 @@
|
|||||||
Getting Help
|
# Getting Help
|
||||||
============
|
|
||||||
|
|
||||||
If you need help or troubleshooting tips or just have a question:
|
If you need help or troubleshooting tips or just have a question:
|
||||||
|
|
||||||
* If applicable, go through our [debugging guide](https://github.com/polybar/polybar/wiki/Debugging-your-Config).
|
* If applicable, go through our [debugging guide](https://github.com/polybar/polybar/wiki/Debugging-your-Config).
|
||||||
* Read the [Known Issues page](https://github.com/polybar/polybar/wiki/Known-Issues), maybe others had the same issue before.
|
* Read the [Known Issues page](https://github.com/polybar/polybar/wiki/Known-Issues), maybe others had the same issue before.
|
||||||
* 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)
|
* Ask your question on [GitHub Discussions](https://github.com/polybar/polybar/discussions)
|
||||||
* Ask in our reddit community at [r/polybar](https://www.reddit.com/r/polybar)
|
* Join our Gitter room at [`gitter.im/polybar/polybar`](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 in our reddit community at [`r/polybar`](https://www.reddit.com/r/polybar)
|
||||||
|
* Join the official IRC channel `#polybar` on the [`irc.libera.chat:6697`](https://libera.chat/) network. This is IRC, you will need to be connected to receive answers.
|
||||||
* 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.
|
**Do not** use the GitHub issue tracker to ask for help or if you have questions, it is meant for bug reports.
|
||||||
|
Issues will be closed and you will be referred to the above resources.
|
||||||
|
|
||||||
|
## Asking Quality Questions
|
||||||
|
|
||||||
|
Spending some time to precisely frame your question will save a lot of time.
|
||||||
|
You will better understand your problem and may be able to solve it yourself
|
||||||
|
and other will be able to better understand what you are asking.
|
||||||
|
Here are some tips:
|
||||||
|
|
||||||
|
* Be explicit and precise:
|
||||||
|
* What are you trying to achieve?
|
||||||
|
* What problems have you encountered while trying to achieve this?
|
||||||
|
* What is stopping you from overcoming these problems?
|
||||||
|
* If a problem is difficult to describe, screenshots can help. Do not make
|
||||||
|
screenshots of your config file or error messages, copy-paste them as text.
|
||||||
|
* Provide as much context as possible. In most cases this includes at least the following:
|
||||||
|
* Window Manager
|
||||||
|
* Polybar version
|
||||||
|
* Relevant portions of your config file. If you are not sure what is relevant, provide the whole thing.
|
||||||
|
* How you start polybar
|
||||||
|
@ -20,3 +20,5 @@ set(SETTING_PATH_MESSAGING_FIFO "/tmp/polybar_mqueue.%pid%"
|
|||||||
CACHE STRING "Path to file containing the current temperature")
|
CACHE STRING "Path to file containing the current temperature")
|
||||||
set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp"
|
set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp"
|
||||||
CACHE STRING "Path to file containing the current temperature")
|
CACHE STRING "Path to file containing the current temperature")
|
||||||
|
set(SETTING_PATH_THERMAL_ZONE_WILDCARD "/sys/class/thermal/thermal_zone*"
|
||||||
|
CACHE STRING "Wildcard path to different thermal zones")
|
||||||
|
@ -17,13 +17,23 @@ add_custom_target(uninstall
|
|||||||
# folders where the clang tools should operate
|
# folders where the clang tools should operate
|
||||||
set(CLANG_SEARCH_PATHS ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/tests)
|
set(CLANG_SEARCH_PATHS ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/tests)
|
||||||
|
|
||||||
# Target: codeformat (clang-format) {{{
|
# Runs clang-format on all source files
|
||||||
|
add_custom_target(
|
||||||
|
clangformat
|
||||||
|
COMMAND ${PROJECT_SOURCE_DIR}/common/file-runner.py
|
||||||
|
--dirs ${CLANG_SEARCH_PATHS}
|
||||||
|
-- clang-format -style=file -i --verbose
|
||||||
|
)
|
||||||
|
|
||||||
add_custom_target(codeformat)
|
# Dry-runs clang-format on all source files
|
||||||
add_custom_command(TARGET codeformat
|
# Useful for CI since it will exit with an error code
|
||||||
COMMAND ${PROJECT_SOURCE_DIR}/common/clang-format.sh ${CLANG_SEARCH_PATHS})
|
add_custom_target(
|
||||||
|
clangformat-dryrun
|
||||||
|
COMMAND ${PROJECT_SOURCE_DIR}/common/file-runner.py
|
||||||
|
--dirs ${CLANG_SEARCH_PATHS}
|
||||||
|
-- clang-format -style=file --dry-run -Werror --verbose
|
||||||
|
)
|
||||||
|
|
||||||
# }}}
|
|
||||||
# Target: codecheck (clang-tidy) {{{
|
# Target: codecheck (clang-tidy) {{{
|
||||||
|
|
||||||
add_custom_target(codecheck)
|
add_custom_target(codecheck)
|
||||||
|
@ -13,11 +13,12 @@ if (BUILD_DOC)
|
|||||||
endif()
|
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")
|
||||||
message_colored(STATUS " BINDIR: ${CMAKE_INSTALL_FULL_BINDIR}" "32")
|
message_colored(STATUS " BINDIR: ${CMAKE_INSTALL_FULL_BINDIR}" "32")
|
||||||
message_colored(STATUS " DATADIR: ${CMAKE_INSTALL_FULL_DATADIR}" "32")
|
message_colored(STATUS " DATADIR: ${CMAKE_INSTALL_FULL_DATADIR}" "32")
|
||||||
message_colored(STATUS " DOCDIR: ${CMAKE_INSTALL_FULL_DOCDIR}" "32")
|
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_colored(STATUS " SYSCONFDIR: ${CMAKE_INSTALL_FULL_SYSCONFDIR}" "32")
|
||||||
|
|
||||||
message(STATUS " Targets:")
|
message(STATUS " Targets:")
|
||||||
colored_option(" polybar" BUILD_POLYBAR)
|
colored_option(" polybar" BUILD_POLYBAR)
|
||||||
|
@ -15,20 +15,19 @@ endif()
|
|||||||
option(CXXLIB_CLANG "Link against libc++" OFF)
|
option(CXXLIB_CLANG "Link against libc++" OFF)
|
||||||
option(CXXLIB_GCC "Link against stdlibc++" OFF)
|
option(CXXLIB_GCC "Link against stdlibc++" OFF)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
|
||||||
|
|
||||||
set(POLYBAR_FLAGS "" CACHE STRING "C++ compiler flags used for compiling polybar")
|
set(POLYBAR_FLAGS "" CACHE STRING "C++ compiler flags used for compiling polybar")
|
||||||
|
|
||||||
list(APPEND cxx_base -Wall -Wextra -Wpedantic)
|
list(APPEND cxx_base -Wall -Wextra -Wpedantic -Wdeprecated-copy-dtor)
|
||||||
list(APPEND cxx_debug -DDEBUG -g2)
|
list(APPEND cxx_debug -DDEBUG -g2 -Og)
|
||||||
list(APPEND cxx_minsizerel "")
|
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_sanitize ${cxx_debug} -O0 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls)
|
||||||
list(APPEND cxx_coverage --coverage)
|
list(APPEND cxx_coverage ${cxx_debug} --coverage)
|
||||||
|
|
||||||
list(APPEND cxx_linker_base "")
|
list(APPEND cxx_linker_base "")
|
||||||
list(APPEND cxx_linker_minsizerel "")
|
list(APPEND cxx_linker_minsizerel "")
|
||||||
@ -79,8 +78,6 @@ elseif(CXXLIB_GCC)
|
|||||||
list(APPEND cxx_linker_base -lstdc++)
|
list(APPEND cxx_linker_base -lstdc++)
|
||||||
endif()
|
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_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_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}")
|
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${CMAKE_SHARED_LINKER_FLAGS_COVERAGE}")
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if [ $# -lt 1 ]; then
|
|
||||||
echo "$0 DIR..." 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Search paths
|
|
||||||
search="${*:-.}"
|
|
||||||
|
|
||||||
echo "$0 in $search"
|
|
||||||
|
|
||||||
# shellcheck disable=2086
|
|
||||||
find $search -regex ".*.[c|h]pp" \
|
|
||||||
-exec printf "\\033[32;1m** \\033[0mFormatting %s\\n" {} \; \
|
|
||||||
-exec clang-format -style=file -i {} \;
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
50
common/file-runner.py
Executable file
50
common/file-runner.py
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
EXTENSIONS = set('.' + ext for ext in ['c', 'h', 'cpp', 'hpp', 'inl'])
|
||||||
|
|
||||||
|
|
||||||
|
def get_files(dirs):
|
||||||
|
"""
|
||||||
|
Generator which yields all files in the given directories with any of the
|
||||||
|
EXTENSIONS.
|
||||||
|
"""
|
||||||
|
for dir in dirs:
|
||||||
|
for root, _, files in os.walk(dir):
|
||||||
|
for file in files:
|
||||||
|
path = Path(os.path.join(root, file))
|
||||||
|
if path.suffix in EXTENSIONS:
|
||||||
|
yield path
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="""
|
||||||
|
Run command on all C/C++ source files in the given directories
|
||||||
|
""")
|
||||||
|
parser.add_argument('--dirs', type=Path, nargs='+',
|
||||||
|
help='Directories to search in')
|
||||||
|
parser.add_argument('command', nargs='+',
|
||||||
|
help='Command to which to pass found files')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
all_files = list(str(file) for file in get_files(args.dirs))
|
||||||
|
|
||||||
|
if not all_files:
|
||||||
|
print("No files found")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
result = subprocess.run(args.command + all_files)
|
||||||
|
print(f'Formatted {len(all_files)} files')
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
sys.exit(result.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -1,24 +1,22 @@
|
|||||||
# 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.5.7
|
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"
|
||||||
arch=("i686" "x86_64")
|
# 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"
|
url="https://github.com/polybar/polybar"
|
||||||
license=("MIT")
|
license=("MIT")
|
||||||
depends=("libuv" "cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm"
|
depends=("libuv" "cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm"
|
||||||
"xcb-util-cursor" "alsa-lib" "libpulse" "libmpdclient" "libnl"
|
"xcb-util-cursor" "alsa-lib" "libpulse" "libmpdclient" "libnl"
|
||||||
"jsoncpp" "curl")
|
"jsoncpp" "curl")
|
||||||
optdepends=("i3-wm: i3 module support"
|
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" "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")
|
||||||
install="${_pkgname}.install"
|
|
||||||
source=("${_pkgname}::git+${url}.git")
|
source=("${_pkgname}::git+${url}.git")
|
||||||
sha256sums=("SKIP")
|
sha256sums=("SKIP")
|
||||||
|
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
# 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"
|
|
||||||
}
|
|
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 |
0
banner.png → doc/_static/banner.png
vendored
0
banner.png → doc/_static/banner.png
vendored
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
BIN
doc/_static/nerd-fonts/bad.png
vendored
Normal file
BIN
doc/_static/nerd-fonts/bad.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
BIN
doc/_static/nerd-fonts/good.png
vendored
Normal file
BIN
doc/_static/nerd-fonts/good.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
26
doc/_templates/layout.html
vendored
Normal file
26
doc/_templates/layout.html
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{% extends "!layout.html" -%}
|
||||||
|
{# Refer to https://github.com/readthedocs/sphinx_rtd_theme/blob/master/sphinx_rtd_theme/layout.html #}
|
||||||
|
|
||||||
|
{%- block document %}
|
||||||
|
{#
|
||||||
|
Adds a warning message on the 'latest' version.
|
||||||
|
The warning is only added on readthedocs, if the version is 'latest'.
|
||||||
|
For the 'dev' folder, no warning is shown since the 'latest' version is
|
||||||
|
usually the most up-to-date.
|
||||||
|
#}
|
||||||
|
{% if READTHEDOCS and polybar_is_latest and not pagename.startswith('dev/') %}
|
||||||
|
<div class="admonition important">
|
||||||
|
<p class="admonition-title">Development Version</p>
|
||||||
|
<p>
|
||||||
|
This is the <code class="docutils literal notranslate"><span class="pre">latest</span></code>
|
||||||
|
(unstable) version of this documentation, which may document features
|
||||||
|
not available in or compatible with released stable versions of polybar.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
See the <a href="https://polybar.readthedocs.io/{{ pagename }}.html">stable version</a> of this documentation page instead.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ super() }}
|
||||||
|
{%- endblock %}
|
207
doc/conf.py
207
doc/conf.py
@ -18,49 +18,57 @@ import datetime
|
|||||||
import sphinx
|
import sphinx
|
||||||
import packaging.version
|
import packaging.version
|
||||||
|
|
||||||
def get_version(root_path):
|
from sphinx.util.docfields import Field
|
||||||
"""
|
from sphinx.locale import _
|
||||||
Reads the polybar version from the version.txt at the root of the repo.
|
|
||||||
"""
|
|
||||||
path = Path(root_path) / "version.txt"
|
|
||||||
with open(path, "r") as f:
|
|
||||||
for line in f.readlines():
|
|
||||||
if not line.startswith("#"):
|
|
||||||
# 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))
|
|
||||||
|
def get_version(root_path):
|
||||||
|
"""
|
||||||
|
Reads the polybar version from the version.txt at the root of the repo.
|
||||||
|
"""
|
||||||
|
path = Path(root_path) / "version.txt"
|
||||||
|
with open(path, "r") as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
if not line.startswith("#"):
|
||||||
|
# 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))
|
||||||
|
|
||||||
|
|
||||||
|
sphinx_version = packaging.version.parse(sphinx.__version__)
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
project = 'Polybar User Manual'
|
project = 'Polybar User Manual'
|
||||||
copyright = '2016-{}, Michael Carlberg & contributors'.format(
|
copyright = '2016-{}, Michael Carlberg & contributors'.format(
|
||||||
datetime.datetime.now().year
|
datetime.datetime.now().year
|
||||||
)
|
)
|
||||||
author = 'Polybar Team'
|
author = 'Polybar Team'
|
||||||
|
|
||||||
# is whether we are on readthedocs.io
|
# is whether we are on readthedocs.io
|
||||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||||
|
|
||||||
if on_rtd:
|
if on_rtd:
|
||||||
# On readthedocs, cmake isn't run so the version string isn't available
|
# On readthedocs, cmake isn't run so the version string isn't available
|
||||||
version = os.environ.get('READTHEDOCS_VERSION', None)
|
version = os.environ.get('READTHEDOCS_VERSION', None)
|
||||||
else:
|
else:
|
||||||
# The short X.Y version
|
# The short X.Y version
|
||||||
version = '@APP_VERSION@'
|
version = '@APP_VERSION@'
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags
|
# The full version, including alpha/beta/rc tags
|
||||||
release = version
|
release = version
|
||||||
|
|
||||||
# Set path to documentation
|
# Set path to documentation
|
||||||
if on_rtd:
|
if on_rtd:
|
||||||
# On readthedocs conf.py is already in the doc folder
|
# On readthedocs conf.py is already in the doc folder
|
||||||
doc_path = '.'
|
doc_path = '.'
|
||||||
else:
|
else:
|
||||||
# In all other builds conf.py is configured with cmake and put into the
|
# In all other builds conf.py is configured with cmake and put into the
|
||||||
# build folder.
|
# build folder.
|
||||||
doc_path = '@doc_path@'
|
doc_path = '@doc_path@'
|
||||||
|
|
||||||
# The version from the version.txt file. Since we are not always first
|
# The version from the version.txt file. Since we are not always first
|
||||||
# configured by cmake, we don't necessarily have access to the current version
|
# configured by cmake, we don't necessarily have access to the current version
|
||||||
@ -77,8 +85,18 @@ version_txt = get_version(Path(doc_path).absolute().parent)
|
|||||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
# ones.
|
# ones.
|
||||||
extensions = [
|
extensions = [
|
||||||
|
"sphinx.ext.extlinks",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if on_rtd:
|
||||||
|
extensions += [
|
||||||
|
# The custom 404 page is only needed
|
||||||
|
"notfound.extension",
|
||||||
|
# The search extension works only on readthedocs
|
||||||
|
# See https://readthedocs-sphinx-search.readthedocs.io
|
||||||
|
"sphinx_search.extension",
|
||||||
|
]
|
||||||
|
|
||||||
# Add any paths that contain templates here, relative to this directory.
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
templates_path = [doc_path + '/_templates']
|
templates_path = [doc_path + '/_templates']
|
||||||
|
|
||||||
@ -96,7 +114,7 @@ master_doc = 'index'
|
|||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = None
|
# language = None
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
@ -110,22 +128,45 @@ highlight_language = 'none'
|
|||||||
|
|
||||||
smartquotes = False
|
smartquotes = False
|
||||||
|
|
||||||
|
# Quickly link to issues or PRs using :issue:`...` or :pull:`...`
|
||||||
|
if sphinx_version >= packaging.version.parse("4.0.0"):
|
||||||
|
extlinks = {
|
||||||
|
"issue": ("https://github.com/polybar/polybar/issues/%s", "#%s"),
|
||||||
|
"pull": ("https://github.com/polybar/polybar/pull/%s", "PR #%s"),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# Versions before 4.0 (e.g. on readthedocs) do not support %s in the
|
||||||
|
# caption and simply append the value
|
||||||
|
extlinks = {
|
||||||
|
"issue": ("https://github.com/polybar/polybar/issues/%s", "#"),
|
||||||
|
"pull": ("https://github.com/polybar/polybar/pull/%s", "PR #"),
|
||||||
|
}
|
||||||
|
|
||||||
|
extlinks_detect_hardcoded_links = True
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
||||||
# a list of builtin themes.
|
|
||||||
#
|
|
||||||
if on_rtd or os.environ.get('USE_RTD_THEME', '0') == '1':
|
|
||||||
html_theme = 'sphinx_rtd_theme'
|
|
||||||
else:
|
|
||||||
html_theme = 'alabaster'
|
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
# documentation.
|
# documentation.
|
||||||
#
|
#
|
||||||
# html_theme_options = {}
|
html_theme_options = {}
|
||||||
|
|
||||||
|
html_context = {
|
||||||
|
'polybar_is_latest': version == 'latest',
|
||||||
|
}
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
if on_rtd or os.environ.get('USE_RTD_THEME', '0') == '1':
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
html_theme_options['collapse_navigation'] = False
|
||||||
|
html_theme_options['style_external_links'] = True
|
||||||
|
else:
|
||||||
|
html_theme = 'alabaster'
|
||||||
|
html_theme_options['description'] = version
|
||||||
|
|
||||||
# Add any paths that contain custom static files (such as style sheets) here,
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
# relative to this directory. They are copied after the builtin static files,
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
@ -183,9 +224,18 @@ latex_documents = [
|
|||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (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-msg.1', 'polybar-msg', 'Send IPC messages to polybar', [], 1),
|
'man/polybar.1', 'polybar',
|
||||||
('man/polybar.5', 'polybar', 'configuration file for polybar(1)', [], 5)
|
'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_make_section_directory = False
|
man_make_section_directory = False
|
||||||
@ -223,33 +273,82 @@ epub_exclude_files = ['search.html']
|
|||||||
# The 'versionadded' and 'versionchanged' directives are overridden.
|
# The 'versionadded' and 'versionchanged' directives are overridden.
|
||||||
suppress_warnings = ['app.add_directive']
|
suppress_warnings = ['app.add_directive']
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
|
||||||
|
# Adds a new directive for document a polybar config setting
|
||||||
|
# Inside goes the description of the option as well as custom roles to
|
||||||
|
# document the type, default value, etc:
|
||||||
|
# .. poly-setting:: NAME
|
||||||
|
#
|
||||||
|
# Description
|
||||||
|
# :type: ...
|
||||||
|
# :default: ...
|
||||||
|
app.add_object_type(
|
||||||
|
'poly-setting',
|
||||||
|
'poly-setting',
|
||||||
|
objname='configuration value',
|
||||||
|
indextemplate='pair: %s; configuration value',
|
||||||
|
doc_field_types=[
|
||||||
|
Field('type',
|
||||||
|
label=_("Type"),
|
||||||
|
names=['type'],
|
||||||
|
has_arg=False,
|
||||||
|
),
|
||||||
|
Field('tags',
|
||||||
|
label=_("Available Tags"),
|
||||||
|
names=['tags'],
|
||||||
|
has_arg=False,
|
||||||
|
),
|
||||||
|
Field('tokens',
|
||||||
|
label=_("Supported Tokens"),
|
||||||
|
names=['tokens'],
|
||||||
|
has_arg=False,
|
||||||
|
),
|
||||||
|
Field('default',
|
||||||
|
label=_("Default Value"),
|
||||||
|
names=['default'],
|
||||||
|
has_arg=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
inject_version_directives(app)
|
||||||
|
except NameError:
|
||||||
|
# Function was not defined because sphinx version was too low
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# It is not exactly clear in which version the VersionChange class was
|
# It is not exactly clear in which version the VersionChange class was
|
||||||
# introduced, but we know it is available in at least 1.8.5.
|
# introduced, but we know it is available in at least 1.8.5.
|
||||||
# This feature is mainly needed for the online docs on readthedocs for the docs
|
# This feature is mainly needed for the online docs on readthedocs for the docs
|
||||||
# built from master, documentation built for proper releases should not even
|
# built from master, documentation built for proper releases should not even
|
||||||
# mention unreleased changes. Because of that it's not that important that this
|
# mention unreleased changes. Because of that it's not that important that this
|
||||||
# is added to local builds.
|
# is added to local builds.
|
||||||
if packaging.version.parse(sphinx.__version__) >= packaging.version.parse("1.8.5"):
|
if sphinx_version >= packaging.version.parse("1.8.5"):
|
||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from docutils.nodes import Node
|
from docutils.nodes import Node
|
||||||
from sphinx.domains.changeset import VersionChange
|
from sphinx.domains.changeset import VersionChange
|
||||||
|
|
||||||
def setup(app):
|
def inject_version_directives(app):
|
||||||
app.add_directive('deprecated', VersionDirective)
|
app.add_directive('deprecated', VersionDirective)
|
||||||
app.add_directive('versionadded', VersionDirective)
|
app.add_directive('versionadded', VersionDirective)
|
||||||
app.add_directive('versionchanged', VersionDirective)
|
app.add_directive('versionchanged', VersionDirective)
|
||||||
|
|
||||||
class VersionDirective(VersionChange):
|
class VersionDirective(VersionChange):
|
||||||
"""
|
"""
|
||||||
Overwrites the Sphinx directive for versionchanged, versionadded, and
|
Overwrites the Sphinx directive for versionchanged, versionadded, and
|
||||||
deprecated and adds an unreleased tag to versions that are not yet released
|
deprecated and adds an unreleased tag to versions that are not yet
|
||||||
"""
|
released
|
||||||
def run(self) -> List[Node]:
|
"""
|
||||||
directive_version = packaging.version.parse(self.arguments[0])
|
|
||||||
parsed_version_txt = packaging.version.parse(version_txt)
|
|
||||||
|
|
||||||
if directive_version > parsed_version_txt:
|
def run(self) -> List[Node]:
|
||||||
self.arguments[0] += " (unreleased)"
|
directive_version = packaging.version.parse(self.arguments[0])
|
||||||
|
parsed_version_txt = packaging.version.parse(version_txt)
|
||||||
|
|
||||||
return super().run()
|
if directive_version > parsed_version_txt:
|
||||||
|
self.arguments[0] += " (unreleased)"
|
||||||
|
|
||||||
|
return super().run()
|
||||||
|
@ -58,14 +58,18 @@ cursor-scroll = ns-resize
|
|||||||
|
|
||||||
enable-ipc = true
|
enable-ipc = true
|
||||||
|
|
||||||
; tray-position = right
|
|
||||||
|
|
||||||
; wm-restack = generic
|
; wm-restack = generic
|
||||||
; wm-restack = bspwm
|
; wm-restack = bspwm
|
||||||
; wm-restack = i3
|
; wm-restack = i3
|
||||||
|
|
||||||
; override-redirect = true
|
; override-redirect = true
|
||||||
|
|
||||||
|
[module/systray]
|
||||||
|
type = internal/tray
|
||||||
|
|
||||||
|
format-margin = 8pt
|
||||||
|
tray-spacing = 16pt
|
||||||
|
|
||||||
[module/xworkspaces]
|
[module/xworkspaces]
|
||||||
type = internal/xworkspaces
|
type = internal/xworkspaces
|
||||||
|
|
||||||
|
41
doc/dev/getting-started.rst
Normal file
41
doc/dev/getting-started.rst
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Getting Started
|
||||||
|
===============
|
||||||
|
|
||||||
|
Setting up polybar for development is basically the same process as `compiling
|
||||||
|
it from source <https://github.com/polybar/polybar/wiki/Compiling>`_.
|
||||||
|
However, we recommend using the ``Debug`` or ``Sanitize`` cmake build type when
|
||||||
|
configuring the project:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
|
# Or
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Sanitize ..
|
||||||
|
|
||||||
|
This will give you debug symbols in the executable and the ``Sanitize`` build
|
||||||
|
type will also enable the ``AddressSanitizer`` and
|
||||||
|
``UndefinedBehaviorSanitizer``, which can give you very useful information
|
||||||
|
about crashes and undefined behavior at runtime.
|
||||||
|
|
||||||
|
Editors
|
||||||
|
-------
|
||||||
|
|
||||||
|
Since this is a cmake project, most IDEs will have built-in support or a plugin
|
||||||
|
to automatically setup this project.
|
||||||
|
|
||||||
|
In addition, the ``cmake`` command creates a ``compile_commands.json`` file in
|
||||||
|
the build folder, which can be used by many `language servers
|
||||||
|
<https://microsoft.github.io/language-server-protocol/>`_.
|
||||||
|
If you are using a C++ language server in your editor, it should be as easy as
|
||||||
|
symlinking the ``compile_commands.json`` into the repo root directory:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
ln -s build/compile_commands.json .
|
||||||
|
|
||||||
|
Distro-Specific Setup
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The wiki contains user-contributed `setup tips
|
||||||
|
<https://github.com/polybar/polybar/wiki/Distro-Specific-Setup>`_ for some
|
||||||
|
distros.
|
@ -78,9 +78,8 @@ Instead of ``sudo make install``, you will most likely want to use
|
|||||||
Finishing Up
|
Finishing Up
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Finally, subscribe to our `GitHub thread for package maintainers
|
Finally, subscribe to our :issue:`GitHub thread for package maintainers <1971>`
|
||||||
<https://github.com/polybar/polybar/issues/1971>`_ to get notified about new
|
to get notified about new releases and changes to how polybar is built.
|
||||||
releases and changes to how polybar is built.
|
|
||||||
If you want to, you can also open a PR to add your package to the `Getting
|
If you want to, you can also open a PR to add your package to the `Getting
|
||||||
Started <https://github.com/polybar/polybar#getting-started>`_ section of our
|
Started <https://github.com/polybar/polybar#getting-started>`_ section of our
|
||||||
README.
|
README.
|
||||||
|
@ -90,8 +90,8 @@ branch and cherry-picks the bugfix commits.
|
|||||||
|
|
||||||
Alternatively, the contributor can also ``git rebase --onto`` to base the
|
Alternatively, the contributor can also ``git rebase --onto`` to base the
|
||||||
branch off the previous release tag. However, in most cases it makes sense for
|
branch off the previous release tag. However, in most cases it makes sense for
|
||||||
a maintainer to create the release branch since they will also need to add a
|
a maintainer to create the release branch since they will also need to create
|
||||||
`Release Commit`_ to it.
|
a `Release PR`_ for it.
|
||||||
|
|
||||||
Once the release branch is created and contains the right commits, the
|
Once the release branch is created and contains the right commits, the
|
||||||
maintainer should follow `Publishing a new Release`_ to finish this patch
|
maintainer should follow `Publishing a new Release`_ to finish this patch
|
||||||
@ -110,13 +110,19 @@ Publishing a new Release
|
|||||||
The process for publishing a release is the same for all release types. It goes
|
The process for publishing a release is the same for all release types. It goes
|
||||||
as follows:
|
as follows:
|
||||||
|
|
||||||
* A `Release commit`_ is added to the tip of the release branch.
|
* A `Release PR`_ is created for the release. 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 without message is created locally at the
|
||||||
* After approval, the GitHub release publishing tool is used to publish the
|
tip of the release branch and pushed:
|
||||||
release and tag the tip of the release branch (the release commit).
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
git tag -m "" -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
|
||||||
@ -136,16 +142,23 @@ as follows:
|
|||||||
Here ``<release-branch>`` is either a ``release/X.Y.0`` branch or a
|
Here ``<release-branch>`` is either a ``release/X.Y.0`` branch or a
|
||||||
``hotfix/X.Y.Z`` branch.
|
``hotfix/X.Y.Z`` branch.
|
||||||
|
|
||||||
Release Commit
|
Release PR
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
When merging, a release commit must be at the tip of the release branch.
|
The final state of the release branch is prepared as a draft PR on
|
||||||
|
GitHub.
|
||||||
|
That PR is not merged from the GitHub interface though.
|
||||||
|
|
||||||
The release commit needs to update the version number in:
|
The release PR must do the following things:
|
||||||
|
|
||||||
* ``version.txt``
|
* Write any missing migration guides for:
|
||||||
|
|
||||||
The release commit must also finalize the `Changelog`_ for this release.
|
* Deprecated or removed options
|
||||||
|
* New features that it might be worth migrating to
|
||||||
|
* Have a release commit at its tip with the message ``Version X.Y.Z`` and the following changes
|
||||||
|
|
||||||
|
* Finalizes the `Changelog`_ for this release
|
||||||
|
* Updates the version number in ``version.txt``
|
||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
@ -193,8 +206,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``.
|
||||||
@ -202,23 +215,30 @@ 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.
|
new contributors should be generated and put at the end of the release notes.
|
||||||
The generated list of PRs can be removed.
|
The generated list of PRs can be removed.
|
||||||
|
|
||||||
|
For minor and major releases, add a link to the migration guide directly under
|
||||||
|
the ``## Changelog`` header:
|
||||||
|
|
||||||
|
.. code-block:: markdown
|
||||||
|
|
||||||
|
**[Migration Guide](https://polybar.readthedocs.io/en/stable/migration/X.Y/index.html)**
|
||||||
|
|
||||||
|
At the bottom, check the two boxes "Set as the latest release" and "Create a
|
||||||
|
discussion for this release" (select the category "Announcements").
|
||||||
|
|
||||||
After-Release Checklist
|
After-Release Checklist
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* Make sure all the new functionality is documented on the wiki
|
* Verify the release archive (see `Verify Release`_)
|
||||||
* Mark deprecated features appropriately (see `Deprecations`_)
|
* Update the Wiki
|
||||||
* Remove all unreleased notes from the wiki (not for patch releases)
|
|
||||||
* Inform packagers of new release in `#1971
|
* Make sure all the new functionality is documented
|
||||||
<https://github.com/polybar/polybar/issues/1971>`_. Mention any dependency
|
* Mark deprecated features appropriately (see `Deprecations`_)
|
||||||
|
* Remove all "unreleased" notes (not for patch releases)
|
||||||
|
* Inform packagers of new release in :issue:`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 +246,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
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
75
doc/dev/style-guide.rst
Normal file
75
doc/dev/style-guide.rst
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
Style Guide
|
||||||
|
===========
|
||||||
|
|
||||||
|
There is a ``.editorconfig`` and a ``.clang-format`` file in the project root
|
||||||
|
that defines some basic guidelines, mainly relating to indentation.
|
||||||
|
|
||||||
|
Code Formatting
|
||||||
|
---------------
|
||||||
|
|
||||||
|
We use ``clang-format`` for code formatting, the style rules are defined in
|
||||||
|
``.clang-format``, before submitting a PR, make sure to run the following command
|
||||||
|
on all the C++ files you changed:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
clang-format -style=file -i <FILES>
|
||||||
|
|
||||||
|
**Note:** Depending on which file you change, this may produce a lot of changes
|
||||||
|
because we have not run ``clang-format`` on all files in the project. This is
|
||||||
|
fine.
|
||||||
|
|
||||||
|
Indentation
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
Files use 2 spaces for indentation.
|
||||||
|
|
||||||
|
Line Width
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Lines should not be longer than 120 characters, ``clang-format`` will enforce
|
||||||
|
this when run. However, try to keep lines under 80 characters if it seems
|
||||||
|
reasonable in the current situation.
|
||||||
|
|
||||||
|
In some cases it makes sense to have lines longer than 80 characters for
|
||||||
|
readability. But long lines can just the same be unreadable, for example if you
|
||||||
|
have long if-conditions or use complex expressions as function parameters. Make
|
||||||
|
sure you only use longer lines if keeping it under 80 would be less readable.
|
||||||
|
|
||||||
|
Comments
|
||||||
|
--------
|
||||||
|
|
||||||
|
Use Doxygen ``/** */`` comments in front of functions, methods, types, members and
|
||||||
|
classes:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates a config object from a config file
|
||||||
|
*
|
||||||
|
* For modularity the parsing and storing of the config is separated
|
||||||
|
*/
|
||||||
|
class config_parser {
|
||||||
|
...
|
||||||
|
/**
|
||||||
|
* @brief Is used to resolve ${root...} references
|
||||||
|
*/
|
||||||
|
string m_barname;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
For all other comments use ``//`` for single-line and ``/* */`` for multi-line comments.
|
||||||
|
|
||||||
|
Your comments should describe the intent and purpose of your code, not necessarily what it does.
|
||||||
|
|
||||||
|
Header Files
|
||||||
|
------------
|
||||||
|
|
||||||
|
Header files should end in ``.hpp``.
|
||||||
|
|
||||||
|
We use pragmas instead of include guards to guarantee header files are included
|
||||||
|
only once:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#pragma once
|
26
doc/dev/testing.rst
Normal file
26
doc/dev/testing.rst
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
Polybar uses `googletest <https://google.github.io/googletest/>`_ as its
|
||||||
|
testing and mocking framework.
|
||||||
|
Tests live in the ``tests/`` directory; they can be enabled during cmake with
|
||||||
|
``-DBUILD_TESTS=ON`` and compiled with ``make all_unit_tests``.
|
||||||
|
|
||||||
|
Each test gets its own executable in ``build/tests``, which can be executed to run
|
||||||
|
a specific test.
|
||||||
|
|
||||||
|
Running all tests is preferably done with the following command:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
make check
|
||||||
|
|
||||||
|
This runs all available tests and prints the output in color for failed tests
|
||||||
|
only.
|
||||||
|
|
||||||
|
Adding New Tests
|
||||||
|
----------------
|
||||||
|
|
||||||
|
All new tests need to be added to the ``tests/CMakeLists.txt`` file. Have a look
|
||||||
|
at the other unit tests in ``tests/unit_tests`` to see how to write tests for your
|
||||||
|
code.
|
@ -14,6 +14,10 @@ Welcome to the official polybar documentation.
|
|||||||
|
|
||||||
user/actions
|
user/actions
|
||||||
user/ipc
|
user/ipc
|
||||||
|
user/modules/index
|
||||||
|
user/fonts/index
|
||||||
|
user/default-config
|
||||||
|
migration/index
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
@ -33,6 +37,9 @@ Welcome to the official polybar documentation.
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
:caption: Developer Documentation:
|
:caption: Developer Documentation:
|
||||||
|
|
||||||
|
dev/getting-started
|
||||||
|
dev/style-guide
|
||||||
|
dev/testing
|
||||||
dev/release-workflow
|
dev/release-workflow
|
||||||
|
|
||||||
Getting Help
|
Getting Help
|
||||||
|
40
doc/migration/3.7/index.rst
Normal file
40
doc/migration/3.7/index.rst
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Migrating From Version 3.6 to 3.7
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Text Module (``custom/text``)
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Using ``content`` to specify the text of the module is deprecated in favor of
|
||||||
|
using the same concepts as all other modules (formats and labels).
|
||||||
|
|
||||||
|
For example, the following text module:
|
||||||
|
|
||||||
|
.. code-block:: dosini
|
||||||
|
|
||||||
|
[module/text]
|
||||||
|
type = custom/text
|
||||||
|
content = Hello World
|
||||||
|
content-foreground = #ff0000
|
||||||
|
|
||||||
|
Should now look like this:
|
||||||
|
|
||||||
|
.. code-block:: dosini
|
||||||
|
|
||||||
|
[module/text]
|
||||||
|
type = custom/text
|
||||||
|
label = Hello World
|
||||||
|
label-foreground = #ff0000
|
||||||
|
|
||||||
|
Because it is set to its default value, the ``format`` setting can also be
|
||||||
|
completely left out.
|
||||||
|
|
||||||
|
In general, all properties on ``content`` also apply the same on ``label``
|
||||||
|
(e.g. ``background``, ``font``), except for ``offset``,
|
||||||
|
``prefix``, ``suffix`` (and their sub-properties).
|
||||||
|
Those three properties have to instead be applied to ``format`` (e.g.
|
||||||
|
``format-offset``).
|
||||||
|
|
||||||
|
System Tray
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. include:: tray.rst
|
57
doc/migration/3.7/tray.rst
Normal file
57
doc/migration/3.7/tray.rst
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
..
|
||||||
|
File included directly in other pages describing migrating to the new tray module
|
||||||
|
|
||||||
|
Polybar version 3.7 introduced the new tray module and deprecated the legacy
|
||||||
|
tray implementation which uses ``tray-position`` to position the tray.
|
||||||
|
You should switch over to the tray module as soon as possible.
|
||||||
|
|
||||||
|
The legacy tray was configured in the `bar section
|
||||||
|
<https://github.com/polybar/polybar/wiki/Configuration#bar-settings>`_, the
|
||||||
|
setting for the module live in that module's section of the config file.
|
||||||
|
The settings in the bar section don't always directly correspond to an
|
||||||
|
equivalent setting in the module section for the new tray module.
|
||||||
|
|
||||||
|
The following lists how each old setting in the bar section should be migrated:
|
||||||
|
|
||||||
|
``tray-position``
|
||||||
|
The tray is now positioned as a module and so its positioning is done by
|
||||||
|
placing it where you want it to appear in one of the three module lists
|
||||||
|
``modules-left``, ``modules-center``, ``modules-right``.
|
||||||
|
|
||||||
|
``tray-detached``
|
||||||
|
This setting does not have an equivalent, detaching the tray is no longer
|
||||||
|
possible.
|
||||||
|
|
||||||
|
``tray-maxsize``
|
||||||
|
The :poly-setting:`tray-size` setting now determines the size of tray icons.
|
||||||
|
|
||||||
|
``tray-transparent``
|
||||||
|
Was already deprecated and does not exist in the tray module.
|
||||||
|
Transparency is enabled automatically if a transparent background is used.
|
||||||
|
|
||||||
|
``tray-background``
|
||||||
|
Also exists in the module section (see :poly-setting:`tray-background`). Now,
|
||||||
|
the setting only applies to the icons themselves and no longer to the space
|
||||||
|
around them.
|
||||||
|
|
||||||
|
``tray-foreground``
|
||||||
|
Also exists in the module section with the same functionality (see
|
||||||
|
:poly-setting:`tray-foreground`).
|
||||||
|
|
||||||
|
``tray-offset-x``, ``tray-offset-y``
|
||||||
|
Has no direct equivalent in the module settings. Horizontally, the tray can
|
||||||
|
be moved in the same way other module content can be moved; by reordering the
|
||||||
|
modules or using things like ``format-offset``, ``format-margin``, or
|
||||||
|
``format-padding``.
|
||||||
|
The tray can't be moved vertically.
|
||||||
|
|
||||||
|
In any case, the tray can no longer be moved outside of the bar window.
|
||||||
|
|
||||||
|
``tray-padding``
|
||||||
|
Spacing between tray icons works a bit different now and needs to be
|
||||||
|
completely reconfigured (see :poly-setting:`tray-padding` and
|
||||||
|
:poly-setting:`tray-spacing`).
|
||||||
|
|
||||||
|
``tray-scale``
|
||||||
|
No longer exist. The size of the icons is solely determined by
|
||||||
|
:poly-setting:`tray-size`.
|
24
doc/migration/index.rst
Normal file
24
doc/migration/index.rst
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Polybar Migration Guides
|
||||||
|
========================
|
||||||
|
|
||||||
|
Updating polybar to the newest version often requires updating your
|
||||||
|
configuration files to use the newest features and replace outdated settings.
|
||||||
|
|
||||||
|
Starting from version 3.7, we include a small guide here for how to migrate
|
||||||
|
from the previous version.
|
||||||
|
If you are upgrading over multiple versions (e.g. from 3.5 to 3.7), also read
|
||||||
|
the migration guides for all versions in between.
|
||||||
|
|
||||||
|
For migration guides before version 3.7, please look at our `release blog posts
|
||||||
|
<https://polybar.github.io/blog/>`_.
|
||||||
|
|
||||||
|
When upgrading make sure to run polybar from the terminal and look for errors,
|
||||||
|
warnings, and deprecation messages.
|
||||||
|
This can save you a lot of issues in the future when deprecated settings and
|
||||||
|
features are removed.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: Guides
|
||||||
|
|
||||||
|
3.7/index
|
7
doc/requirements.txt
Normal file
7
doc/requirements.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Installing these packages is only really needed on readthedocs, building
|
||||||
|
# locally works as long as sphinx is installed.
|
||||||
|
# For local development, you may want to install some of these though.
|
||||||
|
sphinx~=7.2.6
|
||||||
|
sphinx-rtd-theme~=2.0.0rc2
|
||||||
|
sphinx-notfound-page~=1.0.0
|
||||||
|
readthedocs-sphinx-search~=0.3.1
|
16
doc/user/default-config.rst
Normal file
16
doc/user/default-config.rst
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Default Configuration
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. versionadded:: 3.6.0
|
||||||
|
|
||||||
|
Polybar's default configuration lives in ``/etc/polybar/config.ini`` and is
|
||||||
|
loaded if no other configuration file can be found.
|
||||||
|
|
||||||
|
|
||||||
|
.. image:: ../_static/default.png
|
||||||
|
:alt: Screenshot of default polybar configuration
|
||||||
|
|
||||||
|
.. literalinclude:: ../config.ini
|
||||||
|
:language: ini
|
||||||
|
:linenos:
|
||||||
|
:caption: :download:`Download <../config.ini>`
|
8
doc/user/fonts/index.rst
Normal file
8
doc/user/fonts/index.rst
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Fonts
|
||||||
|
=====
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
Wiki <https://github.com/polybar/polybar/wiki/Fonts>
|
||||||
|
Nerd Fonts <nerd-fonts>
|
54
doc/user/fonts/nerd-fonts.rst
Normal file
54
doc/user/fonts/nerd-fonts.rst
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
Nerd Fonts
|
||||||
|
==========
|
||||||
|
|
||||||
|
`Nerd Fonts <https://www.nerdfonts.com/>`_ (`GitHub
|
||||||
|
<https://github.com/ryanoasis/nerd-fonts/>`_) is a project that patches
|
||||||
|
together a textual font with font icons (or glyphs) from other projects (e.g.
|
||||||
|
`Font Awesome <https://github.com/FortAwesome/Font-Awesome>`_, `Material Design
|
||||||
|
Icons <https://github.com/Templarian/MaterialDesign>`_, etc.) into a single
|
||||||
|
font.
|
||||||
|
|
||||||
|
In polybar, just using nerd fonts can lead to some issues:
|
||||||
|
|
||||||
|
* Cut-off Characters
|
||||||
|
* Overlapping
|
||||||
|
* No Spacing
|
||||||
|
|
||||||
|
These look something like this:
|
||||||
|
|
||||||
|
.. image:: /_static/nerd-fonts/bad.png
|
||||||
|
:alt: Showcase of the three issues listed above.
|
||||||
|
|
||||||
|
This behavior is intrinsic to Nerd Fonts and is described in more detail `here
|
||||||
|
<https://github.com/ryanoasis/nerd-fonts/issues/442#issuecomment-1263358904>`_.
|
||||||
|
Also see :issue:`991` for more information.
|
||||||
|
|
||||||
|
**To resolve these issues, we recommend using Nerd Fonts like this:**
|
||||||
|
|
||||||
|
The monospaced variants of the different Nerd Fonts (all characters have the
|
||||||
|
same width) don't have this issue.
|
||||||
|
However, then you often have the problem that the icons are too small and that
|
||||||
|
their size cannot be set independently of the text.
|
||||||
|
|
||||||
|
Due to that, we recommend using ``Symbols Nerd Font Mono`` (available for
|
||||||
|
`download <https://github.com/ryanoasis/nerd-fonts/releases/>`_ as
|
||||||
|
``NerdFontsSymbolsOnly.zip``).
|
||||||
|
This font only contains the nerd font icons and no text.
|
||||||
|
For the text, simply use any non-Nerd Font:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
font-0 = "Liberation Mono:size=20"
|
||||||
|
font-1 = "Symbols Nerd Font Mono:size=26"
|
||||||
|
|
||||||
|
Now the icon sizes can be adjusted separately to get the best experience.
|
||||||
|
This solves all three problems shown above:
|
||||||
|
|
||||||
|
.. image:: /_static/nerd-fonts/good.png
|
||||||
|
:alt: The same config as in the previous screenshot but using ``Symbols Nerd
|
||||||
|
Font Mono`` for the font icons
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
In the overlap example, there is no space between the icon and text, that's
|
||||||
|
why they're so close together.
|
13
doc/user/modules/defs.rst
Normal file
13
doc/user/modules/defs.rst
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.. highlight:: ini
|
||||||
|
|
||||||
|
..
|
||||||
|
Substitutions for quickly referencing different config value types
|
||||||
|
|
||||||
|
.. |type-format| replace:: `format <type-format_>`_
|
||||||
|
.. |type-extent| replace:: `extent <type-extent_>`_
|
||||||
|
.. |type-pwo| replace:: `percentage with offset <type-pwo_>`_
|
||||||
|
.. |type-color| replace:: color
|
||||||
|
|
||||||
|
.. _type-format: https://github.com/polybar/polybar/wiki/Formatting#formats
|
||||||
|
.. _type-extent: https://github.com/polybar/polybar/wiki/Formatting#extent
|
||||||
|
.. _type-pwo: https://github.com/polybar/polybar/wiki/Formatting#percentage-with-offset
|
31
doc/user/modules/index.rst
Normal file
31
doc/user/modules/index.rst
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Modules
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
System Tray <tray>
|
||||||
|
|
||||||
|
Alsa <https://github.com/polybar/polybar/wiki/Module:-alsa>
|
||||||
|
Backlight <https://github.com/polybar/polybar/wiki/Module:-backlight>
|
||||||
|
Battery <https://github.com/polybar/polybar/wiki/Module:-battery>
|
||||||
|
bspwm <https://github.com/polybar/polybar/wiki/Module:-bspwm>
|
||||||
|
CPU <https://github.com/polybar/polybar/wiki/Module:-cpu>
|
||||||
|
Date and Time <https://github.com/polybar/polybar/wiki/Module:-date>
|
||||||
|
Filesystem <https://github.com/polybar/polybar/wiki/Module:-filesystem>
|
||||||
|
GitHub <https://github.com/polybar/polybar/wiki/Module:-github>
|
||||||
|
i3 <https://github.com/polybar/polybar/wiki/Module:-i3>
|
||||||
|
Inter-process-messaging (IPC) <https://github.com/polybar/polybar/wiki/Module:-ipc>
|
||||||
|
Memory <https://github.com/polybar/polybar/wiki/Module:-memory>
|
||||||
|
Menu <https://github.com/polybar/polybar/wiki/Module:-menu>
|
||||||
|
MPD <https://github.com/polybar/polybar/wiki/Module:-mpd>
|
||||||
|
Network <https://github.com/polybar/polybar/wiki/Module:-network>
|
||||||
|
PulseAudio <https://github.com/polybar/polybar/wiki/Module:-pulseaudio>
|
||||||
|
Script <https://github.com/polybar/polybar/wiki/Module:-script>
|
||||||
|
Temperature <https://github.com/polybar/polybar/wiki/Module:-temperature>
|
||||||
|
Text <https://github.com/polybar/polybar/wiki/Module:-text>
|
||||||
|
XBacklight <https://github.com/polybar/polybar/wiki/Module:-xbacklight>
|
||||||
|
XKeyboard <https://github.com/polybar/polybar/wiki/Module:-xkeyboard>
|
||||||
|
XWindow <https://github.com/polybar/polybar/wiki/Module:-xwindow>
|
||||||
|
XWorkspaces <https://github.com/polybar/polybar/wiki/Module:-xworkspaces>
|
||||||
|
User contributed modules <https://github.com/polybar/polybar/wiki/User-contributed-modules>
|
116
doc/user/modules/tray.rst
Normal file
116
doc/user/modules/tray.rst
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
.. include:: defs.rst
|
||||||
|
|
||||||
|
Tray Module
|
||||||
|
===========
|
||||||
|
.. poly-setting:: type = internal/tray
|
||||||
|
|
||||||
|
.. versionadded:: 3.7.0
|
||||||
|
|
||||||
|
The tray module displays system tray application icons on the bar.
|
||||||
|
|
||||||
|
This module is a bit different from the other modules.
|
||||||
|
The tray icons (also called clients) are individual windows managed by their
|
||||||
|
respective application (e.g. the Dropbox tray icon is created and managed by
|
||||||
|
the Dropbox application).
|
||||||
|
Polybar is only responsible for embedding the windows in the bar and
|
||||||
|
positioning them correctly.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Only a single instance of this module can be active at the same time (across
|
||||||
|
all polybar instances).
|
||||||
|
|
||||||
|
The way the `system tray protocol <systray-spec_>`_ works, at most one tray
|
||||||
|
can exist at any time.
|
||||||
|
Polybar will produce a warning if additional tray instances are created.
|
||||||
|
|
||||||
|
For transparent background colors, the tray will use pseudo-transparency, true
|
||||||
|
transparency is not possible for the tray icons.
|
||||||
|
|
||||||
|
Formats
|
||||||
|
-------
|
||||||
|
|
||||||
|
The module only has a single format:
|
||||||
|
|
||||||
|
.. poly-setting:: format
|
||||||
|
|
||||||
|
:type: |type-format|
|
||||||
|
:tags: ``<tray>``: Shows tray icons
|
||||||
|
:default: ``<tray>``
|
||||||
|
|
||||||
|
Settings
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. poly-setting:: tray-spacing
|
||||||
|
|
||||||
|
Space added between tray icons
|
||||||
|
|
||||||
|
:type: |type-extent|, non-negative
|
||||||
|
:default: ``0px``
|
||||||
|
|
||||||
|
.. poly-setting:: tray-padding
|
||||||
|
|
||||||
|
Space added before and after each tray icon
|
||||||
|
|
||||||
|
:type: |type-extent|, non-negative
|
||||||
|
:default: ``0px``
|
||||||
|
|
||||||
|
.. poly-setting:: tray-size
|
||||||
|
|
||||||
|
Size of individual tray icons
|
||||||
|
|
||||||
|
:type: |type-pwo|, relative to bar height, non-negative
|
||||||
|
:default: 66%
|
||||||
|
|
||||||
|
.. poly-setting:: tray-background
|
||||||
|
|
||||||
|
Background color of tray icons
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
This only affects the color of the individual icons and not the space in
|
||||||
|
between, changing this setting to anything else than the bar background
|
||||||
|
will likely not look good unless the background color is also changed for
|
||||||
|
the rest of the tray module (e.g. with ``format-background``).
|
||||||
|
|
||||||
|
:type: |type-color|
|
||||||
|
:default: ``${root.background}``
|
||||||
|
|
||||||
|
.. poly-setting:: tray-foreground
|
||||||
|
|
||||||
|
Tray icon color
|
||||||
|
|
||||||
|
This serves as a hint to the tray icon application for which color to use for
|
||||||
|
the icon.
|
||||||
|
|
||||||
|
This is not guaranteed to have any effect (likely only in GTK3) because it
|
||||||
|
targets a non-standard part of the `system tray protocol <systray-spec_>`_ by
|
||||||
|
setting the ``_NET_SYSTEM_TRAY_COLORS`` atom on the tray window.
|
||||||
|
|
||||||
|
:type: |type-color|
|
||||||
|
:default: ``${tray-foreground}``
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
[module/tray]
|
||||||
|
type = internal/tray
|
||||||
|
|
||||||
|
format-margin = 8px
|
||||||
|
tray-spacing = 8px
|
||||||
|
|
||||||
|
Migrating From Legacy Tray Implementation
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
.. include:: /migration/3.7/tray.rst
|
||||||
|
|
||||||
|
References
|
||||||
|
----------
|
||||||
|
|
||||||
|
* `System Tray Protocol Specification <systray-spec_>`_
|
||||||
|
* `XEmbed Protocol Specification <xembed_>`_
|
||||||
|
|
||||||
|
.. _systray-spec: https://specifications.freedesktop.org/systemtray-spec/systemtray-spec-latest.html
|
||||||
|
.. _xembed: https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
|
@ -1,46 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USE_ALSALIB_H
|
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
#else
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#ifndef __FreeBSD__
|
|
||||||
#include <endian.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#define __inline__ inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <alsa/asoundef.h>
|
|
||||||
#include <alsa/version.h>
|
|
||||||
#include <alsa/global.h>
|
|
||||||
#include <alsa/input.h>
|
|
||||||
#include <alsa/output.h>
|
|
||||||
#include <alsa/error.h>
|
|
||||||
#include <alsa/conf.h>
|
|
||||||
#include <alsa/pcm.h>
|
|
||||||
#include <alsa/rawmidi.h>
|
|
||||||
#include <alsa/timer.h>
|
|
||||||
#include <alsa/hwdep.h>
|
|
||||||
#include <alsa/control.h>
|
|
||||||
#include <alsa/mixer.h>
|
|
||||||
#include <alsa/seq_event.h>
|
|
||||||
#include <alsa/seq.h>
|
|
||||||
#include <alsa/seqmid.h>
|
|
||||||
#include <alsa/seq_midi_event.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
@ -21,8 +21,8 @@ class script_runner {
|
|||||||
using on_update = std::function<void(const data&)>;
|
using on_update = std::function<void(const data&)>;
|
||||||
using interval = std::chrono::duration<double>;
|
using interval = std::chrono::duration<double>;
|
||||||
|
|
||||||
script_runner(on_update on_update, const string& exec, const string& exec_if, bool tail, interval interval,
|
script_runner(on_update on_update, const string& exec, const string& exec_if, bool tail, interval interval_success,
|
||||||
const vector<pair<string, string>>& env);
|
interval interval_fail, const vector<pair<string, string>>& env);
|
||||||
|
|
||||||
bool check_condition() const;
|
bool check_condition() const;
|
||||||
interval process();
|
interval process();
|
||||||
@ -48,7 +48,8 @@ class script_runner {
|
|||||||
const string m_exec;
|
const string m_exec;
|
||||||
const string m_exec_if;
|
const string m_exec_if;
|
||||||
const bool m_tail;
|
const bool m_tail;
|
||||||
const interval m_interval;
|
const interval m_interval_success;
|
||||||
|
const interval m_interval_fail;
|
||||||
const vector<pair<string, string>> m_env;
|
const vector<pair<string, string>> m_env;
|
||||||
|
|
||||||
data m_data;
|
data m_data;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <iomanip>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
#include "cairo/font.hpp"
|
#include "cairo/font.hpp"
|
||||||
@ -163,9 +164,21 @@ namespace cairo {
|
|||||||
std::iter_swap(fns.begin(), fns.begin() + t.font - 1);
|
std::iter_swap(fns.begin(), fns.begin() + t.font - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
string utf8 = string(t.contents);
|
string utf8 = t.contents;
|
||||||
utils::unicode_charlist chars;
|
string_util::unicode_charlist chars;
|
||||||
utils::utf8_to_ucs4((const unsigned char*)utf8.c_str(), chars);
|
bool valid = string_util::utf8_to_ucs4(utf8, chars);
|
||||||
|
|
||||||
|
// The conversion already removed any invalid chunks. We should probably log a warning though.
|
||||||
|
if (!valid) {
|
||||||
|
sstream hex;
|
||||||
|
hex << std::hex << std::setw(2) << std::setfill('0');
|
||||||
|
|
||||||
|
for(const char& c: utf8) {
|
||||||
|
hex << (static_cast<int>(c) & 0xff) << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.warn("Dropping invalid parts of UTF8 text '%s' %s", utf8, hex.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
while (!chars.empty()) {
|
while (!chars.empty()) {
|
||||||
auto remaining = chars.size();
|
auto remaining = chars.size();
|
||||||
@ -196,6 +209,12 @@ namespace cairo {
|
|||||||
cairo_text_extents_t extents;
|
cairo_text_extents_t extents;
|
||||||
f->textwidth(subset, &extents);
|
f->textwidth(subset, &extents);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure we don't advance partial pixels, this can cause problems
|
||||||
|
* later when cairo renders background colors over half-pixels.
|
||||||
|
*/
|
||||||
|
extents.x_advance = std::ceil(extents.x_advance);
|
||||||
|
|
||||||
// Draw the background
|
// Draw the background
|
||||||
if (t.bg_rect.h != 0.0) {
|
if (t.bg_rect.h != 0.0) {
|
||||||
save();
|
save();
|
||||||
@ -228,9 +247,9 @@ namespace cairo {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
char unicode[6]{'\0'};
|
std::array<char, 5> unicode{};
|
||||||
utils::ucs4_to_utf8(unicode, chars.begin()->codepoint);
|
string_util::ucs4_to_utf8(unicode, chars.begin()->codepoint);
|
||||||
m_log.warn("Dropping unmatched character %s (U+%04x) in '%s'", unicode, chars.begin()->codepoint, t.contents);
|
m_log.warn("Dropping unmatched character '%s' (U+%04x) in '%s'", unicode.data(), chars.begin()->codepoint, t.contents);
|
||||||
utf8.erase(chars.begin()->offset, chars.begin()->length);
|
utf8.erase(chars.begin()->offset, chars.begin()->length);
|
||||||
for (auto&& c : chars) {
|
for (auto&& c : chars) {
|
||||||
c.offset -= chars.begin()->length;
|
c.offset -= chars.begin()->length;
|
||||||
|
@ -15,327 +15,328 @@
|
|||||||
POLYBAR_NS
|
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
|
||||||
|
*/
|
||||||
|
class font {
|
||||||
|
public:
|
||||||
|
explicit font(cairo_t* cairo, double offset) : m_cairo(cairo), m_offset(offset) {}
|
||||||
|
virtual ~font(){};
|
||||||
|
|
||||||
|
virtual string name() const = 0;
|
||||||
|
virtual string file() const = 0;
|
||||||
|
virtual double offset() const = 0;
|
||||||
|
virtual double size(double dpi) const = 0;
|
||||||
|
|
||||||
|
virtual cairo_font_extents_t extents() = 0;
|
||||||
|
|
||||||
|
virtual void use() {
|
||||||
|
cairo_set_font_face(m_cairo, cairo_font_face_reference(m_font_face));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t match(string_util::unicode_character& character) = 0;
|
||||||
|
virtual size_t match(string_util::unicode_charlist& charlist) = 0;
|
||||||
|
virtual size_t render(const string& text, double x = 0.0, double y = 0.0) = 0;
|
||||||
|
virtual void textwidth(const string& text, cairo_text_extents_t* extents) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cairo_t* m_cairo;
|
||||||
|
cairo_font_face_t* m_font_face{nullptr};
|
||||||
|
cairo_font_extents_t m_extents{};
|
||||||
|
double m_offset{0.0};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Font based on fontconfig/freetype
|
||||||
|
*/
|
||||||
|
class font_fc : public font {
|
||||||
|
public:
|
||||||
|
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 ctm;
|
||||||
|
cairo_matrix_init_scale(&fm, size(dpi_x), size(dpi_y));
|
||||||
|
cairo_get_matrix(m_cairo, &ctm);
|
||||||
|
|
||||||
|
auto fontface = cairo_ft_font_face_create_for_pattern(m_pattern);
|
||||||
|
auto opts = cairo_font_options_create();
|
||||||
|
m_scaled = cairo_scaled_font_create(fontface, &fm, &ctm, opts);
|
||||||
|
cairo_font_options_destroy(opts);
|
||||||
|
cairo_font_face_destroy(fontface);
|
||||||
|
|
||||||
|
auto status = cairo_scaled_font_status(m_scaled);
|
||||||
|
if (status != CAIRO_STATUS_SUCCESS) {
|
||||||
|
throw application_error(sstream() << "cairo_scaled_font_create(): " << cairo_status_to_string(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lock = make_unique<utils::ft_face_lock>(m_scaled);
|
||||||
|
auto face = static_cast<FT_Face>(*lock);
|
||||||
|
|
||||||
|
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) == FT_Err_Ok) {
|
||||||
|
return;
|
||||||
|
} else if (FT_Select_Charmap(face, FT_ENCODING_BIG5) == FT_Err_Ok) {
|
||||||
|
return;
|
||||||
|
} else if (FT_Select_Charmap(face, FT_ENCODING_SJIS) == FT_Err_Ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
~font_fc() override {
|
||||||
|
if (m_scaled != nullptr) {
|
||||||
|
cairo_scaled_font_destroy(m_scaled);
|
||||||
|
}
|
||||||
|
if (m_pattern != nullptr) {
|
||||||
|
FcPatternDestroy(m_pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_font_extents_t extents() override {
|
||||||
|
cairo_scaled_font_extents(m_scaled, &m_extents);
|
||||||
|
return m_extents;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name() const override {
|
||||||
|
return property("family");
|
||||||
|
}
|
||||||
|
|
||||||
|
string file() const override {
|
||||||
|
return property("file");
|
||||||
|
}
|
||||||
|
|
||||||
|
double offset() const override {
|
||||||
|
return m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Abstract font face
|
* Calculates the font size in pixels for the given dpi
|
||||||
|
*
|
||||||
|
* We use the two font properties size and pixelsize. size is in points and
|
||||||
|
* needs to be scaled with the given dpi. pixelsize is not scaled.
|
||||||
|
*
|
||||||
|
* If both size properties are 0, we fall back to a default value of 10
|
||||||
|
* points for scalable fonts or 10 pixel for non-scalable ones. This should
|
||||||
|
* only happen if both properties are purposefully set to 0
|
||||||
|
*
|
||||||
|
* For scalable fonts we try to use the size property scaled according to
|
||||||
|
* the dpi.
|
||||||
|
* For non-scalable fonts we try to use the pixelsize property as-is
|
||||||
*/
|
*/
|
||||||
class font {
|
double size(double dpi) const override {
|
||||||
public:
|
bool scalable;
|
||||||
explicit font(cairo_t* cairo, double offset) : m_cairo(cairo), m_offset(offset) {}
|
double fc_pixelsize = 0, fc_size = 0;
|
||||||
virtual ~font(){};
|
|
||||||
|
|
||||||
virtual string name() const = 0;
|
property(FC_SCALABLE, &scalable);
|
||||||
virtual string file() const = 0;
|
|
||||||
virtual double offset() const = 0;
|
|
||||||
virtual double size(double dpi) const = 0;
|
|
||||||
|
|
||||||
virtual cairo_font_extents_t extents() = 0;
|
// Size in points
|
||||||
|
property(FC_SIZE, &fc_size);
|
||||||
|
|
||||||
virtual void use() {
|
// Size in pixels
|
||||||
cairo_set_font_face(m_cairo, cairo_font_face_reference(m_font_face));
|
property(FC_PIXEL_SIZE, &fc_pixelsize);
|
||||||
}
|
|
||||||
|
|
||||||
virtual size_t match(utils::unicode_character& character) = 0;
|
// Fall back to a default value if the size is 0
|
||||||
virtual size_t match(utils::unicode_charlist& charlist) = 0;
|
double pixelsize = fc_pixelsize == 0 ? 10 : fc_pixelsize;
|
||||||
virtual size_t render(const string& text, double x = 0.0, double y = 0.0) = 0;
|
double size = fc_size == 0 ? 10 : fc_size;
|
||||||
virtual void textwidth(const string& text, cairo_text_extents_t* extents) = 0;
|
|
||||||
|
|
||||||
protected:
|
// Font size in pixels if we use the pixelsize property
|
||||||
cairo_t* m_cairo;
|
int px_pixelsize = pixelsize + 0.5;
|
||||||
cairo_font_face_t* m_font_face{nullptr};
|
|
||||||
cairo_font_extents_t m_extents{};
|
|
||||||
double m_offset{0.0};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* @brief Font based on fontconfig/freetype
|
* Font size in pixels if we use the size property. Since the size
|
||||||
*/
|
* specifies the font size in points, this is converted to pixels
|
||||||
class font_fc : public font {
|
* according to the dpi given.
|
||||||
public:
|
* One point is 1/72 inches, thus this gives us the number of 'dots'
|
||||||
explicit font_fc(cairo_t* cairo, FcPattern* pattern, double offset, double dpi_x, double dpi_y)
|
* (or pixels) for this font
|
||||||
: font(cairo, offset), m_pattern(pattern) {
|
|
||||||
cairo_matrix_t fm;
|
|
||||||
cairo_matrix_t ctm;
|
|
||||||
cairo_matrix_init_scale(&fm, size(dpi_x), size(dpi_y));
|
|
||||||
cairo_get_matrix(m_cairo, &ctm);
|
|
||||||
|
|
||||||
auto fontface = cairo_ft_font_face_create_for_pattern(m_pattern);
|
|
||||||
auto opts = cairo_font_options_create();
|
|
||||||
m_scaled = cairo_scaled_font_create(fontface, &fm, &ctm, opts);
|
|
||||||
cairo_font_options_destroy(opts);
|
|
||||||
cairo_font_face_destroy(fontface);
|
|
||||||
|
|
||||||
auto status = cairo_scaled_font_status(m_scaled);
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
|
||||||
throw application_error(sstream() << "cairo_scaled_font_create(): " << cairo_status_to_string(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = make_unique<utils::ft_face_lock>(m_scaled);
|
|
||||||
auto face = static_cast<FT_Face>(*lock);
|
|
||||||
|
|
||||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) == FT_Err_Ok) {
|
|
||||||
return;
|
|
||||||
} else if (FT_Select_Charmap(face, FT_ENCODING_BIG5) == FT_Err_Ok) {
|
|
||||||
return;
|
|
||||||
} else if (FT_Select_Charmap(face, FT_ENCODING_SJIS) == FT_Err_Ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
~font_fc() override {
|
|
||||||
if (m_scaled != nullptr) {
|
|
||||||
cairo_scaled_font_destroy(m_scaled);
|
|
||||||
}
|
|
||||||
if (m_pattern != nullptr) {
|
|
||||||
FcPatternDestroy(m_pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_font_extents_t extents() override {
|
|
||||||
cairo_scaled_font_extents(m_scaled, &m_extents);
|
|
||||||
return m_extents;
|
|
||||||
}
|
|
||||||
|
|
||||||
string name() const override {
|
|
||||||
return property("family");
|
|
||||||
}
|
|
||||||
|
|
||||||
string file() const override {
|
|
||||||
return property("file");
|
|
||||||
}
|
|
||||||
|
|
||||||
double offset() const override {
|
|
||||||
return m_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the font size in pixels for the given dpi
|
|
||||||
*
|
|
||||||
* We use the two font properties size and pixelsize. size is in points and
|
|
||||||
* needs to be scaled with the given dpi. pixelsize is not scaled.
|
|
||||||
*
|
|
||||||
* If both size properties are 0, we fall back to a default value of 10
|
|
||||||
* points for scalable fonts or 10 pixel for non-scalable ones. This should
|
|
||||||
* only happen if both properties are purposefully set to 0
|
|
||||||
*
|
|
||||||
* For scalable fonts we try to use the size property scaled according to
|
|
||||||
* the dpi.
|
|
||||||
* For non-scalable fonts we try to use the pixelsize property as-is
|
|
||||||
*/
|
*/
|
||||||
double size(double dpi) const override {
|
int px_size = size / 72.0 * dpi + 0.5;
|
||||||
bool scalable;
|
|
||||||
double fc_pixelsize = 0, fc_size = 0;
|
|
||||||
|
|
||||||
property(FC_SCALABLE, &scalable);
|
if (fc_size == 0 && fc_pixelsize == 0) {
|
||||||
|
return scalable ? px_size : px_pixelsize;
|
||||||
// Size in points
|
}
|
||||||
property(FC_SIZE, &fc_size);
|
|
||||||
|
|
||||||
// Size in pixels
|
|
||||||
property(FC_PIXEL_SIZE, &fc_pixelsize);
|
|
||||||
|
|
||||||
// Fall back to a default value if the size is 0
|
|
||||||
double pixelsize = fc_pixelsize == 0 ? 10 : fc_pixelsize;
|
|
||||||
double size = fc_size == 0 ? 10 : fc_size;
|
|
||||||
|
|
||||||
// Font size in pixels if we use the pixelsize property
|
|
||||||
int px_pixelsize = pixelsize + 0.5;
|
|
||||||
|
|
||||||
|
if (scalable) {
|
||||||
/*
|
/*
|
||||||
* Font size in pixels if we use the size property. Since the size
|
* Use the point size if it's not 0. The pixelsize is only used if the
|
||||||
* specifies the font size in points, this is converted to pixels
|
* size property is 0 and pixelsize is not
|
||||||
* according to the dpi given.
|
|
||||||
* One point is 1/72 inches, thus this gives us the number of 'dots'
|
|
||||||
* (or pixels) for this font
|
|
||||||
*/
|
*/
|
||||||
int px_size = size / 72.0 * dpi + 0.5;
|
if (fc_size != 0) {
|
||||||
|
return px_size;
|
||||||
if (fc_size == 0 && fc_pixelsize == 0) {
|
|
||||||
return scalable ? px_size : px_pixelsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scalable) {
|
|
||||||
/*
|
|
||||||
* Use the point size if it's not 0. The pixelsize is only used if the
|
|
||||||
* size property is 0 and pixelsize is not
|
|
||||||
*/
|
|
||||||
if (fc_size != 0) {
|
|
||||||
return px_size;
|
|
||||||
} else {
|
|
||||||
return px_pixelsize;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
return px_pixelsize;
|
||||||
* Non-scalable fonts do it the other way around, here the size
|
}
|
||||||
* property is only used if pixelsize is 0 and size is not
|
} else {
|
||||||
*/
|
/*
|
||||||
if (fc_pixelsize != 0) {
|
* Non-scalable fonts do it the other way around, here the size
|
||||||
return px_pixelsize;
|
* property is only used if pixelsize is 0 and size is not
|
||||||
} else {
|
*/
|
||||||
return px_size;
|
if (fc_pixelsize != 0) {
|
||||||
}
|
return px_pixelsize;
|
||||||
|
} else {
|
||||||
|
return px_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void use() override {
|
||||||
|
cairo_set_scaled_font(m_cairo, m_scaled);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t match(string_util::unicode_character& character) override {
|
||||||
|
auto lock = make_unique<utils::ft_face_lock>(m_scaled);
|
||||||
|
auto face = static_cast<FT_Face>(*lock);
|
||||||
|
return FT_Get_Char_Index(face, character.codepoint) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t match(string_util::unicode_charlist& charlist) override {
|
||||||
|
auto lock = make_unique<utils::ft_face_lock>(m_scaled);
|
||||||
|
auto face = static_cast<FT_Face>(*lock);
|
||||||
|
size_t available_chars = 0;
|
||||||
|
for (auto&& c : charlist) {
|
||||||
|
if (FT_Get_Char_Index(face, c.codepoint)) {
|
||||||
|
available_chars++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void use() override {
|
return available_chars;
|
||||||
cairo_set_scaled_font(m_cairo, m_scaled);
|
}
|
||||||
|
|
||||||
|
size_t render(const string& text, double x = 0.0, double y = 0.0) override {
|
||||||
|
cairo_glyph_t* glyphs{nullptr};
|
||||||
|
cairo_text_cluster_t* clusters{nullptr};
|
||||||
|
cairo_text_cluster_flags_t cf{};
|
||||||
|
int nglyphs = 0;
|
||||||
|
int nclusters = 0;
|
||||||
|
|
||||||
|
string utf8 = string(text);
|
||||||
|
auto status = cairo_scaled_font_text_to_glyphs(
|
||||||
|
m_scaled, x, y, utf8.c_str(), utf8.size(), &glyphs, &nglyphs, &clusters, &nclusters, &cf);
|
||||||
|
|
||||||
|
if (status != CAIRO_STATUS_SUCCESS) {
|
||||||
|
throw application_error(sstream() << "cairo_scaled_font_text_to_glyphs() " << cairo_status_to_string(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t match(utils::unicode_character& character) override {
|
size_t bytes = 0;
|
||||||
auto lock = make_unique<utils::ft_face_lock>(m_scaled);
|
for (int g = 0; g < nglyphs; g++) {
|
||||||
auto face = static_cast<FT_Face>(*lock);
|
if (glyphs[g].index) {
|
||||||
return FT_Get_Char_Index(face, character.codepoint) ? 1 : 0;
|
bytes += clusters[g].num_bytes;
|
||||||
}
|
} else {
|
||||||
|
break;
|
||||||
size_t match(utils::unicode_charlist& charlist) override {
|
|
||||||
auto lock = make_unique<utils::ft_face_lock>(m_scaled);
|
|
||||||
auto face = static_cast<FT_Face>(*lock);
|
|
||||||
size_t available_chars = 0;
|
|
||||||
for (auto&& c : charlist) {
|
|
||||||
if (FT_Get_Char_Index(face, c.codepoint)) {
|
|
||||||
available_chars++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return available_chars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t render(const string& text, double x = 0.0, double y = 0.0) override {
|
if (bytes && bytes < text.size()) {
|
||||||
cairo_glyph_t* glyphs{nullptr};
|
cairo_glyph_free(glyphs);
|
||||||
cairo_text_cluster_t* clusters{nullptr};
|
cairo_text_cluster_free(clusters);
|
||||||
cairo_text_cluster_flags_t cf{};
|
|
||||||
int nglyphs = 0, nclusters = 0;
|
|
||||||
|
|
||||||
string utf8 = string(text);
|
utf8 = text.substr(0, bytes);
|
||||||
auto status = cairo_scaled_font_text_to_glyphs(
|
auto status = cairo_scaled_font_text_to_glyphs(
|
||||||
m_scaled, x, y, utf8.c_str(), utf8.size(), &glyphs, &nglyphs, &clusters, &nclusters, &cf);
|
m_scaled, x, y, utf8.c_str(), utf8.size(), &glyphs, &nglyphs, &clusters, &nclusters, &cf);
|
||||||
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
if (status != CAIRO_STATUS_SUCCESS) {
|
||||||
throw application_error(sstream() << "cairo_scaled_font_text_to_glyphs()" << cairo_status_to_string(status));
|
throw application_error(sstream() << "cairo_scaled_font_text_to_glyphs() " << cairo_status_to_string(status));
|
||||||
}
|
|
||||||
|
|
||||||
size_t bytes = 0;
|
|
||||||
for (int g = 0; g < nglyphs; g++) {
|
|
||||||
if (glyphs[g].index) {
|
|
||||||
bytes += clusters[g].num_bytes;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes && bytes < text.size()) {
|
|
||||||
cairo_glyph_free(glyphs);
|
|
||||||
cairo_text_cluster_free(clusters);
|
|
||||||
|
|
||||||
utf8 = text.substr(0, bytes);
|
|
||||||
auto status = cairo_scaled_font_text_to_glyphs(
|
|
||||||
m_scaled, x, y, utf8.c_str(), utf8.size(), &glyphs, &nglyphs, &clusters, &nclusters, &cf);
|
|
||||||
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS) {
|
|
||||||
throw application_error(sstream() << "cairo_scaled_font_text_to_glyphs()" << cairo_status_to_string(status));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes) {
|
|
||||||
// auto lock = make_unique<utils::device_lock>(cairo_surface_get_device(cairo_get_target(m_cairo)));
|
|
||||||
// if (lock.get()) {
|
|
||||||
// cairo_glyph_path(m_cairo, glyphs, nglyphs);
|
|
||||||
// }
|
|
||||||
|
|
||||||
cairo_text_extents_t extents{};
|
|
||||||
cairo_scaled_font_glyph_extents(m_scaled, glyphs, nglyphs, &extents);
|
|
||||||
cairo_show_text_glyphs(m_cairo, utf8.c_str(), utf8.size(), glyphs, nglyphs, clusters, nclusters, cf);
|
|
||||||
cairo_fill(m_cairo);
|
|
||||||
cairo_move_to(m_cairo, x + extents.x_advance, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_glyph_free(glyphs);
|
|
||||||
cairo_text_cluster_free(clusters);
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void textwidth(const string& text, cairo_text_extents_t* extents) override {
|
|
||||||
cairo_scaled_font_text_extents(m_scaled, text.c_str(), extents);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
string property(string&& property) const {
|
|
||||||
FcChar8* file;
|
|
||||||
if (FcPatternGetString(m_pattern, property.c_str(), 0, &file) == FcResultMatch) {
|
|
||||||
return string(reinterpret_cast<char*>(file));
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void property(string&& property, bool* dst) const {
|
if (bytes) {
|
||||||
FcBool b;
|
// auto lock = make_unique<utils::device_lock>(cairo_surface_get_device(cairo_get_target(m_cairo)));
|
||||||
FcPatternGetBool(m_pattern, property.c_str(), 0, &b);
|
// if (lock.get()) {
|
||||||
*dst = b;
|
// cairo_glyph_path(m_cairo, glyphs, nglyphs);
|
||||||
|
// }
|
||||||
|
|
||||||
|
cairo_text_extents_t extents{};
|
||||||
|
cairo_scaled_font_glyph_extents(m_scaled, glyphs, nglyphs, &extents);
|
||||||
|
cairo_show_text_glyphs(m_cairo, utf8.c_str(), utf8.size(), glyphs, nglyphs, clusters, nclusters, cf);
|
||||||
|
cairo_fill(m_cairo);
|
||||||
|
cairo_move_to(m_cairo, x + extents.x_advance, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void property(string&& property, double* dst) const {
|
cairo_glyph_free(glyphs);
|
||||||
FcPatternGetDouble(m_pattern, property.c_str(), 0, dst);
|
cairo_text_cluster_free(clusters);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void textwidth(const string& text, cairo_text_extents_t* extents) override {
|
||||||
|
cairo_scaled_font_text_extents(m_scaled, text.c_str(), extents);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string property(string&& property) const {
|
||||||
|
FcChar8* file;
|
||||||
|
if (FcPatternGetString(m_pattern, property.c_str(), 0, &file) == FcResultMatch) {
|
||||||
|
return string(reinterpret_cast<char*>(file));
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void property(string&& property, int* dst) const {
|
void property(string&& property, bool* dst) const {
|
||||||
FcPatternGetInteger(m_pattern, property.c_str(), 0, dst);
|
FcBool b;
|
||||||
}
|
FcPatternGetBool(m_pattern, property.c_str(), 0, &b);
|
||||||
|
*dst = b;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
void property(string&& property, double* dst) const {
|
||||||
cairo_scaled_font_t* m_scaled{nullptr};
|
FcPatternGetDouble(m_pattern, property.c_str(), 0, dst);
|
||||||
FcPattern* m_pattern{nullptr};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
void property(string&& property, int* dst) const {
|
||||||
* Match and create font from given fontconfig pattern
|
FcPatternGetInteger(m_pattern, property.c_str(), 0, dst);
|
||||||
*/
|
}
|
||||||
inline decltype(auto) make_font(cairo_t* cairo, string&& fontname, double offset, double dpi_x, double dpi_y) {
|
|
||||||
static bool fc_init{false};
|
|
||||||
if (!fc_init && !(fc_init = FcInit())) {
|
|
||||||
throw application_error("Could not load fontconfig");
|
|
||||||
} else if (FT_Init_FreeType(&g_ftlib) != FT_Err_Ok) {
|
|
||||||
throw application_error("Could not load FreeType");
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto fc_cleanup = scope_util::make_exit_handler([] {
|
private:
|
||||||
FT_Done_FreeType(g_ftlib);
|
cairo_scaled_font_t* m_scaled{nullptr};
|
||||||
FcFini();
|
FcPattern* m_pattern{nullptr};
|
||||||
});
|
};
|
||||||
|
|
||||||
auto pattern = FcNameParse((FcChar8*)fontname.c_str());
|
/**
|
||||||
|
* Match and create font from given fontconfig pattern
|
||||||
|
*/
|
||||||
|
inline decltype(auto) make_font(cairo_t* cairo, string&& fontname, double offset, double dpi_x, double dpi_y) {
|
||||||
|
static bool fc_init{false};
|
||||||
|
if (!fc_init && !(fc_init = FcInit())) {
|
||||||
|
throw application_error("Could not load fontconfig");
|
||||||
|
} else if (FT_Init_FreeType(&g_ftlib) != FT_Err_Ok) {
|
||||||
|
throw application_error("Could not load FreeType");
|
||||||
|
}
|
||||||
|
|
||||||
if (!pattern) {
|
static scope_util::on_exit fc_cleanup([] {
|
||||||
logger::make().err("Could not parse font \"%s\"", fontname);
|
FT_Done_FreeType(g_ftlib);
|
||||||
throw application_error("Could not parse font \"" + fontname + "\"");
|
FcFini();
|
||||||
}
|
});
|
||||||
|
|
||||||
FcDefaultSubstitute(pattern);
|
auto pattern = FcNameParse((FcChar8*)fontname.c_str());
|
||||||
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
|
||||||
|
|
||||||
FcResult result;
|
if (!pattern) {
|
||||||
FcPattern* match = FcFontMatch(nullptr, pattern, &result);
|
logger::make().err("Could not parse font \"%s\"", fontname);
|
||||||
FcPatternDestroy(pattern);
|
throw application_error("Could not parse font \"" + fontname + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
if (match == nullptr) {
|
FcDefaultSubstitute(pattern);
|
||||||
throw application_error("Could not load font \"" + fontname + "\"");
|
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
||||||
}
|
|
||||||
|
FcResult result;
|
||||||
|
FcPattern* match = FcFontMatch(nullptr, pattern, &result);
|
||||||
|
FcPatternDestroy(pattern);
|
||||||
|
|
||||||
|
if (match == nullptr) {
|
||||||
|
throw application_error("Could not load font \"" + fontname + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FONTCONFIG
|
#ifdef DEBUG_FONTCONFIG
|
||||||
FcPatternPrint(match);
|
FcPatternPrint(match);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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
|
} // namespace cairo
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -1,70 +1,47 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cairo/cairo-ft.h>
|
#include <cairo/cairo-ft.h>
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
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:
|
||||||
explicit device_lock(cairo_device_t* device);
|
explicit device_lock(cairo_device_t* device);
|
||||||
~device_lock();
|
~device_lock();
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator cairo_device_t*() const;
|
operator cairo_device_t*() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cairo_device_t* m_device{nullptr};
|
cairo_device_t* m_device{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 {
|
||||||
public:
|
public:
|
||||||
explicit ft_face_lock(cairo_scaled_font_t* font);
|
explicit ft_face_lock(cairo_scaled_font_t* font);
|
||||||
~ft_face_lock();
|
~ft_face_lock();
|
||||||
operator FT_Face() const;
|
operator FT_Face() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cairo_scaled_font_t* m_font;
|
cairo_scaled_font_t* m_font;
|
||||||
FT_Face m_face;
|
FT_Face m_face;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unicode character containing converted codepoint
|
* @see <cairo/cairo.h>
|
||||||
* and details on where its position in the source string
|
*/
|
||||||
*/
|
cairo_operator_t str2operator(const string& mode, cairo_operator_t fallback);
|
||||||
struct unicode_character {
|
} // namespace utils
|
||||||
explicit unicode_character();
|
} // namespace cairo
|
||||||
unsigned long codepoint;
|
|
||||||
int offset;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
using unicode_charlist = std::list<unicode_character>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see <cairo/cairo.h>
|
|
||||||
*/
|
|
||||||
cairo_operator_t str2operator(const string& mode, cairo_operator_t fallback);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a UCS-4 codepoint from a utf-8 encoded string
|
|
||||||
*/
|
|
||||||
bool utf8_to_ucs4(const unsigned char* src, unicode_charlist& result_list);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert a UCS-4 codepoint to a utf-8 encoded string
|
|
||||||
*/
|
|
||||||
size_t ucs4_to_utf8(char* utf8, unsigned int ucs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
@ -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"
|
||||||
@ -22,10 +23,12 @@ class connection;
|
|||||||
class logger;
|
class logger;
|
||||||
class renderer;
|
class renderer;
|
||||||
class screen;
|
class screen;
|
||||||
|
namespace legacy_tray {
|
||||||
class tray_manager;
|
class tray_manager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace tags {
|
namespace tags {
|
||||||
class dispatch;
|
class dispatch;
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
@ -34,16 +37,15 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
public signal_receiver<SIGN_PRIORITY_BAR, signals::ui::dim_window> {
|
public signal_receiver<SIGN_PRIORITY_BAR, signals::ui::dim_window> {
|
||||||
public:
|
public:
|
||||||
using make_type = unique_ptr<bar>;
|
using make_type = unique_ptr<bar>;
|
||||||
static make_type make(eventloop::loop&, bool only_initialize_values = false);
|
static make_type make(eventloop::loop&, const config&, bool only_initialize_values = false);
|
||||||
|
|
||||||
explicit bar(connection&, signal_emitter&, const config&, const logger&, eventloop::loop&, 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<tags::action_context>&&,
|
unique_ptr<tags::dispatch>&&, unique_ptr<tags::action_context>&&, bool only_initialize_values);
|
||||||
bool only_initialize_values);
|
|
||||||
~bar();
|
~bar();
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
eventloop::loop& m_loop;
|
eventloop::loop& m_loop;
|
||||||
unique_ptr<screen> m_screen;
|
unique_ptr<screen> m_screen;
|
||||||
unique_ptr<tray_manager> m_tray;
|
unique_ptr<legacy_tray::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<tags::action_context> m_action_ctxt;
|
unique_ptr<tags::action_context> m_action_ctxt;
|
||||||
@ -105,12 +107,12 @@ 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::timer_handle_t m_leftclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
||||||
eventloop::TimerHandle& m_middleclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
eventloop::timer_handle_t m_middleclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
||||||
eventloop::TimerHandle& m_rightclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
eventloop::timer_handle_t m_rightclick_timer{m_loop.handle<eventloop::TimerHandle>()};
|
||||||
eventloop::TimerHandle& m_dim_timer{m_loop.handle<eventloop::TimerHandle>()};
|
eventloop::timer_handle_t m_dim_timer{m_loop.handle<eventloop::TimerHandle>()};
|
||||||
|
|
||||||
bool m_visible{true};
|
bool m_visible{true};
|
||||||
};
|
};
|
||||||
|
@ -24,10 +24,7 @@ using file_list = vector<string>;
|
|||||||
|
|
||||||
class config {
|
class config {
|
||||||
public:
|
public:
|
||||||
using make_type = const config&;
|
explicit config(const logger& logger, string&& path, string&& bar)
|
||||||
static make_type make(string path = "", string bar = "");
|
|
||||||
|
|
||||||
explicit config(const logger& logger, string&& path = "", string&& bar = "")
|
|
||||||
: m_log(logger), m_file(move(path)), m_barname(move(bar)){};
|
: m_log(logger), m_file(move(path)), m_barname(move(bar)){};
|
||||||
|
|
||||||
const string& filepath() const;
|
const string& filepath() const;
|
||||||
@ -44,33 +41,19 @@ class config {
|
|||||||
|
|
||||||
void set_included(file_list included);
|
void set_included(file_list included);
|
||||||
|
|
||||||
void warn_deprecated(const string& section, const string& key, string replacement) const;
|
file_list get_included_files() const;
|
||||||
|
|
||||||
|
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a given parameter exists
|
* Returns true if a given parameter exists
|
||||||
*/
|
*/
|
||||||
bool has(const string& section, const string& key) const {
|
bool has(const string& section, const string& key) const;
|
||||||
auto it = m_sections.find(section);
|
|
||||||
return it != m_sections.end() && it->second.find(key) != it->second.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set parameter value
|
* Set parameter value
|
||||||
*/
|
*/
|
||||||
void set(const string& section, const string& key, string&& value) {
|
void set(const string& section, const string& key, string&& value);
|
||||||
auto it = m_sections.find(section);
|
|
||||||
if (it == m_sections.end()) {
|
|
||||||
valuemap_t values;
|
|
||||||
values[key] = value;
|
|
||||||
m_sections[section] = move(values);
|
|
||||||
}
|
|
||||||
auto it2 = it->second.find(key);
|
|
||||||
if ((it2 = it->second.find(key)) == it->second.end()) {
|
|
||||||
it2 = it->second.emplace_hint(it2, key, value);
|
|
||||||
} else {
|
|
||||||
it2->second = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get parameter for the current bar by name
|
* Get parameter for the current bar by name
|
||||||
@ -92,7 +75,7 @@ class config {
|
|||||||
if (it->second.find(key) == it->second.end()) {
|
if (it->second.find(key) == it->second.end()) {
|
||||||
throw key_error("Missing parameter \"" + section + "." + key + "\"");
|
throw key_error("Missing parameter \"" + section + "." + key + "\"");
|
||||||
}
|
}
|
||||||
return dereference<T>(section, key, it->second.at(key), convert<T>(string{it->second.at(key)}));
|
return convert<T>(dereference(section, key, it->second.at(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,8 +86,7 @@ class config {
|
|||||||
T get(const string& section, const string& key, const T& default_value) const {
|
T get(const string& section, const string& key, const T& default_value) const {
|
||||||
try {
|
try {
|
||||||
string string_value{get<string>(section, key)};
|
string string_value{get<string>(section, key)};
|
||||||
T result{convert<T>(string{string_value})};
|
return convert<T>(dereference(move(section), move(key), move(string_value)));
|
||||||
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 std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
@ -157,12 +139,11 @@ class config {
|
|||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||||
T value{convert<T>(string{string_value})};
|
|
||||||
|
|
||||||
if (!string_value.empty()) {
|
if (!string_value.empty()) {
|
||||||
results.emplace_back(dereference<T>(section, key, move(string_value), move(value)));
|
results.emplace_back(convert<T>(dereference(section, key, move(string_value))));
|
||||||
} else {
|
} else {
|
||||||
results.emplace_back(move(value));
|
results.emplace_back(convert<T>(move(string_value)));
|
||||||
}
|
}
|
||||||
} catch (const key_error& err) {
|
} catch (const key_error& err) {
|
||||||
break;
|
break;
|
||||||
@ -187,12 +168,11 @@ class config {
|
|||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||||
T value{convert<T>(string{string_value})};
|
|
||||||
|
|
||||||
if (!string_value.empty()) {
|
if (!string_value.empty()) {
|
||||||
results.emplace_back(dereference<T>(section, key, move(string_value), move(value)));
|
results.emplace_back(convert<T>(dereference(section, key, move(string_value))));
|
||||||
} else {
|
} else {
|
||||||
results.emplace_back(move(value));
|
results.emplace_back(convert<T>(move(string_value)));
|
||||||
}
|
}
|
||||||
} catch (const key_error& err) {
|
} catch (const key_error& err) {
|
||||||
break;
|
break;
|
||||||
@ -210,8 +190,6 @@ 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
|
||||||
@ -225,20 +203,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);
|
||||||
* @see deprecated<T>
|
|
||||||
*/
|
|
||||||
template <typename T = string>
|
|
||||||
T deprecated_list(const string& section, const string& old, const string& newkey, const vector<T>& fallback) const {
|
|
||||||
try {
|
|
||||||
vector<T> value{get_list<T>(section, old)};
|
|
||||||
warn_deprecated(section, old, newkey);
|
|
||||||
return value;
|
|
||||||
} catch (const key_error& err) {
|
|
||||||
return get_list<T>(section, newkey, fallback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,27 +219,7 @@ class config {
|
|||||||
/**
|
/**
|
||||||
* Dereference value reference
|
* Dereference value reference
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
string dereference(const string& section, const string& key, const string& var) const;
|
||||||
T dereference(const string& section, const string& key, const string& var, const T& fallback) const {
|
|
||||||
if (var.substr(0, 2) != "${" || var.substr(var.length() - 1) != "}") {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto path = var.substr(2, var.length() - 3);
|
|
||||||
size_t pos;
|
|
||||||
|
|
||||||
if (path.compare(0, 4, "env:") == 0) {
|
|
||||||
return dereference_env<T>(path.substr(4));
|
|
||||||
} else if (path.compare(0, 5, "xrdb:") == 0) {
|
|
||||||
return dereference_xrdb<T>(path.substr(5));
|
|
||||||
} else if (path.compare(0, 5, "file:") == 0) {
|
|
||||||
return dereference_file<T>(path.substr(5));
|
|
||||||
} else if ((pos = path.find(".")) != string::npos) {
|
|
||||||
return dereference_local<T>(path.substr(0, pos), path.substr(pos + 1), section);
|
|
||||||
} else {
|
|
||||||
throw value_error("Invalid reference defined at \"" + section + "." + key + "\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dereference local value reference defined using:
|
* Dereference local value reference defined using:
|
||||||
@ -282,133 +230,28 @@ class config {
|
|||||||
* ${section.key}
|
* ${section.key}
|
||||||
* ${section.key:fallback}
|
* ${section.key:fallback}
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
string dereference_local(string section, const string& key, const string& current_section) const;
|
||||||
T dereference_local(string section, const string& key, const string& current_section) const {
|
|
||||||
if (section == "BAR") {
|
|
||||||
m_log.warn("${BAR.key} is deprecated. Use ${root.key} instead");
|
|
||||||
}
|
|
||||||
|
|
||||||
section = string_util::replace(section, "BAR", this->section(), 0, 3);
|
|
||||||
section = string_util::replace(section, "root", this->section(), 0, 4);
|
|
||||||
section = string_util::replace(section, "self", current_section, 0, 4);
|
|
||||||
|
|
||||||
try {
|
|
||||||
string string_value{get<string>(section, key)};
|
|
||||||
T result{convert<T>(string{string_value})};
|
|
||||||
return dereference<T>(string(section), move(key), move(string_value), move(result));
|
|
||||||
} catch (const key_error& err) {
|
|
||||||
size_t pos;
|
|
||||||
if ((pos = key.find(':')) != string::npos) {
|
|
||||||
string fallback = key.substr(pos + 1);
|
|
||||||
m_log.info("The reference ${%s.%s} does not exist, using defined fallback value \"%s\"", section,
|
|
||||||
key.substr(0, pos), fallback);
|
|
||||||
return convert<T>(move(fallback));
|
|
||||||
}
|
|
||||||
throw value_error("The reference ${" + section + "." + key + "} does not exist (no fallback set)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dereference environment variable reference defined using:
|
* Dereference environment variable reference defined using:
|
||||||
* ${env:key}
|
* ${env:key}
|
||||||
* ${env:key:fallback value}
|
* ${env:key:fallback value}
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
string dereference_env(string var) const;
|
||||||
T dereference_env(string var) const {
|
|
||||||
size_t pos;
|
|
||||||
string env_default;
|
|
||||||
/*
|
|
||||||
* This is needed because with only the string we cannot distinguish
|
|
||||||
* between an empty string as default and not default
|
|
||||||
*/
|
|
||||||
bool has_default = false;
|
|
||||||
|
|
||||||
if ((pos = var.find(':')) != string::npos) {
|
|
||||||
env_default = var.substr(pos + 1);
|
|
||||||
has_default = true;
|
|
||||||
var.erase(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env_util::has(var)) {
|
|
||||||
string env_value{env_util::get(var)};
|
|
||||||
m_log.info("Environment var reference ${%s} found (value=%s)", var, env_value);
|
|
||||||
return convert<T>(move(env_value));
|
|
||||||
} else if (has_default) {
|
|
||||||
m_log.info("Environment var ${%s} is undefined, using defined fallback value \"%s\"", var, env_default);
|
|
||||||
return convert<T>(move(env_default));
|
|
||||||
} else {
|
|
||||||
throw value_error(sstream() << "Environment var ${" << var << "} does not exist (no fallback set)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dereference X resource db value defined using:
|
* Dereference X resource db value defined using:
|
||||||
* ${xrdb:key}
|
* ${xrdb:key}
|
||||||
* ${xrdb:key:fallback value}
|
* ${xrdb:key:fallback value}
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
string dereference_xrdb(string var) const;
|
||||||
T dereference_xrdb(string var) const {
|
|
||||||
size_t pos;
|
|
||||||
#if not WITH_XRM
|
|
||||||
m_log.warn("No built-in support to dereference ${xrdb:%s} references (requires `xcb-util-xrm`)", var);
|
|
||||||
if ((pos = var.find(':')) != string::npos) {
|
|
||||||
return convert<T>(var.substr(pos + 1));
|
|
||||||
}
|
|
||||||
return convert<T>("");
|
|
||||||
#else
|
|
||||||
if (!m_xrm) {
|
|
||||||
throw application_error("xrm is not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
string fallback;
|
|
||||||
bool has_fallback = false;
|
|
||||||
if ((pos = var.find(':')) != string::npos) {
|
|
||||||
fallback = var.substr(pos + 1);
|
|
||||||
has_fallback = true;
|
|
||||||
var.erase(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto value = m_xrm->require<string>(var.c_str());
|
|
||||||
m_log.info("Found matching X resource \"%s\" (value=%s)", var, value);
|
|
||||||
return convert<T>(move(value));
|
|
||||||
} catch (const xresource_error& err) {
|
|
||||||
if (has_fallback) {
|
|
||||||
m_log.info("%s, using defined fallback value \"%s\"", err.what(), fallback);
|
|
||||||
return convert<T>(move(fallback));
|
|
||||||
}
|
|
||||||
throw value_error(sstream() << err.what() << " (no fallback set)");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dereference file reference by reading its contents
|
* Dereference file reference by reading its contents
|
||||||
* ${file:/absolute/file/path}
|
* ${file:/absolute/file/path}
|
||||||
* ${file:/absolute/file/path:fallback value}
|
* ${file:/absolute/file/path:fallback value}
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
string dereference_file(string var) const;
|
||||||
T dereference_file(string var) const {
|
|
||||||
size_t pos;
|
|
||||||
string fallback;
|
|
||||||
bool has_fallback = false;
|
|
||||||
if ((pos = var.find(':')) != string::npos) {
|
|
||||||
fallback = var.substr(pos + 1);
|
|
||||||
has_fallback = true;
|
|
||||||
var.erase(pos);
|
|
||||||
}
|
|
||||||
var = file_util::expand(var);
|
|
||||||
|
|
||||||
if (file_util::exists(var)) {
|
|
||||||
m_log.info("File reference \"%s\" found", var);
|
|
||||||
return convert<T>(string_util::trim(file_util::contents(var), '\n'));
|
|
||||||
} else if (has_fallback) {
|
|
||||||
m_log.info("File reference \"%s\" not found, using defined fallback value \"%s\"", var, fallback);
|
|
||||||
return convert<T>(move(fallback));
|
|
||||||
} else {
|
|
||||||
throw value_error(sstream() << "The file \"" << var << "\" does not exist (no fallback set)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
|
@ -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 parse(string barname);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -229,12 +229,7 @@ class config_parser {
|
|||||||
/**
|
/**
|
||||||
* @brief Absolute path to the main config file
|
* @brief Absolute path to the main config file
|
||||||
*/
|
*/
|
||||||
string m_config;
|
string m_config_file;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
||||||
|
@ -39,7 +39,7 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eve
|
|||||||
signals::ipc::hook, signals::ui::button_press, signals::ui::update_background> {
|
signals::ipc::hook, 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(bool has_ipc, eventloop::loop&);
|
static make_type make(bool has_ipc, eventloop::loop&, const config&);
|
||||||
|
|
||||||
explicit controller(connection&, signal_emitter&, const logger&, const config&, bool has_ipc, eventloop::loop&);
|
explicit controller(connection&, signal_emitter&, const logger&, const config&, bool has_ipc, eventloop::loop&);
|
||||||
~controller();
|
~controller();
|
||||||
@ -55,12 +55,14 @@ 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& filename);
|
||||||
void confwatch_handler(const char* fname);
|
void confwatch_handler(const char* fname);
|
||||||
void notifier_handler();
|
void notifier_handler();
|
||||||
void screenshot_handler();
|
void screenshot_handler();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void trigger_notification();
|
void trigger_notification();
|
||||||
|
void start_modules();
|
||||||
void read_events(bool confwatch);
|
void read_events(bool confwatch);
|
||||||
void process_inputdata(string&& cmd);
|
void process_inputdata(string&& cmd);
|
||||||
bool process_update(bool force);
|
bool process_update(bool force);
|
||||||
@ -100,6 +102,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
|
||||||
@ -107,7 +110,7 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eve
|
|||||||
* This handle is used to notify the eventloop of changes which are not otherwise covered by other handles.
|
* This handle is used to notify the eventloop of changes which are not otherwise covered by other handles.
|
||||||
* E.g. click actions.
|
* E.g. click actions.
|
||||||
*/
|
*/
|
||||||
eventloop::AsyncHandle& m_notifier{m_loop.handle<eventloop::AsyncHandle>([this]() { notifier_handler(); })};
|
eventloop::async_handle_t m_notifier{m_loop.handle<eventloop::AsyncHandle>([this]() { notifier_handler(); })};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification data for the controller.
|
* Notification data for the controller.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "components/logger.hpp"
|
#include "components/logger.hpp"
|
||||||
@ -36,12 +37,12 @@ namespace eventloop {
|
|||||||
get()->data = this;
|
get()->data = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self& leak(std::unique_ptr<Self> h) {
|
void leak(std::shared_ptr<Self> h) {
|
||||||
lifetime_extender = std::move(h);
|
lifetime_extender = std::move(h);
|
||||||
return *lifetime_extender;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unleak() {
|
void unleak() {
|
||||||
|
reset_callbacks();
|
||||||
lifetime_extender.reset();
|
lifetime_extender.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +74,15 @@ namespace eventloop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
~Handle() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets all callbacks stored in the handle as part of closing the handle.
|
||||||
|
*
|
||||||
|
* This releases any lambda captures, breaking possible cyclic dependencies in shared_ptr.
|
||||||
|
*/
|
||||||
|
virtual void reset_callbacks() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic callback function that can be used for all uv handle callbacks.
|
* Generic callback function that can be used for all uv handle callbacks.
|
||||||
*
|
*
|
||||||
@ -128,14 +138,14 @@ namespace eventloop {
|
|||||||
uv_loop_t* uv_loop;
|
uv_loop_t* uv_loop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The handle stores the unique_ptr to itself so that it effectively leaks memory.
|
* The handle stores the shared_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.
|
* 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
|
* 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.
|
* is reset and the object is explicitly destroyed.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Self> lifetime_extender;
|
std::shared_ptr<Self> lifetime_extender;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ErrorEvent {
|
struct ErrorEvent {
|
||||||
@ -144,54 +154,32 @@ namespace eventloop {
|
|||||||
|
|
||||||
using cb_error = cb_event<ErrorEvent>;
|
using cb_error = cb_event<ErrorEvent>;
|
||||||
|
|
||||||
class WriteRequest : public non_copyable_mixin {
|
class WriteRequest : public non_copyable_mixin, public non_movable_mixin {
|
||||||
public:
|
public:
|
||||||
using cb_write = cb_void;
|
using cb_write = cb_void;
|
||||||
|
|
||||||
WriteRequest(cb_write user_cb, cb_error err_cb) : write_callback(user_cb), write_err_cb(err_cb) {
|
WriteRequest(cb_write&& user_cb, cb_error&& err_cb);
|
||||||
get()->data = this;
|
|
||||||
};
|
|
||||||
|
|
||||||
static WriteRequest& create(cb_write user_cb, cb_error err_cb) {
|
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() {
|
uv_write_t* get();
|
||||||
return &req;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger the write callback.
|
* Trigger the write callback.
|
||||||
*
|
*
|
||||||
* After that, this object is destroyed.
|
* After that, this object is destroyed.
|
||||||
*/
|
*/
|
||||||
void trigger(int status) {
|
void trigger(int status);
|
||||||
if (status < 0) {
|
|
||||||
if (write_err_cb) {
|
|
||||||
write_err_cb(ErrorEvent{status});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (write_callback) {
|
|
||||||
write_callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unleak();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WriteRequest& leak(std::unique_ptr<WriteRequest> h) {
|
WriteRequest& leak(std::unique_ptr<WriteRequest> h);
|
||||||
lifetime_extender = std::move(h);
|
|
||||||
return *lifetime_extender;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unleak() {
|
void unleak();
|
||||||
lifetime_extender.reset();
|
|
||||||
}
|
void reset_callbacks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uv_write_t req;
|
uv_write_t req{};
|
||||||
|
|
||||||
cb_write write_callback;
|
cb_write write_callback;
|
||||||
cb_error write_err_cb;
|
cb_error write_err_cb;
|
||||||
@ -208,13 +196,16 @@ namespace eventloop {
|
|||||||
int signum;
|
int signum;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SignalHandle : public Handle<SignalHandle, uv_signal_t> {
|
class SignalHandle final : public Handle<SignalHandle, uv_signal_t> {
|
||||||
public:
|
public:
|
||||||
using Handle::Handle;
|
using Handle::Handle;
|
||||||
using cb = cb_event<SignalEvent>;
|
using cb = cb_event<SignalEvent>;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void start(int signum, cb user_cb);
|
void start(int signum, cb&& user_cb);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cb callback;
|
cb callback;
|
||||||
@ -224,15 +215,18 @@ namespace eventloop {
|
|||||||
uv_poll_event event;
|
uv_poll_event event;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PollHandle : public Handle<PollHandle, uv_poll_t> {
|
class PollHandle final : public Handle<PollHandle, uv_poll_t> {
|
||||||
public:
|
public:
|
||||||
using Handle::Handle;
|
using Handle::Handle;
|
||||||
using cb = cb_event<PollEvent>;
|
using cb = cb_event<PollEvent>;
|
||||||
|
|
||||||
void init(int fd);
|
void init(int fd);
|
||||||
void start(int events, cb user_cb, cb_error err_cb);
|
void start(int events, cb&& user_cb, cb_error&& err_cb);
|
||||||
static void poll_callback(uv_poll_t*, int status, int events);
|
static void poll_callback(uv_poll_t*, int status, int events);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cb callback;
|
cb callback;
|
||||||
cb_error err_cb;
|
cb_error err_cb;
|
||||||
@ -243,41 +237,50 @@ namespace eventloop {
|
|||||||
uv_fs_event event;
|
uv_fs_event event;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FSEventHandle : public Handle<FSEventHandle, uv_fs_event_t> {
|
class FSEventHandle final : public Handle<FSEventHandle, uv_fs_event_t> {
|
||||||
public:
|
public:
|
||||||
using Handle::Handle;
|
using Handle::Handle;
|
||||||
using cb = cb_event<FSEvent>;
|
using cb = cb_event<FSEvent>;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void start(const string& path, int flags, cb user_cb, cb_error err_cb);
|
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);
|
static void fs_event_callback(uv_fs_event_t*, const char* path, int events, int status);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cb callback;
|
cb callback;
|
||||||
cb_error err_cb;
|
cb_error err_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimerHandle : public Handle<TimerHandle, uv_timer_t> {
|
class TimerHandle final : public Handle<TimerHandle, uv_timer_t> {
|
||||||
public:
|
public:
|
||||||
using Handle::Handle;
|
using Handle::Handle;
|
||||||
using cb = cb_void;
|
using cb = cb_void;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void start(uint64_t timeout, uint64_t repeat, cb user_cb);
|
void start(uint64_t timeout, uint64_t repeat, cb&& user_cb);
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cb callback;
|
cb callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncHandle : public Handle<AsyncHandle, uv_async_t> {
|
class AsyncHandle final : public Handle<AsyncHandle, uv_async_t> {
|
||||||
public:
|
public:
|
||||||
using Handle::Handle;
|
using Handle::Handle;
|
||||||
using cb = cb_void;
|
using cb = cb_void;
|
||||||
|
|
||||||
void init(cb user_cb);
|
void init(cb&& user_cb);
|
||||||
void send();
|
void send();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cb callback;
|
cb callback;
|
||||||
};
|
};
|
||||||
@ -295,9 +298,9 @@ namespace eventloop {
|
|||||||
using cb_read_eof = cb_void;
|
using cb_read_eof = cb_void;
|
||||||
using cb_connection = cb_void;
|
using cb_connection = cb_void;
|
||||||
|
|
||||||
void listen(int backlog, cb_connection user_cb, cb_error err_cb) {
|
void listen(int backlog, cb_connection&& user_cb, cb_error&& err_cb) {
|
||||||
this->connection_callback = user_cb;
|
this->connection_callback = std::move(user_cb);
|
||||||
this->connection_err_cb = err_cb;
|
this->connection_err_cb = std::move(err_cb);
|
||||||
UV(uv_listen, this->template get<uv_stream_t>(), backlog, connection_cb);
|
UV(uv_listen, this->template get<uv_stream_t>(), backlog, connection_cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -316,11 +319,11 @@ namespace eventloop {
|
|||||||
UV(uv_accept, this->template get<uv_stream_t>(), client.template get<uv_stream_t>());
|
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) {
|
void read_start(cb_read&& fun, cb_void&& eof_cb, cb_error&& err_cb) {
|
||||||
this->read_callback = fun;
|
this->read_callback = std::move(fun);
|
||||||
this->read_eof_cb = eof_cb;
|
this->read_eof_cb = std::move(eof_cb);
|
||||||
this->read_err_cb = err_cb;
|
this->read_err_cb = std::move(err_cb);
|
||||||
UV(uv_read_start, this->template get<uv_stream_t>(), &this->alloc_callback, read_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) {
|
static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
|
||||||
@ -340,8 +343,8 @@ namespace eventloop {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void write(const vector<uint8_t>& data, WriteRequest::cb_write user_cb = {}, cb_error err_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);
|
WriteRequest& req = WriteRequest::create(std::move(user_cb), std::move(err_cb));
|
||||||
|
|
||||||
uv_buf_t buf{(char*)data.data(), data.size()};
|
uv_buf_t buf{(char*)data.data(), data.size()};
|
||||||
|
|
||||||
@ -349,6 +352,17 @@ namespace eventloop {
|
|||||||
[](uv_write_t* r, int status) { static_cast<WriteRequest*>(r->data)->trigger(status); });
|
[](uv_write_t* r, int status) { static_cast<WriteRequest*>(r->data)->trigger(status); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~StreamHandle() = default;
|
||||||
|
|
||||||
|
void reset_callbacks() override {
|
||||||
|
read_callback = nullptr;
|
||||||
|
read_eof_cb = nullptr;
|
||||||
|
read_err_cb = nullptr;
|
||||||
|
connection_callback = nullptr;
|
||||||
|
connection_err_cb = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Callback for receiving data
|
* Callback for receiving data
|
||||||
@ -371,7 +385,7 @@ namespace eventloop {
|
|||||||
cb_error connection_err_cb;
|
cb_error connection_err_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PipeHandle : public StreamHandle<PipeHandle, uv_pipe_t> {
|
class PipeHandle final : public StreamHandle<PipeHandle, uv_pipe_t> {
|
||||||
public:
|
public:
|
||||||
using StreamHandle::StreamHandle;
|
using StreamHandle::StreamHandle;
|
||||||
using cb_connect = cb_void;
|
using cb_connect = cb_void;
|
||||||
@ -381,7 +395,10 @@ namespace eventloop {
|
|||||||
|
|
||||||
void bind(const string& path);
|
void bind(const string& path);
|
||||||
|
|
||||||
void connect(const string& name, cb_connect user_cb, cb_error err_cb);
|
void connect(const string& name, cb_connect&& user_cb, cb_error&& err_cb);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void connect_cb(uv_connect_t* req, int status);
|
static void connect_cb(uv_connect_t* req, int status);
|
||||||
@ -390,27 +407,53 @@ namespace eventloop {
|
|||||||
cb_connect connect_callback;
|
cb_connect connect_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PrepareHandle final : public Handle<PrepareHandle, uv_prepare_t> {
|
||||||
|
public:
|
||||||
|
using Handle::Handle;
|
||||||
|
using cb = cb_void;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void start(cb&& user_cb);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset_callbacks() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void connect_cb(uv_connect_t* req, int status);
|
||||||
|
|
||||||
|
cb callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
using signal_handle_t = shared_ptr<SignalHandle>;
|
||||||
|
using poll_handle_t = shared_ptr<PollHandle>;
|
||||||
|
using fs_event_handle_t = shared_ptr<FSEventHandle>;
|
||||||
|
using timer_handle_t = shared_ptr<TimerHandle>;
|
||||||
|
using async_handle_t = shared_ptr<AsyncHandle>;
|
||||||
|
using pipe_handle_t = shared_ptr<PipeHandle>;
|
||||||
|
using prepare_handle_t = shared_ptr<PrepareHandle>;
|
||||||
|
|
||||||
class loop : public non_copyable_mixin, public non_movable_mixin {
|
class loop : public non_copyable_mixin, public non_movable_mixin {
|
||||||
public:
|
public:
|
||||||
loop();
|
loop();
|
||||||
~loop();
|
~loop();
|
||||||
void run();
|
void run();
|
||||||
void stop();
|
void stop();
|
||||||
|
uint64_t now() const;
|
||||||
|
|
||||||
template <typename H, typename... Args>
|
template <typename H, typename... Args>
|
||||||
H& handle(Args... args) {
|
shared_ptr<H> handle(Args&&... args) {
|
||||||
auto ptr = make_unique<H>(get());
|
auto ptr = make_shared<H>(get());
|
||||||
ptr->init(std::forward<Args>(args)...);
|
ptr->init(std::forward<Args>(args)...);
|
||||||
return ptr->leak(std::move(ptr));
|
ptr->leak(ptr);
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
uv_loop_t* get() const;
|
uv_loop_t* get() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<uv_loop_t> m_loop{nullptr};
|
std::unique_ptr<uv_loop_t> m_loop{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace eventloop
|
} // namespace eventloop
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -34,11 +34,15 @@ class logger {
|
|||||||
|
|
||||||
explicit logger(loglevel level);
|
explicit logger(loglevel level);
|
||||||
|
|
||||||
|
const logger& operator=(const logger&) const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
static loglevel parse_verbosity(const string& name, loglevel fallback = loglevel::NONE);
|
static loglevel parse_verbosity(const string& name, loglevel fallback = loglevel::NONE);
|
||||||
|
|
||||||
void verbosity(loglevel level);
|
void verbosity(loglevel level);
|
||||||
|
|
||||||
#ifdef DEBUG_LOGGER // {{{
|
#ifdef DEBUG_LOGGER // {{{
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void trace(const string& message, Args&&... args) const {
|
void trace(const string& message, Args&&... args) const {
|
||||||
output(loglevel::TRACE, message, std::forward<Args>(args)...);
|
output(loglevel::TRACE, message, std::forward<Args>(args)...);
|
||||||
@ -57,7 +61,7 @@ class logger {
|
|||||||
void trace(Args&&...) const {}
|
void trace(Args&&...) const {}
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void trace_x(Args&&...) const {}
|
void trace_x(Args&&...) const {}
|
||||||
#endif // }}}
|
#endif // }}}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output an info message
|
* Output an info message
|
||||||
@ -118,21 +122,21 @@ class logger {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__clang__) // {{{
|
#if defined(__clang__) // {{{
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wformat-security"
|
#pragma clang diagnostic ignored "-Wformat-security"
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wformat-security"
|
#pragma GCC diagnostic ignored "-Wformat-security"
|
||||||
#endif // }}}
|
#endif // }}}
|
||||||
|
|
||||||
dprintf(m_fd, (m_prefixes.at(level) + format + m_suffixes.at(level) + "\n").c_str(), convert(values)...);
|
dprintf(m_fd, (m_prefixes.at(level) + format + m_suffixes.at(level) + "\n").c_str(), convert(values)...);
|
||||||
|
|
||||||
#if defined(__clang__) // {{{
|
#if defined(__clang__) // {{{
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif // }}}
|
#endif // }}}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -46,13 +46,15 @@ class renderer : public renderer_interface,
|
|||||||
public signal_receiver<SIGN_PRIORITY_RENDERER, signals::ui::request_snapshot> {
|
public signal_receiver<SIGN_PRIORITY_RENDERER, signals::ui::request_snapshot> {
|
||||||
public:
|
public:
|
||||||
using make_type = unique_ptr<renderer>;
|
using make_type = unique_ptr<renderer>;
|
||||||
static make_type make(const bar_settings& bar, tags::action_context& action_ctxt);
|
static make_type make(const bar_settings& bar, tags::action_context& action_ctxt, const config&);
|
||||||
|
|
||||||
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, tags::action_context& action_ctxt);
|
background_manager& background_manager, tags::action_context& action_ctxt);
|
||||||
~renderer();
|
~renderer();
|
||||||
|
|
||||||
xcb_window_t window() const;
|
xcb_window_t window() const;
|
||||||
|
xcb_visualtype_t* visual() const;
|
||||||
|
int depth() const;
|
||||||
|
|
||||||
void begin(xcb_rectangle_t rect);
|
void begin(xcb_rectangle_t rect);
|
||||||
void end();
|
void end();
|
||||||
@ -67,6 +69,8 @@ class renderer : public renderer_interface,
|
|||||||
|
|
||||||
double get_alignment_start(const alignment align) const override;
|
double get_alignment_start(const alignment align) const override;
|
||||||
|
|
||||||
|
void apply_tray_position(const tags::context& context) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void fill_background();
|
void fill_background();
|
||||||
void fill_overline(rgba color, double x, double w);
|
void fill_overline(rgba color, double x, double w);
|
||||||
@ -100,18 +104,22 @@ class renderer : public renderer_interface,
|
|||||||
const bar_settings& m_bar;
|
const bar_settings& m_bar;
|
||||||
std::shared_ptr<bg_slice> m_background;
|
std::shared_ptr<bg_slice> m_background;
|
||||||
|
|
||||||
int m_depth{32};
|
int m_depth{-1};
|
||||||
xcb_window_t m_window;
|
xcb_window_t m_window;
|
||||||
xcb_colormap_t m_colormap;
|
xcb_colormap_t m_colormap{XCB_NONE};
|
||||||
xcb_visualtype_t* m_visual;
|
xcb_visualtype_t* m_visual;
|
||||||
xcb_gcontext_t m_gcontext;
|
xcb_gcontext_t m_gcontext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Background pixmap for the bar window
|
||||||
|
*
|
||||||
|
* All bar contents are rendered onto this.
|
||||||
|
*/
|
||||||
xcb_pixmap_t m_pixmap;
|
xcb_pixmap_t m_pixmap;
|
||||||
|
|
||||||
xcb_rectangle_t m_rect{0, 0, 0U, 0U};
|
xcb_rectangle_t m_rect{0, 0, 0U, 0U};
|
||||||
reserve_area m_cleararea{};
|
reserve_area m_cleararea{};
|
||||||
|
|
||||||
// bool m_autosize{false};
|
|
||||||
|
|
||||||
unique_ptr<cairo::context> m_context;
|
unique_ptr<cairo::context> m_context;
|
||||||
unique_ptr<cairo::xcb_surface> m_surface;
|
unique_ptr<cairo::xcb_surface> m_surface;
|
||||||
map<alignment, alignment_block> m_blocks;
|
map<alignment, alignment_block> m_blocks;
|
||||||
|
@ -33,6 +33,8 @@ class renderer_interface {
|
|||||||
*/
|
*/
|
||||||
virtual double get_alignment_start(const alignment align) const = 0;
|
virtual double get_alignment_start(const alignment align) const = 0;
|
||||||
|
|
||||||
|
virtual void apply_tray_position(const tags::context& context) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Stores information about actions in the current render cycle.
|
* Stores information about actions in the current render cycle.
|
||||||
|
@ -16,23 +16,16 @@ class logger;
|
|||||||
class connection;
|
class connection;
|
||||||
class signal_emitter;
|
class signal_emitter;
|
||||||
|
|
||||||
class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
|
class screen : public xpp::event::sink<evt::map_notify, evt::randr_screen_change_notify> {
|
||||||
public:
|
public:
|
||||||
using make_type = unique_ptr<screen>;
|
using make_type = unique_ptr<screen>;
|
||||||
static make_type make();
|
static make_type make(const config&);
|
||||||
|
|
||||||
explicit screen(connection& conn, signal_emitter& emitter, const logger& logger, const config& conf);
|
explicit screen(connection& conn, signal_emitter& emitter, const logger& logger, const config& conf);
|
||||||
~screen();
|
~screen();
|
||||||
|
|
||||||
struct size size() const {
|
|
||||||
return m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
xcb_window_t root() const {
|
|
||||||
return m_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void handle(const evt::map_notify& evt) override;
|
||||||
void handle(const evt::randr_screen_change_notify& evt) override;
|
void handle(const evt::randr_screen_change_notify& evt) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -50,6 +43,12 @@ class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
|
|||||||
};
|
};
|
||||||
bool m_sigraised{false};
|
bool m_sigraised{false};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Original event mask on the root window.
|
||||||
|
* Used to restore event mask after the proxy window is mapped.
|
||||||
|
*/
|
||||||
|
uint32_t m_root_mask{0};
|
||||||
|
|
||||||
bool have_monitors_changed() const;
|
bool have_monitors_changed() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,11 +82,15 @@ enum class strut {
|
|||||||
struct position {
|
struct position {
|
||||||
int x{0};
|
int x{0};
|
||||||
int y{0};
|
int y{0};
|
||||||
|
|
||||||
|
bool operator==(const position& other) {
|
||||||
|
return this->x == other.x && this->y == other.y;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct size {
|
struct size {
|
||||||
unsigned int w{1U};
|
unsigned w{1U};
|
||||||
unsigned int h{1U};
|
unsigned h{1U};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class spacing_type { SPACE, POINT, PIXEL };
|
enum class spacing_type { SPACE, POINT, PIXEL };
|
||||||
@ -163,11 +167,21 @@ struct action {
|
|||||||
string command{};
|
string command{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings specific to the X window system.
|
||||||
|
*/
|
||||||
|
struct x_settings {
|
||||||
|
xcb_window_t window{XCB_NONE};
|
||||||
|
xcb_visualtype_t* visual{nullptr};
|
||||||
|
int depth{-1};
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
xcb_window_t window{XCB_NONE};
|
x_settings x_data;
|
||||||
|
|
||||||
monitor_t monitor{};
|
monitor_t monitor{};
|
||||||
bool monitor_strict{false};
|
bool monitor_strict{false};
|
||||||
bool monitor_exact{true};
|
bool monitor_exact{true};
|
||||||
@ -183,6 +197,7 @@ struct bar_settings {
|
|||||||
position offset{0, 0};
|
position offset{0, 0};
|
||||||
side_values padding{ZERO_SPACE, ZERO_SPACE};
|
side_values padding{ZERO_SPACE, ZERO_SPACE};
|
||||||
side_values module_margin{ZERO_SPACE, ZERO_SPACE};
|
side_values module_margin{ZERO_SPACE, ZERO_SPACE};
|
||||||
|
bool struts{true};
|
||||||
struct {
|
struct {
|
||||||
int top;
|
int top;
|
||||||
int bottom;
|
int bottom;
|
||||||
@ -275,9 +290,4 @@ struct event_timer {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class output_policy {
|
|
||||||
REDIRECTED,
|
|
||||||
IGNORED,
|
|
||||||
};
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -21,6 +21,6 @@ namespace drawtypes {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using iconset_t = shared_ptr<iconset>;
|
using iconset_t = shared_ptr<iconset>;
|
||||||
} // namespace drawtypes
|
} // namespace drawtypes
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -16,6 +16,7 @@ namespace drawtypes {
|
|||||||
size_t max{0_z};
|
size_t max{0_z};
|
||||||
string suffix{""s};
|
string suffix{""s};
|
||||||
bool zpad{false};
|
bool zpad{false};
|
||||||
|
bool rpadding{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
class label : public non_copyable_mixin {
|
class label : public non_copyable_mixin {
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
using std::strerror;
|
|
||||||
using std::exception;
|
using std::exception;
|
||||||
using std::runtime_error;
|
using std::runtime_error;
|
||||||
|
using std::strerror;
|
||||||
|
|
||||||
class application_error : public runtime_error {
|
class application_error : public runtime_error {
|
||||||
public:
|
public:
|
||||||
explicit application_error(const string& message, int code = 0) : runtime_error(message), code(code) {}
|
explicit application_error(const string& message, int code = 0) : runtime_error(message), code(code) {}
|
||||||
virtual ~application_error() {}
|
|
||||||
int code{0};
|
int code{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,7 +23,6 @@ class system_error : public application_error {
|
|||||||
explicit system_error() : application_error(strerror(errno), errno) {}
|
explicit system_error() : application_error(strerror(errno), errno) {}
|
||||||
explicit system_error(const string& message)
|
explicit system_error(const string& message)
|
||||||
: application_error(message + " (reason: " + strerror(errno) + ")", errno) {}
|
: application_error(message + " (reason: " + strerror(errno) + ")", errno) {}
|
||||||
virtual ~system_error() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_CHILD_ERROR(error, parent) \
|
#define DEFINE_CHILD_ERROR(error, parent) \
|
||||||
|
@ -101,7 +101,7 @@ namespace signals {
|
|||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
||||||
namespace ui_tray {
|
namespace ui_tray {
|
||||||
struct mapped_clients : public detail::value_signal<mapped_clients, unsigned int> {
|
struct tray_pos_change : public detail::value_signal<tray_pos_change, int> {
|
||||||
using base_type::base_type;
|
using base_type::base_type;
|
||||||
};
|
};
|
||||||
} // namespace ui_tray
|
} // namespace ui_tray
|
||||||
|
@ -35,8 +35,8 @@ namespace signals {
|
|||||||
struct update_geometry;
|
struct update_geometry;
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
namespace ui_tray {
|
namespace ui_tray {
|
||||||
struct mapped_clients;
|
struct tray_pos_change;
|
||||||
}
|
} // namespace ui_tray
|
||||||
} // namespace signals
|
} // namespace signals
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -42,14 +42,14 @@ namespace ipc {
|
|||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
eventloop::loop& m_loop;
|
eventloop::loop& m_loop;
|
||||||
|
|
||||||
eventloop::PipeHandle& socket;
|
eventloop::pipe_handle_t m_socket;
|
||||||
|
|
||||||
class connection : public non_copyable_mixin, public non_movable_mixin {
|
class connection : public non_copyable_mixin, public non_movable_mixin {
|
||||||
public:
|
public:
|
||||||
using cb = std::function<void(connection&, uint8_t, type_t, const std::vector<uint8_t>&)>;
|
using cb = std::function<void(connection&, uint8_t, type_t, const std::vector<uint8_t>&)>;
|
||||||
connection(eventloop::loop& loop, cb msg_callback);
|
connection(eventloop::loop& loop, cb msg_callback);
|
||||||
~connection();
|
~connection();
|
||||||
eventloop::PipeHandle& client_pipe;
|
eventloop::pipe_handle_t client_pipe;
|
||||||
decoder dec;
|
decoder dec;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ namespace ipc {
|
|||||||
struct fifo {
|
struct fifo {
|
||||||
fifo(eventloop::loop& loop, ipc& ipc, const string& path);
|
fifo(eventloop::loop& loop, ipc& ipc, const string& path);
|
||||||
~fifo();
|
~fifo();
|
||||||
eventloop::PipeHandle& pipe_handle;
|
eventloop::pipe_handle_t pipe_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
unique_ptr<fifo> ipc_pipe;
|
unique_ptr<fifo> ipc_pipe;
|
||||||
@ -89,7 +89,7 @@ namespace ipc {
|
|||||||
* Buffer for the currently received IPC message over the named pipe
|
* Buffer for the currently received IPC message over the named pipe
|
||||||
*/
|
*/
|
||||||
string m_pipe_buffer{};
|
string m_pipe_buffer{};
|
||||||
void receive_data(string buf);
|
void receive_data(const string& buf);
|
||||||
void receive_eof();
|
void receive_eof();
|
||||||
};
|
};
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/event_module.hpp"
|
#include "modules/meta/event_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -20,7 +21,7 @@ namespace modules {
|
|||||||
|
|
||||||
class alsa_module : public event_module<alsa_module> {
|
class alsa_module : public event_module<alsa_module> {
|
||||||
public:
|
public:
|
||||||
explicit alsa_module(const bar_settings&, string);
|
explicit alsa_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void teardown();
|
void teardown();
|
||||||
bool has_event();
|
bool has_event();
|
||||||
@ -29,7 +30,7 @@ namespace modules {
|
|||||||
string get_output();
|
string get_output();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/alsa";
|
static constexpr auto TYPE = ALSA_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_INC = "inc";
|
static constexpr auto EVENT_INC = "inc";
|
||||||
static constexpr auto EVENT_DEC = "dec";
|
static constexpr auto EVENT_DEC = "dec";
|
||||||
|
@ -2,11 +2,25 @@
|
|||||||
|
|
||||||
#include "components/config.hpp"
|
#include "components/config.hpp"
|
||||||
#include "modules/meta/inotify_module.hpp"
|
#include "modules/meta/inotify_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
/**
|
||||||
|
* Reads value from `/sys/class/backlight/` to get a brightness value for some device.
|
||||||
|
*
|
||||||
|
* There are two file providing brightness values: `brightness` and `actual_brightness`.
|
||||||
|
* The `actual_brightness` file is usually more reliable, but in some cases does not work (provides completely wrong
|
||||||
|
* values, doesn't update) depending on kernel version, graphics driver, and/or graphics card.
|
||||||
|
* Which file is used is controlled by the use-actual-brightness setting.
|
||||||
|
*
|
||||||
|
* The general issue with the `brightness` file seems to be that, while it does receive inotify events, the events it
|
||||||
|
* receives are not for modification of the file and arrive just before the file is updated with a new value. The module
|
||||||
|
* thus reads and displays an outdated brightness value. To compensate for this, the module periodically (controlled by
|
||||||
|
* `poll-interval`) forces an update. By default, this is only enabled if the `backlight` file is used.
|
||||||
|
*/
|
||||||
class backlight_module : public inotify_module<backlight_module> {
|
class backlight_module : public inotify_module<backlight_module> {
|
||||||
public:
|
public:
|
||||||
struct brightness_handle {
|
struct brightness_handle {
|
||||||
@ -19,14 +33,13 @@ namespace modules {
|
|||||||
|
|
||||||
string get_output();
|
string get_output();
|
||||||
|
|
||||||
public:
|
explicit backlight_module(const bar_settings&, string, const config&);
|
||||||
explicit backlight_module(const bar_settings&, string);
|
|
||||||
|
|
||||||
void idle();
|
void idle();
|
||||||
bool on_event(inotify_event* event);
|
bool on_event(const inotify_event& event);
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/backlight";
|
static constexpr auto TYPE = BACKLIGHT_TYPE;
|
||||||
|
|
||||||
static constexpr const char* EVENT_INC = "inc";
|
static constexpr const char* EVENT_INC = "inc";
|
||||||
static constexpr const char* EVENT_DEC = "dec";
|
static constexpr const char* EVENT_DEC = "dec";
|
||||||
@ -46,15 +59,19 @@ namespace modules {
|
|||||||
label_t m_label;
|
label_t m_label;
|
||||||
progressbar_t m_progressbar;
|
progressbar_t m_progressbar;
|
||||||
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;
|
||||||
brightness_handle m_max;
|
brightness_handle m_max;
|
||||||
|
|
||||||
int m_percentage = 0;
|
int m_percentage = 0;
|
||||||
|
|
||||||
|
chrono::duration<double> m_interval{};
|
||||||
|
chrono::steady_clock::time_point m_lastpoll;
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "modules/meta/inotify_module.hpp"
|
#include "modules/meta/inotify_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
@ -46,16 +47,16 @@ namespace modules {
|
|||||||
using consumption_reader = mutex_wrapper<value_reader<string /* watts */>>;
|
using consumption_reader = mutex_wrapper<value_reader<string /* watts */>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit battery_module(const bar_settings&, string);
|
explicit battery_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void start() override;
|
void start() override;
|
||||||
void teardown();
|
void teardown();
|
||||||
void idle();
|
void idle();
|
||||||
bool on_event(inotify_event* event);
|
bool on_event(const inotify_event& event);
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/battery";
|
static constexpr auto TYPE = BATTERY_TYPE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
state current_state();
|
state current_state();
|
||||||
@ -115,6 +116,6 @@ namespace modules {
|
|||||||
chrono::steady_clock::time_point m_lastpoll;
|
chrono::steady_clock::time_point m_lastpoll;
|
||||||
thread m_subthread;
|
thread m_subthread;
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/event_module.hpp"
|
#include "modules/meta/event_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "utils/bspwm.hpp"
|
#include "utils/bspwm.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -39,7 +40,7 @@ namespace modules {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit bspwm_module(const bar_settings&, string);
|
explicit bspwm_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
bool has_event();
|
bool has_event();
|
||||||
@ -47,7 +48,7 @@ namespace modules {
|
|||||||
string get_output();
|
string get_output();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/bspwm";
|
static constexpr auto TYPE = BSPWM_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_FOCUS = "focus";
|
static constexpr auto EVENT_FOCUS = "focus";
|
||||||
static constexpr auto EVENT_NEXT = "next";
|
static constexpr auto EVENT_NEXT = "next";
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
class counter_module : public timer_module<counter_module> {
|
class counter_module : public timer_module<counter_module> {
|
||||||
public:
|
public:
|
||||||
explicit counter_module(const bar_settings&, string);
|
explicit counter_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/counter";
|
static constexpr auto TYPE = COUNTER_TYPE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr auto TAG_COUNTER = "<counter>";
|
static constexpr auto TAG_COUNTER = "<counter>";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -20,13 +21,13 @@ namespace modules {
|
|||||||
|
|
||||||
class cpu_module : public timer_module<cpu_module> {
|
class cpu_module : public timer_module<cpu_module> {
|
||||||
public:
|
public:
|
||||||
explicit cpu_module(const bar_settings&, string);
|
explicit cpu_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/cpu";
|
static constexpr auto TYPE = CPU_TYPE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool read_values();
|
bool read_values();
|
||||||
|
@ -6,18 +6,19 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
class date_module : public timer_module<date_module> {
|
class date_module : public timer_module<date_module> {
|
||||||
public:
|
public:
|
||||||
explicit date_module(const bar_settings&, string);
|
explicit date_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/date";
|
static constexpr auto TYPE = DATE_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_TOGGLE = "toggle";
|
static constexpr auto EVENT_TOGGLE = "toggle";
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <dwmipcpp/connection.hpp>
|
#include <dwmipcpp/connection.hpp>
|
||||||
|
|
||||||
#include "modules/meta/event_module.hpp"
|
#include "modules/meta/event_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ namespace modules {
|
|||||||
label_t label;
|
label_t label;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/dwm";
|
static constexpr auto TYPE = DWM_TYPE;
|
||||||
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
bool has_event();
|
bool has_event();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "components/config.hpp"
|
#include "components/config.hpp"
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -35,14 +36,14 @@ namespace modules {
|
|||||||
*/
|
*/
|
||||||
class fs_module : public timer_module<fs_module> {
|
class fs_module : public timer_module<fs_module> {
|
||||||
public:
|
public:
|
||||||
explicit fs_module(const bar_settings&, string);
|
explicit fs_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
string get_output();
|
string get_output();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/fs";
|
static constexpr auto TYPE = FS_TYPE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr auto FORMAT_MOUNTED = "format-mounted";
|
static constexpr auto FORMAT_MOUNTED = "format-mounted";
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "utils/http.hpp"
|
#include "utils/http.hpp"
|
||||||
|
|
||||||
@ -14,13 +15,13 @@ namespace modules {
|
|||||||
*/
|
*/
|
||||||
class github_module : public timer_module<github_module> {
|
class github_module : public timer_module<github_module> {
|
||||||
public:
|
public:
|
||||||
explicit github_module(const bar_settings&, string);
|
explicit github_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/github";
|
static constexpr auto TYPE = GITHUB_TYPE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_label(int);
|
void update_label(int);
|
||||||
@ -35,7 +36,7 @@ namespace modules {
|
|||||||
string m_api_url;
|
string m_api_url;
|
||||||
string m_user;
|
string m_user;
|
||||||
string m_accesstoken{};
|
string m_accesstoken{};
|
||||||
unique_ptr<http_downloader> m_http{};
|
http_downloader m_http{};
|
||||||
bool m_empty_notifications{false};
|
bool m_empty_notifications{false};
|
||||||
std::atomic<bool> m_offline{false};
|
std::atomic<bool> m_offline{false};
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "components/config.hpp"
|
#include "components/config.hpp"
|
||||||
#include "modules/meta/event_module.hpp"
|
#include "modules/meta/event_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "utils/i3.hpp"
|
#include "utils/i3.hpp"
|
||||||
#include "utils/io.hpp"
|
#include "utils/io.hpp"
|
||||||
|
|
||||||
@ -44,14 +45,14 @@ namespace modules {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit i3_module(const bar_settings&, string);
|
explicit i3_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
bool has_event();
|
bool has_event();
|
||||||
bool update();
|
bool update();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/i3";
|
static constexpr auto TYPE = I3_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_FOCUS = "focus";
|
static constexpr auto EVENT_FOCUS = "focus";
|
||||||
static constexpr auto EVENT_NEXT = "next";
|
static constexpr auto EVENT_NEXT = "next";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/static_module.hpp"
|
#include "modules/meta/static_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "utils/command.hpp"
|
#include "utils/command.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -24,15 +25,16 @@ namespace modules {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ipc_module(const bar_settings&, string);
|
explicit ipc_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void start() override;
|
void start() override;
|
||||||
void update();
|
void update();
|
||||||
string get_output();
|
string get_output();
|
||||||
|
string get_format() const;
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
void on_message(const string& message);
|
void on_message(const string& message);
|
||||||
|
|
||||||
static constexpr auto TYPE = "custom/ipc";
|
static constexpr auto TYPE = IPC_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_SEND = "send";
|
static constexpr auto EVENT_SEND = "send";
|
||||||
static constexpr auto EVENT_HOOK = "hook";
|
static constexpr auto EVENT_HOOK = "hook";
|
||||||
@ -53,16 +55,21 @@ namespace modules {
|
|||||||
bool has_hook() const;
|
bool has_hook() const;
|
||||||
|
|
||||||
void set_hook(int h);
|
void set_hook(int h);
|
||||||
|
void update_output() ;
|
||||||
private:
|
private:
|
||||||
static constexpr const char* TAG_OUTPUT{"<output>"};
|
static constexpr auto TAG_OUTPUT = "<output>";
|
||||||
|
static constexpr auto TAG_LABEL = "<label>";
|
||||||
|
|
||||||
|
label_t m_label;
|
||||||
|
|
||||||
vector<unique_ptr<hook>> m_hooks;
|
vector<unique_ptr<hook>> m_hooks;
|
||||||
map<mousebtn, string> m_actions;
|
map<mousebtn, string> m_actions;
|
||||||
string m_output;
|
string m_output;
|
||||||
|
|
||||||
int m_initial{-1};
|
int m_initial{-1};
|
||||||
int m_current_hook{-1};
|
int m_current_hook{-1};
|
||||||
void exec_hook();
|
void exec_hook();
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -10,13 +11,13 @@ namespace modules {
|
|||||||
enum class memory_state { NORMAL = 0, WARN };
|
enum class memory_state { NORMAL = 0, WARN };
|
||||||
class memory_module : public timer_module<memory_module> {
|
class memory_module : public timer_module<memory_module> {
|
||||||
public:
|
public:
|
||||||
explicit memory_module(const bar_settings&, string);
|
explicit memory_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/memory";
|
static constexpr auto TYPE = MEMORY_TYPE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const char* TAG_LABEL{"<label>"};
|
static constexpr const char* TAG_LABEL{"<label>"};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/static_module.hpp"
|
#include "modules/meta/static_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
@ -17,12 +18,12 @@ namespace modules {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit menu_module(const bar_settings&, string);
|
explicit menu_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
void update() {}
|
void update() {}
|
||||||
|
|
||||||
static constexpr auto TYPE = "custom/menu";
|
static constexpr auto TYPE = MENU_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_OPEN = "open";
|
static constexpr auto EVENT_OPEN = "open";
|
||||||
static constexpr auto EVENT_CLOSE = "close";
|
static constexpr auto EVENT_CLOSE = "close";
|
||||||
|
48
include/modules/meta/all.hpp
Normal file
48
include/modules/meta/all.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header file to include the headers for all modules.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/backlight.hpp"
|
||||||
|
#include "modules/battery.hpp"
|
||||||
|
#include "modules/bspwm.hpp"
|
||||||
|
#include "modules/counter.hpp"
|
||||||
|
#include "modules/cpu.hpp"
|
||||||
|
#include "modules/date.hpp"
|
||||||
|
#include "modules/fs.hpp"
|
||||||
|
#include "modules/ipc.hpp"
|
||||||
|
#include "modules/memory.hpp"
|
||||||
|
#include "modules/menu.hpp"
|
||||||
|
#include "modules/meta/base.hpp"
|
||||||
|
#include "modules/script.hpp"
|
||||||
|
#include "modules/temperature.hpp"
|
||||||
|
#include "modules/text.hpp"
|
||||||
|
#include "modules/tray.hpp"
|
||||||
|
#include "modules/xbacklight.hpp"
|
||||||
|
#include "modules/xwindow.hpp"
|
||||||
|
#include "modules/xworkspaces.hpp"
|
||||||
|
#if ENABLE_I3
|
||||||
|
#include "modules/i3.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_DWM
|
||||||
|
#include "modules/dwm.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_MPD
|
||||||
|
#include "modules/mpd.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_NETWORK
|
||||||
|
#include "modules/network.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_ALSA
|
||||||
|
#include "modules/alsa.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_PULSEAUDIO
|
||||||
|
#include "modules/pulseaudio.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_CURL
|
||||||
|
#include "modules/github.hpp"
|
||||||
|
#endif
|
||||||
|
#if ENABLE_XKEYBOARD
|
||||||
|
#include "modules/xkeyboard.hpp"
|
||||||
|
#endif
|
@ -8,6 +8,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "components/config.hpp"
|
||||||
#include "components/types.hpp"
|
#include "components/types.hpp"
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include "utils/concurrency.hpp"
|
#include "utils/concurrency.hpp"
|
||||||
@ -58,7 +59,6 @@ namespace modules {
|
|||||||
|
|
||||||
struct module_format {
|
struct module_format {
|
||||||
string value{};
|
string value{};
|
||||||
vector<string> tags{};
|
|
||||||
label_t prefix{};
|
label_t prefix{};
|
||||||
label_t suffix{};
|
label_t suffix{};
|
||||||
rgba fg{};
|
rgba fg{};
|
||||||
@ -142,7 +142,7 @@ namespace modules {
|
|||||||
template <class Impl>
|
template <class Impl>
|
||||||
class module : public module_interface {
|
class module : public module_interface {
|
||||||
public:
|
public:
|
||||||
module(const bar_settings& bar, string name);
|
module(const bar_settings& bar, string name, const config&);
|
||||||
~module() noexcept;
|
~module() noexcept;
|
||||||
|
|
||||||
static constexpr auto EVENT_MODULE_TOGGLE = "module_toggle";
|
static constexpr auto EVENT_MODULE_TOGGLE = "module_toggle";
|
||||||
@ -189,7 +189,7 @@ namespace modules {
|
|||||||
string get_format() const;
|
string get_format() const;
|
||||||
string get_output();
|
string get_output();
|
||||||
|
|
||||||
void set_visible(bool value);
|
virtual void set_visible(bool value);
|
||||||
|
|
||||||
void action_module_toggle();
|
void action_module_toggle();
|
||||||
void action_module_show();
|
void action_module_show();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "components/builder.hpp"
|
#include "components/builder.hpp"
|
||||||
#include "components/config.hpp"
|
|
||||||
#include "components/logger.hpp"
|
#include "components/logger.hpp"
|
||||||
#include "events/signal.hpp"
|
#include "events/signal.hpp"
|
||||||
#include "events/signal_emitter.hpp"
|
#include "events/signal_emitter.hpp"
|
||||||
@ -15,11 +15,11 @@ namespace modules {
|
|||||||
// module<Impl> public {{{
|
// module<Impl> public {{{
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
module<Impl>::module(const bar_settings& bar, string name)
|
module<Impl>::module(const bar_settings& bar, string name, const config& conf)
|
||||||
: m_sig(signal_emitter::make())
|
: m_sig(signal_emitter::make())
|
||||||
, m_bar(bar)
|
, m_bar(bar)
|
||||||
, m_log(logger::make())
|
, m_log(logger::make())
|
||||||
, m_conf(config::make())
|
, m_conf(conf)
|
||||||
, m_router(make_unique<action_router>())
|
, m_router(make_unique<action_router>())
|
||||||
, m_name("module/" + name)
|
, m_name("module/" + name)
|
||||||
, m_name_raw(name)
|
, m_name_raw(name)
|
||||||
|
@ -1,117 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "modules/backlight.hpp"
|
#include "components/logger.hpp"
|
||||||
#include "modules/battery.hpp"
|
#include "components/types.hpp"
|
||||||
#include "modules/bspwm.hpp"
|
|
||||||
#include "modules/counter.hpp"
|
|
||||||
#include "modules/cpu.hpp"
|
|
||||||
#include "modules/date.hpp"
|
|
||||||
#include "modules/fs.hpp"
|
|
||||||
#include "modules/ipc.hpp"
|
|
||||||
#include "modules/memory.hpp"
|
|
||||||
#include "modules/menu.hpp"
|
|
||||||
#include "modules/meta/base.hpp"
|
#include "modules/meta/base.hpp"
|
||||||
#include "modules/script.hpp"
|
|
||||||
#if DEBUG
|
|
||||||
#include "modules/systray.hpp"
|
|
||||||
#endif
|
|
||||||
#include "modules/temperature.hpp"
|
|
||||||
#include "modules/text.hpp"
|
|
||||||
#include "modules/xbacklight.hpp"
|
|
||||||
#include "modules/xwindow.hpp"
|
|
||||||
#include "modules/xworkspaces.hpp"
|
|
||||||
#if ENABLE_I3
|
|
||||||
#include "modules/i3.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_DWM
|
|
||||||
#include "modules/dwm.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_MPD
|
|
||||||
#include "modules/mpd.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_NETWORK
|
|
||||||
#include "modules/network.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_ALSA
|
|
||||||
#include "modules/alsa.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_PULSEAUDIO
|
|
||||||
#include "modules/pulseaudio.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_CURL
|
|
||||||
#include "modules/github.hpp"
|
|
||||||
#endif
|
|
||||||
#if ENABLE_XKEYBOARD
|
|
||||||
#include "modules/xkeyboard.hpp"
|
|
||||||
#endif
|
|
||||||
#include "modules/unsupported.hpp"
|
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
using namespace modules;
|
namespace modules {
|
||||||
|
using module_t = shared_ptr<module_interface>;
|
||||||
|
|
||||||
namespace {
|
/**
|
||||||
module_interface* make_module(string&& name, const bar_settings& bar, string module_name, const logger& m_log) {
|
* Creates a new module instance.
|
||||||
if (name == counter_module::TYPE) {
|
*
|
||||||
return new counter_module(bar, move(module_name));
|
* @param type The type of the module (as given by each module's TYPE field)
|
||||||
} else if (name == backlight_module::TYPE) {
|
* @param bar An instance of the @ref bar_settings
|
||||||
return new backlight_module(bar, move(module_name));
|
* @param module_name The user-specified module name
|
||||||
} else if (name == battery_module::TYPE) {
|
* @param log A @ref logger instance
|
||||||
return new battery_module(bar, move(module_name));
|
* @param config A @ref config instance
|
||||||
} else if (name == bspwm_module::TYPE) {
|
*/
|
||||||
return new bspwm_module(bar, move(module_name));
|
module_t make_module(string&& type, const bar_settings& bar, string module_name, const logger& log, const config& config);
|
||||||
} else if (name == cpu_module::TYPE) {
|
} // namespace modules
|
||||||
return new cpu_module(bar, move(module_name));
|
|
||||||
} else if (name == date_module::TYPE) {
|
|
||||||
return new date_module(bar, move(module_name));
|
|
||||||
} else if (name == dwm_module::TYPE) {
|
|
||||||
return new dwm_module(bar, move(module_name));
|
|
||||||
} else if (name == github_module::TYPE) {
|
|
||||||
return new github_module(bar, move(module_name));
|
|
||||||
} else if (name == fs_module::TYPE) {
|
|
||||||
return new fs_module(bar, move(module_name));
|
|
||||||
} else if (name == memory_module::TYPE) {
|
|
||||||
return new memory_module(bar, move(module_name));
|
|
||||||
} else if (name == i3_module::TYPE) {
|
|
||||||
return new i3_module(bar, move(module_name));
|
|
||||||
} else if (name == mpd_module::TYPE) {
|
|
||||||
return new mpd_module(bar, move(module_name));
|
|
||||||
} else if (name == "internal/volume") {
|
|
||||||
m_log.warn("internal/volume is deprecated, use %s instead", string(alsa_module::TYPE));
|
|
||||||
return new alsa_module(bar, move(module_name));
|
|
||||||
} else if (name == alsa_module::TYPE) {
|
|
||||||
return new alsa_module(bar, move(module_name));
|
|
||||||
} else if (name == pulseaudio_module::TYPE) {
|
|
||||||
return new pulseaudio_module(bar, move(module_name));
|
|
||||||
} else if (name == network_module::TYPE) {
|
|
||||||
return new network_module(bar, move(module_name));
|
|
||||||
#if DEBUG
|
|
||||||
} else if (name == systray_module::TYPE) {
|
|
||||||
return new systray_module(bar, move(module_name));
|
|
||||||
#endif
|
|
||||||
} else if (name == temperature_module::TYPE) {
|
|
||||||
return new temperature_module(bar, move(module_name));
|
|
||||||
} else if (name == xbacklight_module::TYPE) {
|
|
||||||
return new xbacklight_module(bar, move(module_name));
|
|
||||||
} else if (name == xkeyboard_module::TYPE) {
|
|
||||||
return new xkeyboard_module(bar, move(module_name));
|
|
||||||
} else if (name == xwindow_module::TYPE) {
|
|
||||||
return new xwindow_module(bar, move(module_name));
|
|
||||||
} else if (name == xworkspaces_module::TYPE) {
|
|
||||||
return new xworkspaces_module(bar, move(module_name));
|
|
||||||
} else if (name == text_module::TYPE) {
|
|
||||||
return new text_module(bar, move(module_name));
|
|
||||||
} else if (name == script_module::TYPE) {
|
|
||||||
return new script_module(bar, move(module_name));
|
|
||||||
} else if (name == menu_module::TYPE) {
|
|
||||||
return new menu_module(bar, move(module_name));
|
|
||||||
} else if (name == ipc_module::TYPE) {
|
|
||||||
return new ipc_module(bar, move(module_name));
|
|
||||||
} else {
|
|
||||||
throw application_error("Unknown module: " + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -22,7 +22,7 @@ namespace modules {
|
|||||||
try {
|
try {
|
||||||
// Warm up module output before entering the loop
|
// Warm up module output before entering the loop
|
||||||
std::unique_lock<std::mutex> guard(this->m_updatelock);
|
std::unique_lock<std::mutex> guard(this->m_updatelock);
|
||||||
CAST_MOD(Impl)->on_event(nullptr);
|
CAST_MOD(Impl)->on_event({});
|
||||||
CAST_MOD(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
guard.unlock();
|
guard.unlock();
|
||||||
|
|
||||||
@ -47,15 +47,14 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void poll_events() {
|
void poll_events() {
|
||||||
vector<unique_ptr<inotify_watch>> watches;
|
vector<inotify_watch> watches;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (auto&& w : m_watchlist) {
|
for (auto&& w : m_watchlist) {
|
||||||
watches.emplace_back(inotify_util::make_watch(w.first));
|
watches.emplace_back(w.first);
|
||||||
watches.back()->attach(w.second);
|
watches.back().attach(w.second);
|
||||||
}
|
}
|
||||||
} catch (const system_error& e) {
|
} catch (const system_error& e) {
|
||||||
watches.clear();
|
|
||||||
this->m_log.err("%s: Error while creating inotify watch (what: %s)", this->name(), e.what());
|
this->m_log.err("%s: Error while creating inotify watch (what: %s)", this->name(), e.what());
|
||||||
CAST_MOD(Impl)->sleep(0.1s);
|
CAST_MOD(Impl)->sleep(0.1s);
|
||||||
return;
|
return;
|
||||||
@ -63,24 +62,20 @@ namespace modules {
|
|||||||
|
|
||||||
while (this->running()) {
|
while (this->running()) {
|
||||||
for (auto&& w : watches) {
|
for (auto&& w : watches) {
|
||||||
this->m_log.trace_x("%s: Poll inotify watch %s", this->name(), w->path());
|
this->m_log.trace_x("%s: Poll inotify watch %s", this->name(), w.path());
|
||||||
|
|
||||||
if (w->poll(1000 / watches.size())) {
|
if (w.poll(1000 / watches.size())) {
|
||||||
auto event = w->get_event();
|
auto event = w.get_event();
|
||||||
|
if (CAST_MOD(Impl)->on_event(event)) {
|
||||||
for (auto&& w : watches) {
|
|
||||||
w->remove(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CAST_MOD(Impl)->on_event(event.get())) {
|
|
||||||
CAST_MOD(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
}
|
}
|
||||||
CAST_MOD(Impl)->idle();
|
CAST_MOD(Impl)->idle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->running())
|
if (!this->running()) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CAST_MOD(Impl)->idle();
|
CAST_MOD(Impl)->idle();
|
||||||
}
|
}
|
||||||
@ -89,6 +84,6 @@ namespace modules {
|
|||||||
private:
|
private:
|
||||||
map<string, int> m_watchlist;
|
map<string, int> m_watchlist;
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
38
include/modules/meta/types.hpp
Normal file
38
include/modules/meta/types.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace modules {
|
||||||
|
|
||||||
|
static constexpr const char ALSA_TYPE[] = "internal/alsa";
|
||||||
|
static constexpr const char BACKLIGHT_TYPE[] = "internal/backlight";
|
||||||
|
static constexpr const char BATTERY_TYPE[] = "internal/battery";
|
||||||
|
static constexpr const char BSPWM_TYPE[] = "internal/bspwm";
|
||||||
|
static constexpr const char COUNTER_TYPE[] = "internal/counter";
|
||||||
|
static constexpr const char CPU_TYPE[] = "internal/cpu";
|
||||||
|
static constexpr const char DATE_TYPE[] = "internal/date";
|
||||||
|
static constexpr const char FS_TYPE[] = "internal/fs";
|
||||||
|
static constexpr const char GITHUB_TYPE[] = "internal/github";
|
||||||
|
static constexpr const char I3_TYPE[] = "internal/i3";
|
||||||
|
static constexpr const char DWM_TYPE[] = "internal/dwm";
|
||||||
|
static constexpr const char MEMORY_TYPE[] = "internal/memory";
|
||||||
|
static constexpr const char MPD_TYPE[] = "internal/mpd";
|
||||||
|
static constexpr const char NETWORK_TYPE[] = "internal/network";
|
||||||
|
static constexpr const char PULSEAUDIO_TYPE[] = "internal/pulseaudio";
|
||||||
|
static constexpr const char TEMPERATURE_TYPE[] = "internal/temperature";
|
||||||
|
static constexpr const char TRAY_TYPE[] = "internal/tray";
|
||||||
|
static constexpr const char XBACKLIGHT_TYPE[] = "internal/xbacklight";
|
||||||
|
static constexpr const char XKEYBOARD_TYPE[] = "internal/xkeyboard";
|
||||||
|
static constexpr const char XWINDOW_TYPE[] = "internal/xwindow";
|
||||||
|
static constexpr const char XWORKSPACES_TYPE[] = "internal/xworkspaces";
|
||||||
|
|
||||||
|
static constexpr const char IPC_TYPE[] = "custom/ipc";
|
||||||
|
static constexpr const char MENU_TYPE[] = "custom/menu";
|
||||||
|
static constexpr const char SCRIPT_TYPE[] = "custom/script";
|
||||||
|
static constexpr const char TEXT_TYPE[] = "custom/text";
|
||||||
|
|
||||||
|
} // namespace modules
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "adapters/mpd.hpp"
|
#include "adapters/mpd.hpp"
|
||||||
#include "modules/meta/event_module.hpp"
|
#include "modules/meta/event_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "utils/env.hpp"
|
#include "utils/env.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -13,7 +14,7 @@ using namespace mpd;
|
|||||||
namespace modules {
|
namespace modules {
|
||||||
class mpd_module : public event_module<mpd_module> {
|
class mpd_module : public event_module<mpd_module> {
|
||||||
public:
|
public:
|
||||||
explicit mpd_module(const bar_settings&, string);
|
explicit mpd_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void teardown();
|
void teardown();
|
||||||
inline bool connected() const;
|
inline bool connected() const;
|
||||||
@ -24,7 +25,7 @@ namespace modules {
|
|||||||
string get_output();
|
string get_output();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/mpd";
|
static constexpr auto TYPE = MPD_TYPE;
|
||||||
|
|
||||||
static constexpr const char* EVENT_PLAY = "play";
|
static constexpr const char* EVENT_PLAY = "play";
|
||||||
static constexpr const char* EVENT_PAUSE = "pause";
|
static constexpr const char* EVENT_PAUSE = "pause";
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "adapters/net.hpp"
|
#include "adapters/net.hpp"
|
||||||
#include "components/config.hpp"
|
#include "components/config.hpp"
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
@ -11,14 +12,14 @@ namespace modules {
|
|||||||
|
|
||||||
class network_module : public timer_module<network_module> {
|
class network_module : public timer_module<network_module> {
|
||||||
public:
|
public:
|
||||||
explicit network_module(const bar_settings&, string);
|
explicit network_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void teardown();
|
void teardown();
|
||||||
bool update();
|
bool update();
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/network";
|
static constexpr auto TYPE = NETWORK_TYPE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void subthread_routine();
|
void subthread_routine();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/event_module.hpp"
|
#include "modules/meta/event_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -13,7 +14,7 @@ namespace modules {
|
|||||||
|
|
||||||
class pulseaudio_module : public event_module<pulseaudio_module> {
|
class pulseaudio_module : public event_module<pulseaudio_module> {
|
||||||
public:
|
public:
|
||||||
explicit pulseaudio_module(const bar_settings&, string);
|
explicit pulseaudio_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void teardown();
|
void teardown();
|
||||||
bool has_event();
|
bool has_event();
|
||||||
@ -22,7 +23,7 @@ namespace modules {
|
|||||||
string get_output();
|
string get_output();
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/pulseaudio";
|
static constexpr auto TYPE = PULSEAUDIO_TYPE;
|
||||||
|
|
||||||
static constexpr auto EVENT_INC = "inc";
|
static constexpr auto EVENT_INC = "inc";
|
||||||
static constexpr auto EVENT_DEC = "dec";
|
static constexpr auto EVENT_DEC = "dec";
|
||||||
@ -53,6 +54,7 @@ namespace modules {
|
|||||||
atomic<bool> m_muted{false};
|
atomic<bool> m_muted{false};
|
||||||
atomic<int> m_volume{0};
|
atomic<int> m_volume{0};
|
||||||
atomic<double> m_decibels{0};
|
atomic<double> m_decibels{0};
|
||||||
|
atomic<bool> m_reverse_scroll{false};
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "adapters/script_runner.hpp"
|
#include "adapters/script_runner.hpp"
|
||||||
#include "modules/meta/base.hpp"
|
#include "modules/meta/base.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "utils/command.hpp"
|
#include "utils/command.hpp"
|
||||||
#include "utils/io.hpp"
|
#include "utils/io.hpp"
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ POLYBAR_NS
|
|||||||
namespace modules {
|
namespace modules {
|
||||||
class script_module : public module<script_module> {
|
class script_module : public module<script_module> {
|
||||||
public:
|
public:
|
||||||
explicit script_module(const bar_settings&, string);
|
explicit script_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void start() override;
|
void start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
@ -20,7 +21,7 @@ namespace modules {
|
|||||||
|
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "custom/script";
|
static constexpr auto TYPE = SCRIPT_TYPE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool check_condition();
|
bool check_condition();
|
||||||
@ -33,7 +34,9 @@ namespace modules {
|
|||||||
static constexpr auto FORMAT_FAIL = "format-fail";
|
static constexpr auto FORMAT_FAIL = "format-fail";
|
||||||
|
|
||||||
const bool m_tail;
|
const bool m_tail;
|
||||||
const script_runner::interval m_interval{0};
|
const script_runner::interval m_interval_success{0};
|
||||||
|
const script_runner::interval m_interval_fail{0};
|
||||||
|
const script_runner::interval m_interval_if{0};
|
||||||
|
|
||||||
script_runner m_runner;
|
script_runner m_runner;
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
#if DEBUG
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "modules/meta/static_module.hpp"
|
|
||||||
|
|
||||||
POLYBAR_NS
|
|
||||||
|
|
||||||
class connection;
|
|
||||||
|
|
||||||
namespace modules {
|
|
||||||
/**
|
|
||||||
* Module used to display information about the
|
|
||||||
* currently active X window.
|
|
||||||
*/
|
|
||||||
class systray_module : public static_module<systray_module> {
|
|
||||||
public:
|
|
||||||
explicit systray_module(const bar_settings&, string);
|
|
||||||
|
|
||||||
void update();
|
|
||||||
bool build(builder* builder, const string& tag) const;
|
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/systray";
|
|
||||||
|
|
||||||
static constexpr auto EVENT_TOGGLE = "toggle";
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void action_toggle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static constexpr const char* TAG_LABEL_TOGGLE{"<label-toggle>"};
|
|
||||||
static constexpr const char* TAG_TRAY_CLIENTS{"<tray-clients>"};
|
|
||||||
|
|
||||||
connection& m_connection;
|
|
||||||
label_t m_label;
|
|
||||||
|
|
||||||
bool m_hidden{false};
|
|
||||||
};
|
|
||||||
} // namespace modules
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
|
||||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||||||
#include <istream>
|
#include <istream>
|
||||||
|
|
||||||
#include "modules/meta/timer_module.hpp"
|
#include "modules/meta/timer_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -12,13 +13,13 @@ namespace modules {
|
|||||||
|
|
||||||
class temperature_module : public timer_module<temperature_module> {
|
class temperature_module : public timer_module<temperature_module> {
|
||||||
public:
|
public:
|
||||||
explicit temperature_module(const bar_settings&, string);
|
explicit temperature_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
bool build(builder* builder, const string& tag) const;
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "internal/temperature";
|
static constexpr auto TYPE = TEMPERATURE_TYPE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr auto TAG_LABEL = "<label>";
|
static constexpr auto TAG_LABEL = "<label>";
|
||||||
@ -30,6 +31,7 @@ namespace modules {
|
|||||||
ramp_t m_ramp;
|
ramp_t m_ramp;
|
||||||
|
|
||||||
string m_path;
|
string m_path;
|
||||||
|
string m_zone_type;
|
||||||
int m_zone = 0;
|
int m_zone = 0;
|
||||||
// Base temperature used for where to start the ramp
|
// Base temperature used for where to start the ramp
|
||||||
int m_tempbase = 0;
|
int m_tempbase = 0;
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "modules/meta/static_module.hpp"
|
#include "modules/meta/static_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
class text_module : public static_module<text_module> {
|
class text_module : public static_module<text_module> {
|
||||||
public:
|
public:
|
||||||
explicit text_module(const bar_settings&, string);
|
explicit text_module(const bar_settings&, string, const config&);
|
||||||
|
|
||||||
void update() {}
|
void update() {}
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
string get_output();
|
string get_output();
|
||||||
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
|
||||||
static constexpr auto TYPE = "custom/text";
|
static constexpr auto TYPE = TEXT_TYPE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr const char* TAG_LABEL{"<label>"};
|
||||||
|
|
||||||
|
label_t m_label;
|
||||||
|
|
||||||
|
string m_format{DEFAULT_FORMAT};
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
39
include/modules/tray.hpp
Normal file
39
include/modules/tray.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "components/bar.hpp"
|
||||||
|
#include "modules/meta/static_module.hpp"
|
||||||
|
#include "modules/meta/types.hpp"
|
||||||
|
#include "x11/tray_manager.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
namespace modules {
|
||||||
|
/**
|
||||||
|
* Wraps the tray_manager in a module.
|
||||||
|
*
|
||||||
|
* The module produces the `%{Pt}` formatting tag, which is used by the renderer
|
||||||
|
* to place the tray.
|
||||||
|
* The visibility of the tray icons is directly tied to the visibility of the
|
||||||
|
* module.
|
||||||
|
*/
|
||||||
|
class tray_module : public static_module<tray_module> {
|
||||||
|
public:
|
||||||
|
explicit tray_module(const bar_settings& bar_settings, string name_, const config&);
|
||||||
|
string get_format() const;
|
||||||
|
|
||||||
|
void set_visible(bool value) override;
|
||||||
|
|
||||||
|
void start() override;
|
||||||
|
|
||||||
|
bool build(builder* builder, const string& tag) const;
|
||||||
|
void update() {}
|
||||||
|
|
||||||
|
static constexpr auto TYPE = TRAY_TYPE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr const char* TAG_TRAY{"<tray>"};
|
||||||
|
|
||||||
|
tray::manager m_tray;
|
||||||
|
};
|
||||||
|
} // namespace modules
|
||||||
|
POLYBAR_NS_END
|
@ -1,71 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "modules/meta/base.hpp"
|
|
||||||
#include "modules/meta/base.inl"
|
|
||||||
|
|
||||||
POLYBAR_NS
|
|
||||||
|
|
||||||
namespace modules {
|
|
||||||
struct module_interface;
|
|
||||||
|
|
||||||
#define DEFINE_UNSUPPORTED_MODULE(MODULE_NAME, MODULE_TYPE) \
|
|
||||||
class MODULE_NAME : public module_interface { \
|
|
||||||
public: \
|
|
||||||
MODULE_NAME(const bar_settings, string) { \
|
|
||||||
throw application_error("No built-in support for '" + string{MODULE_TYPE} + "'"); \
|
|
||||||
} \
|
|
||||||
static constexpr auto TYPE = MODULE_TYPE; \
|
|
||||||
string type() const override { \
|
|
||||||
return ""; \
|
|
||||||
} \
|
|
||||||
string name_raw() const override { \
|
|
||||||
return ""; \
|
|
||||||
} \
|
|
||||||
string name() const override { \
|
|
||||||
return ""; \
|
|
||||||
} \
|
|
||||||
bool running() const override { \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
bool visible() const override { \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
void start() override {} \
|
|
||||||
void stop() override {} \
|
|
||||||
void join() override {} \
|
|
||||||
void halt(string) override {} \
|
|
||||||
string contents() override { \
|
|
||||||
return ""; \
|
|
||||||
} \
|
|
||||||
bool input(const string&, const string&) override { \
|
|
||||||
return false; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if not ENABLE_I3
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(i3_module, "internal/i3");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_DWM
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(dwm_module, "internal/dwm");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_MPD
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(mpd_module, "internal/mpd");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_NETWORK
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(network_module, "internal/network");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_ALSA
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(alsa_module, "internal/alsa");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_PULSEAUDIO
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(pulseaudio_module, "internal/pulseaudio");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_CURL
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(github_module, "internal/github");
|
|
||||||
#endif
|
|
||||||
#if not ENABLE_XKEYBOARD
|
|
||||||
DEFINE_UNSUPPORTED_MODULE(xkeyboard_module, "internal/xkeyboard");
|
|
||||||
#endif
|
|
||||||
} // namespace modules
|
|
||||||
|
|
||||||
POLYBAR_NS_END
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user