Merge branch 'hotfix/3.5.1'
This commit is contained in:
commit
1c554dd0e0
98
.github/workflows/ci.yml
vendored
Normal file
98
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
ref:
|
||||||
|
description: 'ref'
|
||||||
|
required: false
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docs:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
COLOR: "ON"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.inputs.ref }}
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: sudo apt-get install -y python3-sphinx
|
||||||
|
- name: Build Documentation
|
||||||
|
run: |
|
||||||
|
mkdir -p doc/build
|
||||||
|
cd doc/build
|
||||||
|
cmake ..
|
||||||
|
make doc
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
cxx: [g++, clang++]
|
||||||
|
polybar_build_type: ["full"]
|
||||||
|
build_type: ["Release"]
|
||||||
|
include:
|
||||||
|
- cxx: g++
|
||||||
|
polybar_build_type: "tests"
|
||||||
|
build_type: "Coverage"
|
||||||
|
- cxx: g++
|
||||||
|
polybar_build_type: "minimal"
|
||||||
|
build_type: "Release"
|
||||||
|
env:
|
||||||
|
CXX: ${{ matrix.cxx }}
|
||||||
|
BUILD_TYPE: ${{ matrix.build_type }}
|
||||||
|
POLYBAR_BUILD_TYPE: ${{ matrix.polybar_build_type }}
|
||||||
|
POLYBAR_DIR: ${{ github.workspace }}
|
||||||
|
BUILD_DIR: "${{ github.workspace}}/build"
|
||||||
|
MAKEFLAGS: "-j4"
|
||||||
|
COLOR: "ON"
|
||||||
|
steps:
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y \
|
||||||
|
libxcb-composite0-dev \
|
||||||
|
libxcb-ewmh-dev \
|
||||||
|
libxcb-icccm4-dev \
|
||||||
|
libxcb-image0-dev \
|
||||||
|
libxcb-randr0-dev \
|
||||||
|
libxcb-util0-dev \
|
||||||
|
libxcb1-dev \
|
||||||
|
libcairo2-dev \
|
||||||
|
python3-xcbgen \
|
||||||
|
xcb-proto
|
||||||
|
|
||||||
|
if [ "$POLYBAR_BUILD_TYPE" != "minimal" ]; then
|
||||||
|
sudo apt-get install -y \
|
||||||
|
libxcb-xkb-dev \
|
||||||
|
libxcb-cursor-dev \
|
||||||
|
libxcb-xrm-dev \
|
||||||
|
i3-wm \
|
||||||
|
libcurl4-openssl-dev \
|
||||||
|
libjsoncpp-dev \
|
||||||
|
libasound2-dev \
|
||||||
|
libpulse-dev \
|
||||||
|
libiw-dev \
|
||||||
|
libmpdclient-dev
|
||||||
|
fi
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
ref: ${{ github.event.inputs.ref }}
|
||||||
|
- name: Summary
|
||||||
|
run: ./common/ci/summary.sh
|
||||||
|
- name: Configure
|
||||||
|
run: ./common/ci/configure.sh
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd $BUILD_DIR
|
||||||
|
make
|
||||||
|
- name: Tests
|
||||||
|
if: ${{ matrix.polybar_build_type == 'tests' }}
|
||||||
|
run: |
|
||||||
|
cd $BUILD_DIR
|
||||||
|
make check
|
||||||
|
cd $POLYBAR_DIR
|
||||||
|
bash <(curl -s https://codecov.io/bash) -F unittests -a "-ap" -Z
|
109
.travis.yml
109
.travis.yml
@ -1,109 +0,0 @@
|
|||||||
sudo: required
|
|
||||||
dist: focal
|
|
||||||
language: cpp
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- JOBS=4
|
|
||||||
- MAKEFLAGS="-j ${JOBS}"
|
|
||||||
- POLYBAR_BUILD_TYPE="compile"
|
|
||||||
|
|
||||||
# Build configurations can either not specify anything for 'addon' and use this
|
|
||||||
# default list of packages. Or they can pick and choose which package groups to
|
|
||||||
# install
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- &base_deps
|
|
||||||
- libxcb-composite0-dev
|
|
||||||
- libxcb-ewmh-dev
|
|
||||||
- libxcb-icccm4-dev
|
|
||||||
- libxcb-image0-dev
|
|
||||||
- libxcb-randr0-dev
|
|
||||||
- libxcb-util0-dev
|
|
||||||
- python3-xcbgen
|
|
||||||
- xcb-proto
|
|
||||||
- &optional_deps
|
|
||||||
- libxcb-xkb-dev
|
|
||||||
- libxcb-cursor-dev
|
|
||||||
- libxcb-xrm-dev
|
|
||||||
- libxcb1-dev
|
|
||||||
- xutils-dev
|
|
||||||
- i3-wm
|
|
||||||
- libjsoncpp-dev
|
|
||||||
- libasound2-dev
|
|
||||||
- libpulse-dev
|
|
||||||
- libcairo2-dev
|
|
||||||
- libiw-dev
|
|
||||||
- libmpdclient-dev
|
|
||||||
|
|
||||||
script: source ${TRAVIS_BUILD_DIR}/common/travis/build.sh
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# Only builds the documentation
|
|
||||||
- language: generic
|
|
||||||
# Doesn't actually do anything, just used for the indicator on travis
|
|
||||||
compiler: Sphinx
|
|
||||||
addons: {apt: {packages: [python3-sphinx]}}
|
|
||||||
before_script:
|
|
||||||
- mkdir -p doc/build
|
|
||||||
- cd doc/build
|
|
||||||
- cmake ..
|
|
||||||
script: make doc
|
|
||||||
# Disable unnecessary commands
|
|
||||||
cache:
|
|
||||||
|
|
||||||
- compiler: clang
|
|
||||||
env: BUILD_TYPE=Release
|
|
||||||
addons: {apt: {packages: [*base_deps, *optional_deps]}}
|
|
||||||
|
|
||||||
- compiler: gcc
|
|
||||||
env: BUILD_TYPE=Coverage POLYBAR_BUILD_TYPE=tests BUILD_TESTS=ON
|
|
||||||
addons: {apt: {packages: [*base_deps, *optional_deps]}}
|
|
||||||
script: make check
|
|
||||||
after_success:
|
|
||||||
- cd ${TRAVIS_BUILD_DIR}
|
|
||||||
- bash <(curl -s https://codecov.io/bash) -F unittests -a "-ap" -Z || echo "Codecov did not collect coverage reports"
|
|
||||||
|
|
||||||
- compiler: gcc
|
|
||||||
env: BUILD_TYPE=Release
|
|
||||||
addons: {apt: {packages: [*base_deps, *optional_deps]}}
|
|
||||||
|
|
||||||
# Minimal build, contains no optional dependencies. This makes sure that
|
|
||||||
# we properly remove files from compilation that depend on libraries that
|
|
||||||
# are not installed
|
|
||||||
- compiler: gcc
|
|
||||||
env: BUILD_TYPE=Release POLYBAR_BUILD_TYPE=minimal
|
|
||||||
addons: {apt: {packages: [*base_deps]}}
|
|
||||||
|
|
||||||
cache:
|
|
||||||
ccache: true
|
|
||||||
apt: true
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- source ${TRAVIS_BUILD_DIR}/common/travis/summary.sh
|
|
||||||
- source ${TRAVIS_BUILD_DIR}/common/travis/configure.sh
|
|
||||||
|
|
||||||
# Only fetch the newest 5 commits instead of 50
|
|
||||||
git:
|
|
||||||
depth: 5
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
irc:
|
|
||||||
channels:
|
|
||||||
- "irc.freenode.org#polybar"
|
|
||||||
template:
|
|
||||||
- " %{repository_slug}(%{branch})#%{build_number} | \"%{commit_subject}\" by %{author} | Commit #%{commit} %{result}: %{build_url}"
|
|
||||||
use_notice: true
|
|
||||||
on_success: never
|
|
||||||
on_failure: change
|
|
||||||
on_start: never
|
|
||||||
webhooks:
|
|
||||||
urls:
|
|
||||||
# For the https://gitter.im/polybar/polybar gitter room
|
|
||||||
- https://webhooks.gitter.im/e/10bdbe25961312646ace
|
|
||||||
on_success: never
|
|
||||||
on_failure: always
|
|
||||||
on_start: never
|
|
@ -8,8 +8,8 @@ A fast and easy-to-use tool for creating status bars.
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/polybar/polybar/releases"><img src="https://img.shields.io/github/release/polybar/polybar.svg"></a>
|
<a href="https://github.com/polybar/polybar/releases"><img src="https://img.shields.io/github/release/polybar/polybar.svg"></a>
|
||||||
|
<a href="https://github.com/polybar/polybar/actions?query=workflow%3ACI"><img src="https://github.com/polybar/polybar/workflows/CI/badge.svg"></a>
|
||||||
<a href="https://github.com/polybar/polybar/actions?query=workflow%3A%22Release+Workflow%22"><img src="https://github.com/polybar/polybar/workflows/Release%20Workflow/badge.svg?branch=master"></a>
|
<a href="https://github.com/polybar/polybar/actions?query=workflow%3A%22Release+Workflow%22"><img src="https://github.com/polybar/polybar/workflows/Release%20Workflow/badge.svg?branch=master"></a>
|
||||||
<a href="https://travis-ci.com/polybar/polybar"><img src="https://travis-ci.com/polybar/polybar.svg?branch=master"></a>
|
|
||||||
<a href="https://polybar.readthedocs.io"><img src="https://readthedocs.org/projects/polybar/badge/?version=latest"></a>
|
<a href="https://polybar.readthedocs.io"><img src="https://readthedocs.org/projects/polybar/badge/?version=latest"></a>
|
||||||
<a href="https://gitter.im/polybar/polybar"><img src="https://badges.gitter.im/polybar/polybar.svg"></a>
|
<a href="https://gitter.im/polybar/polybar"><img src="https://badges.gitter.im/polybar/polybar.svg"></a>
|
||||||
<a href="https://codecov.io/gh/polybar/polybar/branch/master"><img src="https://codecov.io/gh/polybar/polybar/branch/master/graph/badge.svg"></a>
|
<a href="https://codecov.io/gh/polybar/polybar/branch/master"><img src="https://codecov.io/gh/polybar/polybar/branch/master/graph/badge.svg"></a>
|
||||||
|
46
common/ci/configure.sh
Executable file
46
common/ci/configure.sh
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
if [ -d "$BUILD_DIR" ]; then
|
||||||
|
rm -Rf "$BUILD_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${BUILD_DIR}"
|
||||||
|
cd "${BUILD_DIR}"
|
||||||
|
|
||||||
|
if [ "$POLYBAR_BUILD_TYPE" != "minimal" ]; then
|
||||||
|
ENABLE_PULSEAUDIO=ON
|
||||||
|
ENABLE_NETWORK=ON
|
||||||
|
ENABLE_MPD=ON
|
||||||
|
ENABLE_CURL=ON
|
||||||
|
ENABLE_ALSA=ON
|
||||||
|
ENABLE_I3=ON
|
||||||
|
WITH_XRM=ON
|
||||||
|
WITH_XKB=ON
|
||||||
|
WITH_XRANDR_MONITORS=ON
|
||||||
|
WITH_XCURSOR=ON
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$POLYBAR_BUILD_TYPE" = "tests" ]; then
|
||||||
|
BUILD_TESTS=ON
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake \
|
||||||
|
-DCMAKE_CXX_COMPILER="${CXX}" \
|
||||||
|
-DCMAKE_CXX_FLAGS="${CXXFLAGS} -Werror" \
|
||||||
|
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
||||||
|
-DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \
|
||||||
|
-DBUILD_DOC:BOOL="${BUILD_DOC:-OFF}" \
|
||||||
|
-DWITH_XRANDR=ON \
|
||||||
|
-DENABLE_PULSEAUDIO="${ENABLE_PULSEAUDIO:-OFF}" \
|
||||||
|
-DENABLE_NETWORK="${ENABLE_NETWORK:-OFF}" \
|
||||||
|
-DENABLE_MPD="${ENABLE_MPD:-OFF}" \
|
||||||
|
-DENABLE_CURL="${ENABLE_CURL:-OFF}" \
|
||||||
|
-DENABLE_ALSA="${ENABLE_ALSA:-OFF}" \
|
||||||
|
-DENABLE_I3="${ENABLE_I3:-OFF}" \
|
||||||
|
-DWITH_XRM="${WITH_XRM:-OFF}" \
|
||||||
|
-DWITH_XKB="${WITH_XKB:-OFF}" \
|
||||||
|
-DWITH_XRANDR_MONITORS="${WITH_XRANDR_MONITORS:-OFF}" \
|
||||||
|
-DWITH_XCURSOR="${WITH_XCURSOR:-OFF}" \
|
||||||
|
..
|
19
common/ci/summary.sh
Executable file
19
common/ci/summary.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
"${CXX}" --version
|
||||||
|
cmake --version
|
||||||
|
|
||||||
|
set +x
|
||||||
|
|
||||||
|
echo "PATH=${PATH}"
|
||||||
|
echo "CXX=${CXX}"
|
||||||
|
echo "CXXFLAGS=${CXXFLAGS}"
|
||||||
|
echo "LDFLAGS=${LDFLAGS}"
|
||||||
|
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
|
||||||
|
echo "MAKEFLAGS=${MAKEFLAGS}"
|
||||||
|
echo "POLYBAR_BUILD_TYPE=${POLYBAR_BUILD_TYPE}"
|
||||||
|
echo "CMAKE_BUILD_TYPE=${BUILD_TYPE}"
|
@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
cd "${TRAVIS_BUILD_DIR}/build" || false
|
|
||||||
make || exit $?
|
|
@ -1,32 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
mkdir -p "${TRAVIS_BUILD_DIR}/build"
|
|
||||||
cd "${TRAVIS_BUILD_DIR}/build" || false
|
|
||||||
|
|
||||||
FLAGS=""
|
|
||||||
|
|
||||||
# Disable all extra modules and X extensions for minimal builds
|
|
||||||
# Most of these should already be turned off because their libraries are not
|
|
||||||
# installed, but some may not be
|
|
||||||
if [ "$POLYBAR_BUILD_TYPE" == "minimal" ]; then
|
|
||||||
FLAGS=(
|
|
||||||
"-DENABLE_PULSEAUDIO=OFF"
|
|
||||||
"-DENABLE_NETWORK=OFF"
|
|
||||||
"-DENABLE_MPD=OFF"
|
|
||||||
"-DENABLE_CURL=OFF"
|
|
||||||
"-DENABLE_ALSA=OFF"
|
|
||||||
"-DENABLE_I3=OFF"
|
|
||||||
"-DWITH_XRM=OFF"
|
|
||||||
"-DWITH_XKB=OFF"
|
|
||||||
"-DWITH_XRANDR_MONITORS=OFF"
|
|
||||||
"-DWITH_XCURSOR=OFF"
|
|
||||||
"-DWITH_XRANDR=ON"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
cmake \
|
|
||||||
-DCMAKE_CXX_COMPILER="${CXX}" \
|
|
||||||
-DCMAKE_CXX_FLAGS="${CXXFLAGS} -Werror" \
|
|
||||||
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
|
|
||||||
-DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \
|
|
||||||
-DBUILD_DOC:BOOL="${BUILD_DOC:-OFF}" \
|
|
||||||
"${FLAGS[@]}" ..
|
|
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
echo "${CXX} --version"
|
|
||||||
eval "${CXX} --version"
|
|
||||||
|
|
||||||
echo "cmake --version"
|
|
||||||
cmake --version
|
|
||||||
|
|
||||||
echo "PATH=${PATH}"
|
|
||||||
echo "CXX=${CXX}"
|
|
||||||
echo "CXXFLAGS=${CXXFLAGS}"
|
|
||||||
echo "LDFLAGS=${LDFLAGS}"
|
|
||||||
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"
|
|
||||||
echo "JOBS=${JOBS}"
|
|
@ -63,7 +63,7 @@ class pulseaudio {
|
|||||||
pa_cvolume cv;
|
pa_cvolume cv;
|
||||||
bool muted{false};
|
bool muted{false};
|
||||||
// default sink name
|
// default sink name
|
||||||
static constexpr auto DEFAULT_SINK{"@DEFAULT_SINK@"};
|
static constexpr auto DEFAULT_SINK = "@DEFAULT_SINK@";
|
||||||
|
|
||||||
pa_context* m_context{nullptr};
|
pa_context* m_context{nullptr};
|
||||||
pa_threaded_mainloop* m_mainloop{nullptr};
|
pa_threaded_mainloop* m_mainloop{nullptr};
|
||||||
|
@ -100,7 +100,8 @@ class logger {
|
|||||||
/**
|
/**
|
||||||
* Convert string
|
* Convert string
|
||||||
*/
|
*/
|
||||||
const char* convert(string arg) const; // NOLINT
|
const char* convert(string& arg) const;
|
||||||
|
const char* convert(const string& arg) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert thread id
|
* Convert thread id
|
||||||
|
@ -48,7 +48,7 @@ namespace modules {
|
|||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
string module<Impl>::type() const {
|
string module<Impl>::type() const {
|
||||||
return string(CONST_MOD(Impl).TYPE);
|
return string(module<Impl>::TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
|
@ -17,6 +17,20 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* Loads and sets the interval for this module.
|
||||||
|
*
|
||||||
|
* Will throw an exception if a non-positive (<= 0) number is given.
|
||||||
|
*/
|
||||||
|
void set_interval(interval_t def) {
|
||||||
|
m_interval = this->m_conf.template get<decltype(m_interval)>(this->name(), "interval", def);
|
||||||
|
|
||||||
|
if (m_interval <= 0s) {
|
||||||
|
throw module_error(
|
||||||
|
this->name() + ": 'interval' must be larger than 0 (got '" + to_string(m_interval.count()) + "s')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void runner() {
|
void runner() {
|
||||||
this->m_log.trace("%s: Thread id = %i", this->name(), concurrency_util::thread_id(this_thread::get_id()));
|
this->m_log.trace("%s: Thread id = %i", this->name(), concurrency_util::thread_id(this_thread::get_id()));
|
||||||
|
|
||||||
|
@ -110,8 +110,6 @@ namespace modules {
|
|||||||
// The following mutex is here to protect the data of this modules.
|
// The following mutex is here to protect the data of this modules.
|
||||||
// This can't be achieved using m_buildlock since we "CRTP override" get_output().
|
// This can't be achieved using m_buildlock since we "CRTP override" get_output().
|
||||||
mutable mutex m_workspace_mutex;
|
mutable mutex m_workspace_mutex;
|
||||||
|
|
||||||
event_timer m_timer{0L, 25L};
|
|
||||||
};
|
};
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
@ -10,11 +12,14 @@ namespace process_util {
|
|||||||
|
|
||||||
void redirect_stdio_to_dev_null();
|
void redirect_stdio_to_dev_null();
|
||||||
|
|
||||||
pid_t fork_detached(std::function<void()> const& lambda);
|
pid_t spawn_async(std::function<void()> const& lambda);
|
||||||
|
void fork_detached(std::function<void()> const& lambda);
|
||||||
|
|
||||||
void exec(char* cmd, char** args);
|
void exec(char* cmd, char** args);
|
||||||
void exec_sh(const char* cmd);
|
void exec_sh(const char* cmd);
|
||||||
|
|
||||||
|
int wait(pid_t pid);
|
||||||
|
|
||||||
pid_t wait_for_completion(pid_t process_id, int* status_addr = nullptr, int waitflags = 0);
|
pid_t wait_for_completion(pid_t process_id, int* status_addr = nullptr, int waitflags = 0);
|
||||||
pid_t wait_for_completion(int* status_addr, int waitflags = 0);
|
pid_t wait_for_completion(int* status_addr, int waitflags = 0);
|
||||||
pid_t wait_for_completion_nohang(pid_t process_id, int* status);
|
pid_t wait_for_completion_nohang(pid_t process_id, int* status);
|
||||||
|
@ -72,34 +72,58 @@ void config::warn_deprecated(const string& section, const string& key, string re
|
|||||||
* Look for sections set up to inherit from a base section
|
* Look for sections set up to inherit from a base section
|
||||||
* and copy the missing parameters
|
* and copy the missing parameters
|
||||||
*
|
*
|
||||||
|
* Multiple sections can be specified, separated by a space.
|
||||||
|
*
|
||||||
* [sub/section]
|
* [sub/section]
|
||||||
* inherit = base/section
|
* inherit = section1 section2
|
||||||
*/
|
*/
|
||||||
void config::copy_inherited() {
|
void config::copy_inherited() {
|
||||||
for (auto&& section : m_sections) {
|
for (auto&& section : m_sections) {
|
||||||
|
std::vector<string> inherit_sections;
|
||||||
|
|
||||||
|
// Collect all sections to be inherited
|
||||||
for (auto&& param : section.second) {
|
for (auto&& param : section.second) {
|
||||||
if (param.first == "inherit") {
|
string key_name = param.first;
|
||||||
// Get name of base section
|
if (key_name == "inherit") {
|
||||||
auto inherit = param.second;
|
auto inherit = param.second;
|
||||||
if ((inherit = dereference<string>(section.first, param.first, inherit, inherit)).empty()) {
|
inherit = dereference<string>(section.first, key_name, inherit, inherit);
|
||||||
throw value_error("Invalid section \"\" defined for \"" + section.first + ".inherit\"");
|
|
||||||
|
std::vector<string> sections = string_util::split(std::move(inherit), ' ');
|
||||||
|
|
||||||
|
inherit_sections.insert(inherit_sections.end(), sections.begin(), sections.end());
|
||||||
|
|
||||||
|
} else if (key_name.find("inherit") == 0) {
|
||||||
|
// Legacy support for keys that just start with 'inherit'
|
||||||
|
m_log.warn(
|
||||||
|
"\"%s.%s\": Using anything other than 'inherit' for inheriting section keys is deprecated. "
|
||||||
|
"The 'inherit' key supports multiple section names separated by a space.",
|
||||||
|
section.first, key_name);
|
||||||
|
|
||||||
|
auto inherit = param.second;
|
||||||
|
inherit = dereference<string>(section.first, key_name, inherit, inherit);
|
||||||
|
if (inherit.empty() || m_sections.find(inherit) == m_sections.end()) {
|
||||||
|
throw value_error(
|
||||||
|
"Invalid section \"" + inherit + "\" defined for \"" + section.first + "." + key_name + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find and validate base section
|
inherit_sections.push_back(std::move(inherit));
|
||||||
auto base_section = m_sections.find(inherit);
|
}
|
||||||
if (base_section == m_sections.end()) {
|
}
|
||||||
throw value_error("Invalid section \"" + inherit + "\" defined for \"" + section.first + ".inherit\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_log.trace("config: Copying missing params (sub=\"%s\", base=\"%s\")", section.first, inherit);
|
for (const auto& base_name : inherit_sections) {
|
||||||
|
const auto base_section = m_sections.find(base_name);
|
||||||
|
if (base_section == m_sections.end()) {
|
||||||
|
throw value_error("Invalid section \"" + base_name + "\" defined for \"" + section.first + ".inherit\"");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
m_log.trace("config: Inheriting keys from \"%s\" in \"%s\"", base_name, section.first);
|
||||||
* Iterate the base and copy the parameters that haven't been defined
|
|
||||||
* for the sub-section
|
/*
|
||||||
*/
|
* Iterate the base and copy the parameters that haven't been defined
|
||||||
for (auto&& base_param : base_section->second) {
|
* yet.
|
||||||
section.second.emplace(base_param.first, base_param.second);
|
*/
|
||||||
}
|
for (auto&& base_param : base_section->second) {
|
||||||
|
section.second.emplace(base_param.first, base_param.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
#include "components/logger.hpp"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "components/logger.hpp"
|
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "utils/concurrency.hpp"
|
#include "utils/concurrency.hpp"
|
||||||
@ -12,7 +13,11 @@ POLYBAR_NS
|
|||||||
/**
|
/**
|
||||||
* Convert string
|
* Convert string
|
||||||
*/
|
*/
|
||||||
const char* logger::convert(string arg) const { // NOLINT
|
const char* logger::convert(string& arg) const {
|
||||||
|
return arg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* logger::convert(const string& arg) const {
|
||||||
return arg.c_str();
|
return arg.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ namespace modules {
|
|||||||
|
|
||||||
counter_module::counter_module(const bar_settings& bar, string name_)
|
counter_module::counter_module(const bar_settings& bar, string name_)
|
||||||
: timer_module<counter_module>(bar, move(name_)) {
|
: timer_module<counter_module>(bar, move(name_)) {
|
||||||
m_interval = m_conf.get(name(), "interval", m_interval);
|
set_interval(1s);
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_COUNTER, {TAG_COUNTER});
|
m_formatter->add(DEFAULT_FORMAT, TAG_COUNTER, {TAG_COUNTER});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +25,6 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -16,7 +16,7 @@ namespace modules {
|
|||||||
template class module<cpu_module>;
|
template class module<cpu_module>;
|
||||||
|
|
||||||
cpu_module::cpu_module(const bar_settings& bar, string name_) : timer_module<cpu_module>(bar, move(name_)) {
|
cpu_module::cpu_module(const bar_settings& bar, string name_) : timer_module<cpu_module>(bar, move(name_)) {
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
|
set_interval(1s);
|
||||||
m_totalwarn = m_conf.get(name(), "warn-percentage", m_totalwarn);
|
m_totalwarn = m_conf.get(name(), "warn-percentage", m_totalwarn);
|
||||||
m_ramp_padding = m_conf.get<decltype(m_ramp_padding)>(name(), "ramp-coreload-spacing", 1);
|
m_ramp_padding = m_conf.get<decltype(m_ramp_padding)>(name(), "ramp-coreload-spacing", 1);
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace modules {
|
|||||||
throw module_error("No date or time format specified");
|
throw module_error("No date or time format specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
|
set_interval(1s);
|
||||||
|
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_DATE});
|
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_DATE});
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace modules {
|
|||||||
m_perc_used_warn = m_conf.get(name(), "warn-percentage", 90);
|
m_perc_used_warn = m_conf.get(name(), "warn-percentage", 90);
|
||||||
m_fixed = m_conf.get(name(), "fixed-values", m_fixed);
|
m_fixed = m_conf.get(name(), "fixed-values", m_fixed);
|
||||||
m_spacing = m_conf.get(name(), "spacing", m_spacing);
|
m_spacing = m_conf.get(name(), "spacing", m_spacing);
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 30s);
|
set_interval(30s);
|
||||||
|
|
||||||
// Add formats and elements
|
// Add formats and elements
|
||||||
m_formatter->add(
|
m_formatter->add(
|
||||||
|
@ -23,7 +23,7 @@ namespace modules {
|
|||||||
m_api_url += '/';
|
m_api_url += '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 60s);
|
set_interval(60s);
|
||||||
m_empty_notifications = m_conf.get(name(), "empty-notifications", m_empty_notifications);
|
m_empty_notifications = m_conf.get(name(), "empty-notifications", m_empty_notifications);
|
||||||
|
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL});
|
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL});
|
||||||
|
@ -16,7 +16,7 @@ namespace modules {
|
|||||||
template class module<memory_module>;
|
template class module<memory_module>;
|
||||||
|
|
||||||
memory_module::memory_module(const bar_settings& bar, string name_) : timer_module<memory_module>(bar, move(name_)) {
|
memory_module::memory_module(const bar_settings& bar, string name_) : timer_module<memory_module>(bar, move(name_)) {
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
|
set_interval(1s);
|
||||||
m_perc_memused_warn = m_conf.get(name(), "warn-percentage", 90);
|
m_perc_memused_warn = m_conf.get(name(), "warn-percentage", 90);
|
||||||
|
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR_USED, TAG_BAR_FREE, TAG_RAMP_USED, TAG_RAMP_FREE,
|
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL, {TAG_LABEL, TAG_BAR_USED, TAG_BAR_FREE, TAG_RAMP_USED, TAG_RAMP_FREE,
|
||||||
|
@ -140,7 +140,7 @@ namespace modules {
|
|||||||
m_log.info("%s: Opening menu level '%i'", name(), static_cast<int>(m_level));
|
m_log.info("%s: Opening menu level '%i'", name(), static_cast<int>(m_level));
|
||||||
|
|
||||||
if (static_cast<size_t>(m_level) >= m_levels.size()) {
|
if (static_cast<size_t>(m_level) >= m_levels.size()) {
|
||||||
m_log.warn("%s: Cannot open unexisting menu level '%i'", name(), level);
|
m_log.warn("%s: Cannot open unexisting menu level '%s'", name(), level);
|
||||||
m_level = -1;
|
m_level = -1;
|
||||||
}
|
}
|
||||||
} else if (action == EVENT_CLOSE) {
|
} else if (action == EVENT_CLOSE) {
|
||||||
|
@ -19,7 +19,7 @@ namespace modules {
|
|||||||
m_ping_nth_update = m_conf.get(name(), "ping-interval", m_ping_nth_update);
|
m_ping_nth_update = m_conf.get(name(), "ping-interval", m_ping_nth_update);
|
||||||
m_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth);
|
m_udspeed_minwidth = m_conf.get(name(), "udspeed-minwidth", m_udspeed_minwidth);
|
||||||
m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate);
|
m_accumulate = m_conf.get(name(), "accumulate-stats", m_accumulate);
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
|
set_interval(1s);
|
||||||
m_unknown_up = m_conf.get<bool>(name(), "unknown-as-up", false);
|
m_unknown_up = m_conf.get<bool>(name(), "unknown-as-up", false);
|
||||||
m_udspeed_unit = m_conf.get<string>(name(), "speed-unit", m_udspeed_unit);
|
m_udspeed_unit = m_conf.get<string>(name(), "speed-unit", m_udspeed_unit);
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace modules {
|
|||||||
m_path = m_conf.get(name(), "hwmon-path", ""s);
|
m_path = m_conf.get(name(), "hwmon-path", ""s);
|
||||||
m_tempbase = m_conf.get(name(), "base-temperature", 0);
|
m_tempbase = m_conf.get(name(), "base-temperature", 0);
|
||||||
m_tempwarn = m_conf.get(name(), "warn-temperature", 80);
|
m_tempwarn = m_conf.get(name(), "warn-temperature", 80);
|
||||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "interval", 1s);
|
set_interval(1s);
|
||||||
m_units = m_conf.get(name(), "units", m_units);
|
m_units = m_conf.get(name(), "units", m_units);
|
||||||
|
|
||||||
if (m_path.empty()) {
|
if (m_path.empty()) {
|
||||||
|
@ -126,9 +126,7 @@ namespace modules {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_timer.allow(evt->time)) {
|
broadcast();
|
||||||
broadcast();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +33,7 @@ command<output_policy::IGNORED>::~command() {
|
|||||||
* Execute the command
|
* Execute the command
|
||||||
*/
|
*/
|
||||||
int command<output_policy::IGNORED>::exec(bool wait_for_completion) {
|
int command<output_policy::IGNORED>::exec(bool wait_for_completion) {
|
||||||
m_forkpid = process_util::fork_detached([m_cmd = m_cmd] { process_util::exec_sh(m_cmd.c_str()); });
|
m_forkpid = process_util::spawn_async([m_cmd = m_cmd] { process_util::exec_sh(m_cmd.c_str()); });
|
||||||
if (wait_for_completion) {
|
if (wait_for_completion) {
|
||||||
auto status = wait();
|
auto status = wait();
|
||||||
m_forkpid = -1;
|
m_forkpid = -1;
|
||||||
|
@ -45,15 +45,11 @@ namespace process_util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forks a child process and completely detaches it.
|
* Forks a child process and executes the given lambda function in it.
|
||||||
*
|
*
|
||||||
* In the child process, the given lambda function is executed.
|
* Processes spawned this way need to be waited on by the caller.
|
||||||
*
|
|
||||||
* Use this if you want to run a command and just forget about it.
|
|
||||||
*
|
|
||||||
* \returns The PID of the child process
|
|
||||||
*/
|
*/
|
||||||
pid_t fork_detached(std::function<void()> const& lambda) {
|
pid_t spawn_async(std::function<void()> const& lambda) {
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
case -1:
|
case -1:
|
||||||
@ -71,6 +67,50 @@ namespace process_util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forks a child process and completely detaches it.
|
||||||
|
*
|
||||||
|
* In the child process, the given lambda function is executed.
|
||||||
|
* We fork twice so that the first forked process can exit and it's child is
|
||||||
|
* reparented to the init process.
|
||||||
|
*
|
||||||
|
* Ref: https://web.archive.org/web/20120914180018/http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16
|
||||||
|
*
|
||||||
|
* Use this if you want to run a command and just forget about it.
|
||||||
|
*
|
||||||
|
* \returns The PID of the child process
|
||||||
|
*/
|
||||||
|
void fork_detached(std::function<void()> const& lambda) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
switch (pid) {
|
||||||
|
case -1:
|
||||||
|
throw runtime_error("fork_detached: Unable to fork: " + string(strerror(errno)));
|
||||||
|
case 0:
|
||||||
|
// Child
|
||||||
|
setsid();
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
switch (pid) {
|
||||||
|
case -1:
|
||||||
|
throw runtime_error("fork_detached: Unable to fork: " + string(strerror(errno)));
|
||||||
|
case 0:
|
||||||
|
// Child
|
||||||
|
umask(0);
|
||||||
|
redirect_stdio_to_dev_null();
|
||||||
|
lambda();
|
||||||
|
_Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Exit(0);
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* The first fork immediately exits and we have to collect its exit
|
||||||
|
* status
|
||||||
|
*/
|
||||||
|
wait(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute command
|
* Execute command
|
||||||
*/
|
*/
|
||||||
@ -92,6 +132,15 @@ namespace process_util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wait(pid_t pid) {
|
||||||
|
int forkstatus;
|
||||||
|
do {
|
||||||
|
process_util::wait_for_completion(pid, &forkstatus, WCONTINUED | WUNTRACED);
|
||||||
|
} while (!WIFEXITED(forkstatus) && !WIFSIGNALED(forkstatus));
|
||||||
|
|
||||||
|
return WEXITSTATUS(forkstatus);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for child process
|
* Wait for child process
|
||||||
*/
|
*/
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
using namespace polybar;
|
using namespace polybar;
|
||||||
using namespace process_util;
|
using namespace process_util;
|
||||||
|
|
||||||
TEST(ForkDetached, is_detached) {
|
TEST(SpawnAsync, is_async) {
|
||||||
pid_t pid = fork_detached([] { exec_sh("sleep 0.1"); });
|
pid_t pid = spawn_async([] { exec_sh("sleep 0.1"); });
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
pid_t res = process_util::wait_for_completion_nohang(pid, &status);
|
pid_t res = process_util::wait_for_completion_nohang(pid, &status);
|
||||||
@ -23,8 +23,8 @@ TEST(ForkDetached, is_detached) {
|
|||||||
EXPECT_FALSE(WIFEXITED(status));
|
EXPECT_FALSE(WIFEXITED(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ForkDetached, exit_code) {
|
TEST(SpawnAsync, exit_code) {
|
||||||
pid_t pid = fork_detached([] { exec_sh("exit 42"); });
|
pid_t pid = spawn_async([] { exec_sh("exit 42"); });
|
||||||
int status = 0;
|
int status = 0;
|
||||||
pid_t res = waitpid(pid, &status, 0);
|
pid_t res = waitpid(pid, &status, 0);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Polybar version information
|
# Polybar version information
|
||||||
# Update this on every release
|
# Update this on every release
|
||||||
# This is used to create the version string if a git repo is not available
|
# This is used to create the version string if a git repo is not available
|
||||||
3.5.0
|
3.5.1
|
||||||
|
Loading…
Reference in New Issue
Block a user