From 5c5270d95ef1ff487a7fed0a2306d34b34654328 Mon Sep 17 00:00:00 2001 From: Samuel Henrique Date: Fri, 6 May 2022 17:32:25 +0100 Subject: [PATCH] Import polybar_3.6.3.orig.tar.gz [dgit import orig polybar_3.6.3.orig.tar.gz] --- .clang-format | 14 + .clang-tidy | 50 + .codecov.yml | 21 + .editorconfig | 12 + .github/FUNDING.yml | 2 + .github/ISSUE_TEMPLATE/bug_report.yml | 112 + .github/ISSUE_TEMPLATE/build.yml | 81 + .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/PULL_REQUEST_TEMPLATE.md | 26 + .github/workflows/ci.yml | 160 + .github/workflows/release.yml | 103 + .gitignore | 11 + .gitmodules | 8 + .valgrind-suppressions | 101 + .ycm_extra_conf.py | 126 + CHANGELOG.md | 194 + CMakeLists.txt | 70 + CONTRIBUTING.md | 166 + LICENSE | 19 + README.md | 229 ++ SUPPORT.md | 14 + banner.png | Bin 0 -> 12078 bytes build.sh | 258 ++ cmake/01-core.cmake | 45 + cmake/02-opts.cmake | 22 + cmake/04-targets.cmake | 64 + cmake/05-summary.cmake | 59 + cmake/common/utils.cmake | 116 + cmake/cxx.cmake | 111 + cmake/libpoly.cmake | 106 + cmake/modules/FindALSA.cmake | 14 + cmake/modules/FindCURL.cmake | 14 + cmake/modules/FindCairoFC.cmake | 14 + cmake/modules/FindLibInotify.cmake | 14 + cmake/modules/FindLibMPDClient.cmake | 14 + cmake/modules/FindLibNlGenl3.cmake | 14 + cmake/modules/FindLibPulse.cmake | 14 + cmake/modules/FindLibUV.cmake | 13 + cmake/modules/FindLibiw.cmake | 21 + cmake/modules/FindXcb.cmake | 59 + cmake/templates/uninstall.cmake.in | 23 + common/ci/configure.sh | 45 + common/ci/summary.sh | 19 + common/clang-format.sh | 20 + common/clang-tidy.sh | 26 + contrib/bash/CMakeLists.txt | 6 + contrib/bash/polybar | 107 + contrib/polybar-git.aur/PKGBUILD | 44 + contrib/polybar.aur/PKGBUILD | 36 + contrib/vim/autoload/ft/cpphpp.vim | 19 + contrib/vim/ftplugin/cpp.vim | 8 + contrib/vim/ftplugin/dosini.vim | 11 + contrib/zsh/CMakeLists.txt | 6 + contrib/zsh/_polybar | 61 + contrib/zsh/_polybar_msg | 32 + doc/.gitignore | 1 + doc/CMakeLists.txt | 80 + doc/README.md | 19 + doc/_static/.gitignore | 0 doc/_static/default.png | Bin 0 -> 18104 bytes doc/conf.py | 255 ++ doc/config.ini | 172 + doc/dev/packaging.rst | 88 + doc/dev/release-workflow.rst | 235 ++ doc/index.rst | 45 + doc/man/polybar-msg.1.rst | 75 + doc/man/polybar.1.rst | 92 + doc/man/polybar.5.rst | 184 + doc/user/actions.rst | 457 +++ doc/user/ipc.rst | 120 + include/CMakeLists.txt | 15 + include/adapters/alsa/control.hpp | 41 + include/adapters/alsa/generic.hpp | 65 + include/adapters/alsa/mixer.hpp | 50 + include/adapters/mpd.hpp | 182 + include/adapters/net.hpp | 191 + include/adapters/pulseaudio.hpp | 87 + include/adapters/script_runner.hpp | 58 + include/cairo/context.hpp | 373 ++ include/cairo/font.hpp | 341 ++ include/cairo/fwd.hpp | 15 + include/cairo/surface.hpp | 76 + include/cairo/types.hpp | 77 + include/cairo/utils.hpp | 70 + include/common.hpp | 53 + include/components/bar.hpp | 118 + include/components/builder.hpp | 69 + include/components/command_line.hpp | 78 + include/components/config.hpp | 429 +++ include/components/config_parser.hpp | 263 ++ include/components/controller.hpp | 152 + include/components/eventloop.hpp | 416 +++ include/components/logger.hpp | 160 + include/components/renderer.hpp | 133 + include/components/renderer_interface.hpp | 43 + include/components/screen.hpp | 56 + include/components/types.hpp | 283 ++ include/debug.hpp | 51 + include/drawtypes/animation.hpp | 47 + include/drawtypes/iconset.hpp | 26 + include/drawtypes/label.hpp | 86 + include/drawtypes/layouticonset.hpp | 33 + include/drawtypes/progressbar.hpp | 45 + include/drawtypes/ramp.hpp | 33 + include/errors.hpp | 36 + include/events/signal.hpp | 110 + include/events/signal_emitter.hpp | 107 + include/events/signal_fwd.hpp | 42 + include/events/signal_receiver.hpp | 52 + include/ipc/decoder.hpp | 61 + include/ipc/encoder.hpp | 14 + include/ipc/ipc.hpp | 97 + include/ipc/msg.hpp | 85 + include/ipc/util.hpp | 16 + include/modules/alsa.hpp | 76 + include/modules/backlight.hpp | 60 + include/modules/battery.hpp | 120 + include/modules/bspwm.hpp | 103 + include/modules/counter.hpp | 24 + include/modules/cpu.hpp | 59 + include/modules/date.hpp | 50 + include/modules/fs.hpp | 77 + include/modules/github.hpp | 44 + include/modules/i3.hpp | 104 + include/modules/ipc.hpp | 68 + include/modules/memory.hpp | 52 + include/modules/menu.hpp | 52 + include/modules/meta/base.hpp | 230 ++ include/modules/meta/base.inl | 313 ++ include/modules/meta/event_handler.hpp | 33 + include/modules/meta/event_module.hpp | 46 + include/modules/meta/factory.hpp | 112 + include/modules/meta/inotify_module.hpp | 94 + include/modules/meta/static_module.hpp | 25 + include/modules/meta/timer_module.hpp | 78 + include/modules/mpd.hpp | 119 + include/modules/network.hpp | 61 + include/modules/pulseaudio.hpp | 59 + include/modules/script.hpp | 51 + include/modules/systray.hpp | 41 + include/modules/temperature.hpp | 44 + include/modules/text.hpp | 20 + include/modules/unsupported.hpp | 68 + include/modules/xbacklight.hpp | 64 + include/modules/xkeyboard.hpp | 74 + include/modules/xwindow.hpp | 54 + include/modules/xworkspaces.hpp | 111 + include/settings.hpp.cmake | 75 + include/tags/action_context.hpp | 136 + include/tags/context.hpp | 85 + include/tags/dispatch.hpp | 45 + include/tags/parser.hpp | 159 + include/tags/types.hpp | 118 + include/utils/action_router.hpp | 60 + include/utils/actions.hpp | 32 + include/utils/bspwm.hpp | 37 + include/utils/color.hpp | 68 + include/utils/command.hpp | 108 + include/utils/concurrency.hpp | 38 + include/utils/env.hpp | 12 + include/utils/factory.hpp | 26 + include/utils/file.hpp | 103 + include/utils/functional.hpp | 12 + include/utils/http.hpp | 29 + include/utils/i3.hpp | 34 + include/utils/inotify.hpp | 47 + include/utils/io.hpp | 14 + include/utils/math.hpp | 105 + include/utils/memory.hpp | 39 + include/utils/mixins.hpp | 33 + include/utils/process.hpp | 32 + include/utils/scope.hpp | 39 + include/utils/socket.hpp | 47 + include/utils/string.hpp | 108 + include/utils/time.hpp | 23 + include/utils/units.hpp | 34 + include/x11/atoms.hpp | 48 + include/x11/background_manager.hpp | 123 + include/x11/connection.hpp | 174 + include/x11/cursor.hpp | 29 + include/x11/ewmh.hpp | 47 + include/x11/extensions/all.hpp | 13 + include/x11/extensions/composite.hpp | 23 + include/x11/extensions/fwd.hpp | 21 + include/x11/extensions/randr.hpp | 68 + include/x11/extensions/xkb.hpp | 98 + include/x11/icccm.hpp | 20 + include/x11/registry.hpp | 25 + include/x11/tray_client.hpp | 62 + include/x11/tray_manager.hpp | 172 + include/x11/types.hpp | 84 + include/x11/window.hpp | 24 + include/x11/winspec.hpp | 180 + include/x11/xembed.hpp | 61 + include/x11/xresources.hpp | 64 + lib/CMakeLists.txt | 38 + lib/i3ipcpp/.gitignore | 4 + lib/i3ipcpp/3rd/auss/LICENSE | 24 + lib/i3ipcpp/3rd/auss/README.md | 27 + lib/i3ipcpp/3rd/auss/include/auss.hpp | 47 + lib/i3ipcpp/CHANGELOG | 33 + lib/i3ipcpp/CMakeLists.txt | 65 + lib/i3ipcpp/Doxyfile | 2353 +++++++++++++ lib/i3ipcpp/LICENSE | 22 + lib/i3ipcpp/README.md | 129 + lib/i3ipcpp/examples/CMakeLists.txt | 23 + lib/i3ipcpp/examples/bar-configs.cpp | 43 + lib/i3ipcpp/examples/events.cpp | 46 + lib/i3ipcpp/examples/workspaces.cpp | 64 + lib/i3ipcpp/include/i3ipc++/ipc-util.hpp | 169 + lib/i3ipcpp/include/i3ipc++/ipc.hpp | 377 ++ lib/i3ipcpp/include/i3ipc++/log.hpp | 97 + lib/i3ipcpp/src/ipc-util.cpp | 172 + lib/i3ipcpp/src/ipc.cpp | 630 ++++ lib/i3ipcpp/test/test_ipc.hpp | 28 + lib/xpp/.gitignore | 7 + lib/xpp/CMakeLists.txt | 200 ++ lib/xpp/LICENSE | 8 + lib/xpp/README.md | 313 ++ lib/xpp/cmake/FindXCB.cmake | 254 ++ lib/xpp/generators/TODO | 53 + lib/xpp/generators/accessor.py | 126 + lib/xpp/generators/cpp_client.py | 3125 +++++++++++++++++ lib/xpp/generators/cppcookie.py | 202 ++ lib/xpp/generators/cpperror.py | 221 ++ lib/xpp/generators/cppevent.py | 380 ++ lib/xpp/generators/cppreply.py | 138 + lib/xpp/generators/cpprequest.py | 197 ++ lib/xpp/generators/extensionclass.py | 45 + lib/xpp/generators/interfaceclass.py | 86 + lib/xpp/generators/objectclass.py | 69 + lib/xpp/generators/parameter.py | 269 ++ lib/xpp/generators/resource_classes.py | 81 + lib/xpp/generators/utils.py | 64 + lib/xpp/include/xpp/atom.hpp | 34 + lib/xpp/include/xpp/colormap.hpp | 77 + lib/xpp/include/xpp/connection.hpp | 157 + lib/xpp/include/xpp/core.hpp | 340 ++ lib/xpp/include/xpp/cursor.hpp | 142 + lib/xpp/include/xpp/drawable.hpp | 35 + lib/xpp/include/xpp/event.hpp | 215 ++ lib/xpp/include/xpp/flags.makefile | 40 + lib/xpp/include/xpp/font.hpp | 74 + lib/xpp/include/xpp/fontable.hpp | 35 + lib/xpp/include/xpp/gcontext.hpp | 114 + lib/xpp/include/xpp/generic.hpp | 15 + lib/xpp/include/xpp/generic/error.hpp | 96 + lib/xpp/include/xpp/generic/event.hpp | 45 + lib/xpp/include/xpp/generic/extension.hpp | 59 + lib/xpp/include/xpp/generic/factory.hpp | 92 + .../xpp/generic/input_iterator_adapter.hpp | 163 + .../include/xpp/generic/iterator_traits.hpp | 24 + .../include/xpp/generic/reply_iterator.hpp | 376 ++ lib/xpp/include/xpp/generic/request.hpp | 129 + lib/xpp/include/xpp/generic/resource.hpp | 142 + lib/xpp/include/xpp/generic/signature.hpp | 16 + lib/xpp/include/xpp/pixmap.hpp | 78 + lib/xpp/include/xpp/valueparam.hpp | 50 + lib/xpp/include/xpp/window.hpp | 91 + lib/xpp/include/xpp/xpp.hpp | 19 + lib/xpp/src/examples/Makefile | 14 + lib/xpp/src/examples/demo_01.cpp | 138 + lib/xpp/src/examples/demo_02.cpp | 229 ++ lib/xpp/src/tests/.gitignore | 2 + lib/xpp/src/tests/Makefile | 25 + lib/xpp/src/tests/README.md | 2 + lib/xpp/src/tests/callable.cpp | 83 + lib/xpp/src/tests/error_test.cpp | 497 +++ lib/xpp/src/tests/event.cpp | 125 + lib/xpp/src/tests/iterator.cpp | 155 + lib/xpp/src/tests/requests.cpp | 910 +++++ lib/xpp/src/tests/resource.cpp | 49 + lib/xpp/src/tests/sizeof.cpp | 767 ++++ lib/xpp/src/tests/template.cpp | 101 + lib/xpp/src/tests/test.cpp | 1255 +++++++ lib/xpp/src/tests/xlib-test.cpp | 33 + lib/xpp/src/tests/xlib.cpp | 30 + lib/xpp/src/tests/xproto.cpp | 870 +++++ lib/xpp/src/xpp.cpp | 1 + src/CMakeLists.txt | 243 ++ src/adapters/alsa/control.cpp | 121 + src/adapters/alsa/mixer.cpp | 232 ++ src/adapters/mpd.cpp | 493 +++ src/adapters/net.cpp | 440 +++ src/adapters/net_iw.cpp | 137 + src/adapters/net_nl.cpp | 232 ++ src/adapters/pulseaudio.cpp | 344 ++ src/adapters/script_runner.cpp | 184 + src/cairo/utils.cpp | 176 + src/components/bar.cpp | 938 +++++ src/components/builder.cpp | 497 +++ src/components/command_line.cpp | 203 ++ src/components/config.cpp | 290 ++ src/components/config_parser.cpp | 336 ++ src/components/controller.cpp | 736 ++++ src/components/eventloop.cpp | 211 ++ src/components/logger.cpp | 100 + src/components/renderer.cpp | 822 +++++ src/components/screen.cpp | 146 + src/drawtypes/animation.cpp | 63 + src/drawtypes/iconset.cpp | 38 + src/drawtypes/label.cpp | 316 ++ src/drawtypes/layouticonset.cpp | 99 + src/drawtypes/progressbar.cpp | 137 + src/drawtypes/ramp.cpp | 83 + src/events/signal_emitter.cpp | 15 + src/events/signal_receiver.cpp | 1 + src/ipc/decoder.cpp | 135 + src/ipc/encoder.cpp | 33 + src/ipc/ipc.cpp | 220 ++ src/ipc/util.cpp | 71 + src/main.cpp | 181 + src/modules/alsa.cpp | 298 ++ src/modules/backlight.cpp | 146 + src/modules/battery.cpp | 392 +++ src/modules/bspwm.cpp | 509 +++ src/modules/counter.cpp | 30 + src/modules/cpu.cpp | 183 + src/modules/date.cpp | 94 + src/modules/fs.cpp | 212 ++ src/modules/github.cpp | 135 + src/modules/i3.cpp | 276 ++ src/modules/ipc.cpp | 229 ++ src/modules/memory.cpp | 177 + src/modules/menu.cpp | 156 + src/modules/meta/base.cpp | 187 + src/modules/mpd.cpp | 452 +++ src/modules/network.cpp | 233 ++ src/modules/pulseaudio.cpp | 165 + src/modules/script.cpp | 158 + src/modules/systray.cpp | 65 + src/modules/temperature.cpp | 107 + src/modules/text.cpp | 56 + src/modules/xbacklight.cpp | 169 + src/modules/xkeyboard.cpp | 324 ++ src/modules/xwindow.cpp | 138 + src/modules/xworkspaces.cpp | 453 +++ src/polybar-msg.cpp | 294 ++ src/settings.cpp.cmake | 62 + src/tags/action_context.cpp | 130 + src/tags/context.cpp | 116 + src/tags/dispatch.cpp | 165 + src/tags/parser.cpp | 507 +++ src/utils/action_router.cpp | 45 + src/utils/actions.cpp | 59 + src/utils/bspwm.cpp | 151 + src/utils/color.cpp | 195 + src/utils/command.cpp | 218 ++ src/utils/concurrency.cpp | 19 + src/utils/env.cpp | 21 + src/utils/factory.cpp | 7 + src/utils/file.cpp | 367 ++ src/utils/http.cpp | 59 + src/utils/i3.cpp | 83 + src/utils/inotify.cpp | 121 + src/utils/io.cpp | 39 + src/utils/process.cpp | 204 ++ src/utils/socket.cpp | 120 + src/utils/string.cpp | 344 ++ src/utils/units.cpp | 165 + src/x11/atoms.cpp | 82 + src/x11/background_manager.cpp | 205 ++ src/x11/connection.cpp | 246 ++ src/x11/cursor.cpp | 43 + src/x11/ewmh.cpp | 185 + src/x11/extensions/composite.cpp | 20 + src/x11/extensions/randr.cpp | 274 ++ src/x11/extensions/xkb.cpp | 205 ++ src/x11/icccm.cpp | 56 + src/x11/registry.cpp | 11 + src/x11/tray_client.cpp | 124 + src/x11/tray_manager.cpp | 1162 ++++++ src/x11/window.cpp | 80 + src/x11/winspec.cpp | 138 + src/x11/xembed.cpp | 115 + src/x11/xresources.cpp | 15 + tests/CMakeLists.txt | 79 + tests/CMakeLists.txt.in | 15 + tests/common/test.hpp | 3 + tests/unit_tests/components/builder.cpp | 142 + tests/unit_tests/components/command_line.cpp | 113 + tests/unit_tests/components/config_parser.cpp | 314 ++ tests/unit_tests/drawtypes/iconset.cpp | 18 + tests/unit_tests/drawtypes/label.cpp | 109 + tests/unit_tests/drawtypes/layouticonset.cpp | 76 + tests/unit_tests/drawtypes/ramp.cpp | 49 + tests/unit_tests/ipc/decoder.cpp | 96 + tests/unit_tests/ipc/encoder.cpp | 58 + tests/unit_tests/ipc/util.cpp | 22 + tests/unit_tests/tags/action_context.cpp | 168 + tests/unit_tests/tags/dispatch.cpp | 288 ++ tests/unit_tests/tags/parser.cpp | 495 +++ tests/unit_tests/utils/action_router.cpp | 49 + tests/unit_tests/utils/actions.cpp | 72 + tests/unit_tests/utils/color.cpp | 128 + tests/unit_tests/utils/command.cpp | 47 + tests/unit_tests/utils/env.cpp | 27 + tests/unit_tests/utils/file.cpp | 46 + tests/unit_tests/utils/math.cpp | 74 + tests/unit_tests/utils/memory.cpp | 23 + tests/unit_tests/utils/process.cpp | 44 + tests/unit_tests/utils/scope.cpp | 19 + tests/unit_tests/utils/string.cpp | 186 + tests/unit_tests/utils/units.cpp | 133 + version.txt | 4 + 406 files changed, 56399 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .codecov.yml create mode 100644 .editorconfig create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/build.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .valgrind-suppressions create mode 100644 .ycm_extra_conf.py create mode 100644 CHANGELOG.md create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 SUPPORT.md create mode 100644 banner.png create mode 100755 build.sh create mode 100644 cmake/01-core.cmake create mode 100644 cmake/02-opts.cmake create mode 100644 cmake/04-targets.cmake create mode 100644 cmake/05-summary.cmake create mode 100644 cmake/common/utils.cmake create mode 100644 cmake/cxx.cmake create mode 100644 cmake/libpoly.cmake create mode 100644 cmake/modules/FindALSA.cmake create mode 100644 cmake/modules/FindCURL.cmake create mode 100644 cmake/modules/FindCairoFC.cmake create mode 100644 cmake/modules/FindLibInotify.cmake create mode 100644 cmake/modules/FindLibMPDClient.cmake create mode 100644 cmake/modules/FindLibNlGenl3.cmake create mode 100644 cmake/modules/FindLibPulse.cmake create mode 100644 cmake/modules/FindLibUV.cmake create mode 100644 cmake/modules/FindLibiw.cmake create mode 100644 cmake/modules/FindXcb.cmake create mode 100644 cmake/templates/uninstall.cmake.in create mode 100755 common/ci/configure.sh create mode 100755 common/ci/summary.sh create mode 100755 common/clang-format.sh create mode 100755 common/clang-tidy.sh create mode 100644 contrib/bash/CMakeLists.txt create mode 100644 contrib/bash/polybar create mode 100644 contrib/polybar-git.aur/PKGBUILD create mode 100644 contrib/polybar.aur/PKGBUILD create mode 100644 contrib/vim/autoload/ft/cpphpp.vim create mode 100644 contrib/vim/ftplugin/cpp.vim create mode 100644 contrib/vim/ftplugin/dosini.vim create mode 100644 contrib/zsh/CMakeLists.txt create mode 100644 contrib/zsh/_polybar create mode 100644 contrib/zsh/_polybar_msg create mode 100644 doc/.gitignore create mode 100644 doc/CMakeLists.txt create mode 100644 doc/README.md create mode 100644 doc/_static/.gitignore create mode 100644 doc/_static/default.png create mode 100644 doc/conf.py create mode 100644 doc/config.ini create mode 100644 doc/dev/packaging.rst create mode 100644 doc/dev/release-workflow.rst create mode 100644 doc/index.rst create mode 100644 doc/man/polybar-msg.1.rst create mode 100644 doc/man/polybar.1.rst create mode 100644 doc/man/polybar.5.rst create mode 100644 doc/user/actions.rst create mode 100644 doc/user/ipc.rst create mode 100644 include/CMakeLists.txt create mode 100644 include/adapters/alsa/control.hpp create mode 100644 include/adapters/alsa/generic.hpp create mode 100644 include/adapters/alsa/mixer.hpp create mode 100644 include/adapters/mpd.hpp create mode 100644 include/adapters/net.hpp create mode 100644 include/adapters/pulseaudio.hpp create mode 100644 include/adapters/script_runner.hpp create mode 100644 include/cairo/context.hpp create mode 100644 include/cairo/font.hpp create mode 100644 include/cairo/fwd.hpp create mode 100644 include/cairo/surface.hpp create mode 100644 include/cairo/types.hpp create mode 100644 include/cairo/utils.hpp create mode 100644 include/common.hpp create mode 100644 include/components/bar.hpp create mode 100644 include/components/builder.hpp create mode 100644 include/components/command_line.hpp create mode 100644 include/components/config.hpp create mode 100644 include/components/config_parser.hpp create mode 100644 include/components/controller.hpp create mode 100644 include/components/eventloop.hpp create mode 100644 include/components/logger.hpp create mode 100644 include/components/renderer.hpp create mode 100644 include/components/renderer_interface.hpp create mode 100644 include/components/screen.hpp create mode 100644 include/components/types.hpp create mode 100644 include/debug.hpp create mode 100644 include/drawtypes/animation.hpp create mode 100644 include/drawtypes/iconset.hpp create mode 100644 include/drawtypes/label.hpp create mode 100644 include/drawtypes/layouticonset.hpp create mode 100644 include/drawtypes/progressbar.hpp create mode 100644 include/drawtypes/ramp.hpp create mode 100644 include/errors.hpp create mode 100644 include/events/signal.hpp create mode 100644 include/events/signal_emitter.hpp create mode 100644 include/events/signal_fwd.hpp create mode 100644 include/events/signal_receiver.hpp create mode 100644 include/ipc/decoder.hpp create mode 100644 include/ipc/encoder.hpp create mode 100644 include/ipc/ipc.hpp create mode 100644 include/ipc/msg.hpp create mode 100644 include/ipc/util.hpp create mode 100644 include/modules/alsa.hpp create mode 100644 include/modules/backlight.hpp create mode 100644 include/modules/battery.hpp create mode 100644 include/modules/bspwm.hpp create mode 100644 include/modules/counter.hpp create mode 100644 include/modules/cpu.hpp create mode 100644 include/modules/date.hpp create mode 100644 include/modules/fs.hpp create mode 100644 include/modules/github.hpp create mode 100644 include/modules/i3.hpp create mode 100644 include/modules/ipc.hpp create mode 100644 include/modules/memory.hpp create mode 100644 include/modules/menu.hpp create mode 100644 include/modules/meta/base.hpp create mode 100644 include/modules/meta/base.inl create mode 100644 include/modules/meta/event_handler.hpp create mode 100644 include/modules/meta/event_module.hpp create mode 100644 include/modules/meta/factory.hpp create mode 100644 include/modules/meta/inotify_module.hpp create mode 100644 include/modules/meta/static_module.hpp create mode 100644 include/modules/meta/timer_module.hpp create mode 100644 include/modules/mpd.hpp create mode 100644 include/modules/network.hpp create mode 100644 include/modules/pulseaudio.hpp create mode 100644 include/modules/script.hpp create mode 100644 include/modules/systray.hpp create mode 100644 include/modules/temperature.hpp create mode 100644 include/modules/text.hpp create mode 100644 include/modules/unsupported.hpp create mode 100644 include/modules/xbacklight.hpp create mode 100644 include/modules/xkeyboard.hpp create mode 100644 include/modules/xwindow.hpp create mode 100644 include/modules/xworkspaces.hpp create mode 100644 include/settings.hpp.cmake create mode 100644 include/tags/action_context.hpp create mode 100644 include/tags/context.hpp create mode 100644 include/tags/dispatch.hpp create mode 100644 include/tags/parser.hpp create mode 100644 include/tags/types.hpp create mode 100644 include/utils/action_router.hpp create mode 100644 include/utils/actions.hpp create mode 100644 include/utils/bspwm.hpp create mode 100644 include/utils/color.hpp create mode 100644 include/utils/command.hpp create mode 100644 include/utils/concurrency.hpp create mode 100644 include/utils/env.hpp create mode 100644 include/utils/factory.hpp create mode 100644 include/utils/file.hpp create mode 100644 include/utils/functional.hpp create mode 100644 include/utils/http.hpp create mode 100644 include/utils/i3.hpp create mode 100644 include/utils/inotify.hpp create mode 100644 include/utils/io.hpp create mode 100644 include/utils/math.hpp create mode 100644 include/utils/memory.hpp create mode 100644 include/utils/mixins.hpp create mode 100644 include/utils/process.hpp create mode 100644 include/utils/scope.hpp create mode 100644 include/utils/socket.hpp create mode 100644 include/utils/string.hpp create mode 100644 include/utils/time.hpp create mode 100644 include/utils/units.hpp create mode 100644 include/x11/atoms.hpp create mode 100644 include/x11/background_manager.hpp create mode 100644 include/x11/connection.hpp create mode 100644 include/x11/cursor.hpp create mode 100644 include/x11/ewmh.hpp create mode 100644 include/x11/extensions/all.hpp create mode 100644 include/x11/extensions/composite.hpp create mode 100644 include/x11/extensions/fwd.hpp create mode 100644 include/x11/extensions/randr.hpp create mode 100644 include/x11/extensions/xkb.hpp create mode 100644 include/x11/icccm.hpp create mode 100644 include/x11/registry.hpp create mode 100644 include/x11/tray_client.hpp create mode 100644 include/x11/tray_manager.hpp create mode 100644 include/x11/types.hpp create mode 100644 include/x11/window.hpp create mode 100644 include/x11/winspec.hpp create mode 100644 include/x11/xembed.hpp create mode 100644 include/x11/xresources.hpp create mode 100644 lib/CMakeLists.txt create mode 100644 lib/i3ipcpp/.gitignore create mode 100644 lib/i3ipcpp/3rd/auss/LICENSE create mode 100644 lib/i3ipcpp/3rd/auss/README.md create mode 100644 lib/i3ipcpp/3rd/auss/include/auss.hpp create mode 100644 lib/i3ipcpp/CHANGELOG create mode 100644 lib/i3ipcpp/CMakeLists.txt create mode 100644 lib/i3ipcpp/Doxyfile create mode 100644 lib/i3ipcpp/LICENSE create mode 100644 lib/i3ipcpp/README.md create mode 100644 lib/i3ipcpp/examples/CMakeLists.txt create mode 100644 lib/i3ipcpp/examples/bar-configs.cpp create mode 100644 lib/i3ipcpp/examples/events.cpp create mode 100644 lib/i3ipcpp/examples/workspaces.cpp create mode 100644 lib/i3ipcpp/include/i3ipc++/ipc-util.hpp create mode 100644 lib/i3ipcpp/include/i3ipc++/ipc.hpp create mode 100644 lib/i3ipcpp/include/i3ipc++/log.hpp create mode 100644 lib/i3ipcpp/src/ipc-util.cpp create mode 100644 lib/i3ipcpp/src/ipc.cpp create mode 100644 lib/i3ipcpp/test/test_ipc.hpp create mode 100644 lib/xpp/.gitignore create mode 100644 lib/xpp/CMakeLists.txt create mode 100644 lib/xpp/LICENSE create mode 100644 lib/xpp/README.md create mode 100644 lib/xpp/cmake/FindXCB.cmake create mode 100644 lib/xpp/generators/TODO create mode 100644 lib/xpp/generators/accessor.py create mode 100644 lib/xpp/generators/cpp_client.py create mode 100644 lib/xpp/generators/cppcookie.py create mode 100644 lib/xpp/generators/cpperror.py create mode 100644 lib/xpp/generators/cppevent.py create mode 100644 lib/xpp/generators/cppreply.py create mode 100644 lib/xpp/generators/cpprequest.py create mode 100644 lib/xpp/generators/extensionclass.py create mode 100644 lib/xpp/generators/interfaceclass.py create mode 100644 lib/xpp/generators/objectclass.py create mode 100644 lib/xpp/generators/parameter.py create mode 100644 lib/xpp/generators/resource_classes.py create mode 100644 lib/xpp/generators/utils.py create mode 100644 lib/xpp/include/xpp/atom.hpp create mode 100644 lib/xpp/include/xpp/colormap.hpp create mode 100644 lib/xpp/include/xpp/connection.hpp create mode 100644 lib/xpp/include/xpp/core.hpp create mode 100644 lib/xpp/include/xpp/cursor.hpp create mode 100644 lib/xpp/include/xpp/drawable.hpp create mode 100644 lib/xpp/include/xpp/event.hpp create mode 100644 lib/xpp/include/xpp/flags.makefile create mode 100644 lib/xpp/include/xpp/font.hpp create mode 100644 lib/xpp/include/xpp/fontable.hpp create mode 100644 lib/xpp/include/xpp/gcontext.hpp create mode 100644 lib/xpp/include/xpp/generic.hpp create mode 100644 lib/xpp/include/xpp/generic/error.hpp create mode 100644 lib/xpp/include/xpp/generic/event.hpp create mode 100644 lib/xpp/include/xpp/generic/extension.hpp create mode 100644 lib/xpp/include/xpp/generic/factory.hpp create mode 100644 lib/xpp/include/xpp/generic/input_iterator_adapter.hpp create mode 100644 lib/xpp/include/xpp/generic/iterator_traits.hpp create mode 100644 lib/xpp/include/xpp/generic/reply_iterator.hpp create mode 100644 lib/xpp/include/xpp/generic/request.hpp create mode 100644 lib/xpp/include/xpp/generic/resource.hpp create mode 100644 lib/xpp/include/xpp/generic/signature.hpp create mode 100644 lib/xpp/include/xpp/pixmap.hpp create mode 100644 lib/xpp/include/xpp/valueparam.hpp create mode 100644 lib/xpp/include/xpp/window.hpp create mode 100644 lib/xpp/include/xpp/xpp.hpp create mode 100644 lib/xpp/src/examples/Makefile create mode 100644 lib/xpp/src/examples/demo_01.cpp create mode 100644 lib/xpp/src/examples/demo_02.cpp create mode 100644 lib/xpp/src/tests/.gitignore create mode 100644 lib/xpp/src/tests/Makefile create mode 100644 lib/xpp/src/tests/README.md create mode 100644 lib/xpp/src/tests/callable.cpp create mode 100644 lib/xpp/src/tests/error_test.cpp create mode 100644 lib/xpp/src/tests/event.cpp create mode 100644 lib/xpp/src/tests/iterator.cpp create mode 100644 lib/xpp/src/tests/requests.cpp create mode 100644 lib/xpp/src/tests/resource.cpp create mode 100644 lib/xpp/src/tests/sizeof.cpp create mode 100644 lib/xpp/src/tests/template.cpp create mode 100644 lib/xpp/src/tests/test.cpp create mode 100644 lib/xpp/src/tests/xlib-test.cpp create mode 100644 lib/xpp/src/tests/xlib.cpp create mode 100644 lib/xpp/src/tests/xproto.cpp create mode 100644 lib/xpp/src/xpp.cpp create mode 100644 src/CMakeLists.txt create mode 100644 src/adapters/alsa/control.cpp create mode 100644 src/adapters/alsa/mixer.cpp create mode 100644 src/adapters/mpd.cpp create mode 100644 src/adapters/net.cpp create mode 100644 src/adapters/net_iw.cpp create mode 100644 src/adapters/net_nl.cpp create mode 100644 src/adapters/pulseaudio.cpp create mode 100644 src/adapters/script_runner.cpp create mode 100644 src/cairo/utils.cpp create mode 100644 src/components/bar.cpp create mode 100644 src/components/builder.cpp create mode 100644 src/components/command_line.cpp create mode 100644 src/components/config.cpp create mode 100644 src/components/config_parser.cpp create mode 100644 src/components/controller.cpp create mode 100644 src/components/eventloop.cpp create mode 100644 src/components/logger.cpp create mode 100644 src/components/renderer.cpp create mode 100644 src/components/screen.cpp create mode 100644 src/drawtypes/animation.cpp create mode 100644 src/drawtypes/iconset.cpp create mode 100644 src/drawtypes/label.cpp create mode 100644 src/drawtypes/layouticonset.cpp create mode 100644 src/drawtypes/progressbar.cpp create mode 100644 src/drawtypes/ramp.cpp create mode 100644 src/events/signal_emitter.cpp create mode 100644 src/events/signal_receiver.cpp create mode 100644 src/ipc/decoder.cpp create mode 100644 src/ipc/encoder.cpp create mode 100644 src/ipc/ipc.cpp create mode 100644 src/ipc/util.cpp create mode 100644 src/main.cpp create mode 100644 src/modules/alsa.cpp create mode 100644 src/modules/backlight.cpp create mode 100644 src/modules/battery.cpp create mode 100644 src/modules/bspwm.cpp create mode 100644 src/modules/counter.cpp create mode 100644 src/modules/cpu.cpp create mode 100644 src/modules/date.cpp create mode 100644 src/modules/fs.cpp create mode 100644 src/modules/github.cpp create mode 100644 src/modules/i3.cpp create mode 100644 src/modules/ipc.cpp create mode 100644 src/modules/memory.cpp create mode 100644 src/modules/menu.cpp create mode 100644 src/modules/meta/base.cpp create mode 100644 src/modules/mpd.cpp create mode 100644 src/modules/network.cpp create mode 100644 src/modules/pulseaudio.cpp create mode 100644 src/modules/script.cpp create mode 100644 src/modules/systray.cpp create mode 100644 src/modules/temperature.cpp create mode 100644 src/modules/text.cpp create mode 100644 src/modules/xbacklight.cpp create mode 100644 src/modules/xkeyboard.cpp create mode 100644 src/modules/xwindow.cpp create mode 100644 src/modules/xworkspaces.cpp create mode 100644 src/polybar-msg.cpp create mode 100644 src/settings.cpp.cmake create mode 100644 src/tags/action_context.cpp create mode 100644 src/tags/context.cpp create mode 100644 src/tags/dispatch.cpp create mode 100644 src/tags/parser.cpp create mode 100644 src/utils/action_router.cpp create mode 100644 src/utils/actions.cpp create mode 100644 src/utils/bspwm.cpp create mode 100644 src/utils/color.cpp create mode 100644 src/utils/command.cpp create mode 100644 src/utils/concurrency.cpp create mode 100644 src/utils/env.cpp create mode 100644 src/utils/factory.cpp create mode 100644 src/utils/file.cpp create mode 100644 src/utils/http.cpp create mode 100644 src/utils/i3.cpp create mode 100644 src/utils/inotify.cpp create mode 100644 src/utils/io.cpp create mode 100644 src/utils/process.cpp create mode 100644 src/utils/socket.cpp create mode 100644 src/utils/string.cpp create mode 100644 src/utils/units.cpp create mode 100644 src/x11/atoms.cpp create mode 100644 src/x11/background_manager.cpp create mode 100644 src/x11/connection.cpp create mode 100644 src/x11/cursor.cpp create mode 100644 src/x11/ewmh.cpp create mode 100644 src/x11/extensions/composite.cpp create mode 100644 src/x11/extensions/randr.cpp create mode 100644 src/x11/extensions/xkb.cpp create mode 100644 src/x11/icccm.cpp create mode 100644 src/x11/registry.cpp create mode 100644 src/x11/tray_client.cpp create mode 100644 src/x11/tray_manager.cpp create mode 100644 src/x11/window.cpp create mode 100644 src/x11/winspec.cpp create mode 100644 src/x11/xembed.cpp create mode 100644 src/x11/xresources.cpp create mode 100644 tests/CMakeLists.txt create mode 100644 tests/CMakeLists.txt.in create mode 100644 tests/common/test.hpp create mode 100644 tests/unit_tests/components/builder.cpp create mode 100644 tests/unit_tests/components/command_line.cpp create mode 100644 tests/unit_tests/components/config_parser.cpp create mode 100644 tests/unit_tests/drawtypes/iconset.cpp create mode 100644 tests/unit_tests/drawtypes/label.cpp create mode 100644 tests/unit_tests/drawtypes/layouticonset.cpp create mode 100644 tests/unit_tests/drawtypes/ramp.cpp create mode 100644 tests/unit_tests/ipc/decoder.cpp create mode 100644 tests/unit_tests/ipc/encoder.cpp create mode 100644 tests/unit_tests/ipc/util.cpp create mode 100644 tests/unit_tests/tags/action_context.cpp create mode 100644 tests/unit_tests/tags/dispatch.cpp create mode 100644 tests/unit_tests/tags/parser.cpp create mode 100644 tests/unit_tests/utils/action_router.cpp create mode 100644 tests/unit_tests/utils/actions.cpp create mode 100644 tests/unit_tests/utils/color.cpp create mode 100644 tests/unit_tests/utils/command.cpp create mode 100644 tests/unit_tests/utils/env.cpp create mode 100644 tests/unit_tests/utils/file.cpp create mode 100644 tests/unit_tests/utils/math.cpp create mode 100644 tests/unit_tests/utils/memory.cpp create mode 100644 tests/unit_tests/utils/process.cpp create mode 100644 tests/unit_tests/utils/scope.cpp create mode 100644 tests/unit_tests/utils/string.cpp create mode 100644 tests/unit_tests/utils/units.cpp create mode 100644 version.txt diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..4d561f8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,14 @@ +--- +Language: Cpp +Standard: Cpp11 +BasedOnStyle: Google +ColumnLimit: 120 +NamespaceIndentation: All +AlignAfterOpenBracket: DontAlign +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +BreakConstructorInitializersBeforeComma: true +DerivePointerAlignment: false +PointerAlignment: Left +SpacesBeforeTrailingComments: 1 +--- diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..b558598 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,50 @@ +--- +Checks: ' + -*, + performance-*, + readability-*, + clang-analyzer-alpha.core*, + clang-analyzer-alpha.security*, + clang-analyzer-alpha.unix.cstring*, + clang-analyzer-core.uninitialized*, + clang-analyzer-cplusplus.*, + clang-analyzer-nullability*, + clang-analyzer-unix*, + cppcoreguidelines*, + modernize-use-*, + modernize-*, + -modernize-raw-string-literal, + -modernize-use-bool-literals, + -modernize-use-trailing-return-type, + -readability-implicit-bool-cast, + -readability-else-after-return, + -readability-named-parameter, + -readability-implicit-bool-conversion, + -cppcoreguidelines-pro-bounds-pointer-arithmetic, + -cppcoreguidelines-pro-bounds-array-to-pointer-decay, + -cppcoreguidelines-pro-type-vararg, + -cppcoreguidelines-pro-type-reinterpret-cast, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-pro-type-cstyle-cast, + -cppcoreguidelines-pro-bounds-constant-array-index + ' + +CheckOptions: + - key: modernize-loop-convert.NamingStyle + value: lower_case + - key: readability-identifier-naming.ClassCase + value: lower_case + - key: readability-identifier-naming.ClassConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.ClassMethodCase + value: lower_case + - key: readability-identifier-naming.MemberCase + value: lower_case + - key: readability-identifier-naming.ProtectedMemberPrefix + value: 'm_' + - key: readability-identifier-naming.PrivateMemberPrefix + value: 'm_' +HeaderFilterRegex: '' +WarningsAsErrors: '' +AnalyzeTemporaryDtors: false +... diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..0a6287d --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,21 @@ +coverage: + status: + project: + default: + # Coverage can drop by 0.1% without failing the status + threshold: 0.1 + patch: + default: + # Patches don't need test coverage + # TODO remove once we have proper testing infrastructure and documentation + target: 0 + +ignore: + - "tests/**/*" + - "lib/**/*" + +comment: + require_changes: true + +github_checks: + annotations: false diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..57c08e6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 +charset = utf-8 + +[Makefile] +indent_style = tab +indent_size = 2 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..ea49a3b --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: polybar +open_collective: polybar diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..ad0a991 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,112 @@ +name: Bug Report +description: Create a report for something that misbehaves +title: "[Bug]: " +labels: ["bug", "needs confirmation"] +body: + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: Please carefully go through this checklist and check each option. + options: + - label: I have read the appropriate section in the [contributing guidelines](https://github.com/polybar/polybar/blob/master/CONTRIBUTING.md) + required: true + - label: I believe this issue is a problem with polybar itself and not a misconfiguration on my part + required: true + - label: I have searched for other open and closed [issues](https://github.com/polybar/polybar/issues?q=is%3Aissue) that may have already reported this problem + required: true + - label: I have checked the [known issues](https://github.com/polybar/polybar/wiki/Known-Issues) page for this problem. + required: true + - label: I have followed the [debugging guide](https://github.com/polybar/polybar/wiki/Debugging-your-Config) to narrow down the problem to a minimal config. + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: Any steps to take and commands to run to reproduce this issue. + placeholder: | + 1. `polybar -c ... bar` + 2. ... + validations: + required: true + - type: textarea + id: config + attributes: + label: Minimal config + description: A minimal but complete config with which the problem occurs. + render: dosini + placeholder: | + [bar/example] + ... + + [module/...] + ... + validations: + required: true + - type: textarea + id: logs + attributes: + label: Polybar log + description: Post everything polybar prints to the terminal when you run it and the issue occurs. If possible, run polybar with a higher log level (e.g. `trace` or `info`). + render: text + placeholder: | + notice: Parsing config file: ... + ... + - type: textarea + id: expected + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + description: What actually happens + validations: + required: true + - type: input + id: wm + attributes: + label: Window Manager and Version + placeholder: ex. i3-gaps 4.19.1 + validations: + required: true + - type: input + id: distro + attributes: + label: Linux Distribution + placeholder: ex. Ubuntu 21.04 + validations: + required: true + - type: textarea + id: version + attributes: + label: Polybar version + description: Output of `polybar -vvv` + render: text + placeholder: | + polybar 3.5.7 + + Features: +alsa +curl +i3 +mpd +network(libnl) +pulseaudio +xkeyboard + + X extensions: +randr (+monitors) +composite +xkb +xrm +xcursor + + Build type: Release + Compiler: /usr/bin/c++ + Compiler flags: -D_FORTIFY_SOURCE=2 -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -O3 -DNDEBUG -Wall -Wextra -Wpedantic -Wsuggest-override + Linker flags: -Wall -Wextra -Wpedantic -Wsuggest-override -Wall -Wextra -Wpedantic -Wsuggest-override + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional Context / Screenshots + description: If applicaple, add screenshots and additional context to explain your problem + validations: + required: false + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! :heart: diff --git a/.github/ISSUE_TEMPLATE/build.yml b/.github/ISSUE_TEMPLATE/build.yml new file mode 100644 index 0000000..d6a5767 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/build.yml @@ -0,0 +1,81 @@ +name: Build Issues +description: Report issues while building polybar from source +labels: ["build", "needs confirmation"] +body: + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: Please carefully go through this checklist and check each option. + options: + - label: I have followed every step on the [compiling wiki page](https://github.com/polybar/polybar/wiki/Compiling) and installed all necessary dependencies. + required: true + - label: My problem is not described on the [known issues page](https://github.com/polybar/polybar/wiki/Known-Issues) + required: true + - label: I have searched for other open and closed [issues](https://github.com/polybar/polybar/issues?q=is%3Aissue) that may have already reported this problem. + required: true + - label: I was able to reproduce this build issue in a clean build + required: true + - type: dropdown + id: source + attributes: + label: From where are you building polybar? + options: + - From a release archive + - By cloning this repository + - Some other way (How?) + validations: + required: true + - type: input + id: how + attributes: + label: Describe how you are building polybar. + description: Only if you selected "Some other way". + placeholder: ex. polybar from the AUR + validations: + required: false + - type: input + id: version + attributes: + label: Version + description: What version of polybar are you trying to build? If you are building directly from git, this is the output of `git describe --tags`. + placeholder: ex. 3.5.7 + validations: + required: true + - type: textarea + id: commands + attributes: + label: Build Process + description: List the exact commands you are using to build polybar + render: shell + placeholder: | + mkdir build + cd build + cmake .. + ... + validations: + required: true + - type: textarea + id: logs + attributes: + label: Build log + description: | + Copy-paste all the terminal output produced while building polybar. + This MUST include the output of the `cmake`, `make`, and/or `build.sh` commands, if you used them. + render: text + validations: + required: true + - type: input + id: distro + attributes: + label: Linux Distribution + placeholder: ex. Ubuntu 21.04 + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional Context + description: Add any other context that you think is necessary about the problem here + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..6a1549a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Polybar Gitter Room + url: https://gitter.im/polybar/polybar + about: Please ask and answer questions here. + - name: Polybar subreddit + url: https://www.reddit.com/r/polybar + about: Please ask and answer questions here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..57279e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +labels: feature, needs confirmation +--- + +## Is your feature request related to a problem? Please describe. + + +## Why does polybar need this feature? + + +## Describe the solution you'd like + + +## Describe alternatives you've considered + + +## Additional context + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..442cf05 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,26 @@ + + +## What type of PR is this? (check all applicable) + +* [ ] Refactor +* [ ] Feature +* [ ] Bug Fix +* [ ] Optimization +* [ ] Documentation Update +* [ ] Other: *Replace this with a description of the type of this PR* + +## Description + + +## Related Issues & Documents + + +## Documentation (check all applicable) + +* [ ] This PR requires changes to the Wiki documentation (describe the changes) +* [ ] This PR requires changes to the documentation inside the git repo (please add them to the PR). +* [ ] Does not require documentation changes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9ec6ae5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,160 @@ +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 update + sudo apt-get install -y python3-sphinx + - name: Build Documentation + run: | + mkdir -p build + cd build + cmake -DDISABLE_ALL=ON -DBUILD_DOC=ON -DSPHINX_FLAGS="-W" .. + make doc + + ipc: + runs-on: ubuntu-20.04 + env: + COLOR: "ON" + steps: + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + libxcb-composite0-dev \ + libxcb-ewmh-dev \ + libxcb-icccm4-dev \ + libxcb-image0-dev \ + libxcb-randr0-dev \ + libxcb-util0-dev \ + libxcb1-dev \ + libcairo2-dev \ + python3-xcbgen \ + libuv1-dev \ + xcb-proto + - uses: actions/checkout@v2 + with: + submodules: true + ref: ${{ github.event.inputs.ref }} + - name: Build polybar-msg + run: | + mkdir -p build + cd build + cmake -DDISABLE_ALL=ON -DBUILD_POLYBAR_MSG=ON .. + make polybar-msg + + build: + 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 \ + libuv1-dev \ + 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 \ + libnl-genl-3-dev \ + libmpdclient-dev + fi + + if [ "$POLYBAR_BUILD_TYPE" = "tests" ]; then + sudo apt-get install -y lcov + 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: Collect initial coverage + if: ${{ matrix.polybar_build_type == 'tests' }} + run: | + lcov --capture --initial --no-external --directory . -o cov_base.info + - name: Tests + if: ${{ matrix.polybar_build_type == 'tests' }} + run: | + cd $BUILD_DIR + make check + - name: Collect coverage + if: ${{ matrix.polybar_build_type == 'tests' }} + run: | + lcov --capture --no-external --directory . -o cov_tests.info + lcov --add-tracefile cov_base.info --add-tracefile cov_tests.info -o cov_total.info + lcov --remove cov_total.info ${PWD}'/build/*' ${PWD}'/tests/*' ${PWD}'/lib/*' -o cov.info + - name: Upload Coverage + if: ${{ matrix.polybar_build_type == 'tests' }} + uses: codecov/codecov-action@v2 + with: + flags: unittests + files: ./cov.info + fail_ci_if_error: true + - name: Upload Logs + if: failure() + uses: actions/upload-artifact@v2 + with: + name: cmake + path: | + build/CMakeFiles/CMakeError.log + build/CMakeFiles/CMakeOutput.log + retention-days: 5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3a8d34c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,103 @@ +# Workflow For Releases +# +# Automatically creates and uploads a complete release archive for the given +# release. +name: Release Workflow + +# Is triggered when a new release is published or by hand +# If triggered by hand, the release tag that this should target has to be +# specified. +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Release Tag' + required: true + +jobs: + upload: + runs-on: ubuntu-latest + steps: + - name: Get Version + if: ${{ github.event.inputs.tag }} != '' + run: | + if [ ${{ github.event_name }} == 'workflow_dispatch' ]; then + echo "Manual Release Triggered" + RELEASE_TAG=${{ github.event.inputs.tag }} + else + echo "Automatic Release Triggered" + RELEASE_TAG=${GITHUB_REF#refs/tags/} + fi + echo "Publishing Version $RELEASE_TAG" + echo "RELEASE_TAG=$RELEASE_TAG" >> "$GITHUB_ENV" + echo "POLYBAR_DIR=polybar-$RELEASE_TAG" >> "$GITHUB_ENV" + echo "POLYBAR_ARCHIVE=polybar-$RELEASE_TAG.tar.gz" >> "$GITHUB_ENV" + + # Checks out the target tag + - uses: actions/checkout@v2 + with: + ref: ${{ env.RELEASE_TAG }} + submodules: true + path: ${{ env.POLYBAR_DIR }} + + - name: Create Release Archive + run: | + find "$DIR" -type d -name ".git" -exec rm -rf {} \+ + tar czf "$ARCHIVE" "$DIR" + echo "SHA256SUM=$(sha256sum "$ARCHIVE" | cut -d ' ' -f 1)" >> "$GITHUB_ENV" + env: + DIR: ${{ env.POLYBAR_DIR }} + ARCHIVE: ${{ env.POLYBAR_ARCHIVE }} + + - name: Get Upload URL + id: get_upload_url + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const tag = '${{ env.RELEASE_TAG }}'; + console.log(`Getting Upload URL for '${tag}'`); + const release = await github.repos.getReleaseByTag({ + owner: context.repo.owner, + repo: context.repo.repo, + tag: tag + }); + core.exportVariable('UPLOAD_URL', release.data.upload_url); + core.exportVariable('RELEASE_ID', release.data.id); + core.exportVariable('RELEASE_BODY', release.data.body); + + - name: Upload Release Archive + id: upload_archive + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ env.UPLOAD_URL }} + asset_path: "./${{ env.POLYBAR_ARCHIVE }}" + asset_name: ${{ env.POLYBAR_ARCHIVE }} + asset_content_type: application/gzip + + # Adds a download section to the beginning of the release body + - name: Update Release Body + uses: actions/github-script@v3 + env: + # Existing release body, fetched in the get_upload_url step. + RELEASE_BODY: ${{ env.RELEASE_BODY }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fname = '${{ env.POLYBAR_ARCHIVE }}' + const url = '${{ steps.upload_archive.outputs.browser_download_url }}' + const hash = '${{ env.SHA256SUM }}' + let body = "## Download:\n\n" + body += `[${fname}](${url}) (**sha256**: \`${hash}\`)\n\n` + body += process.env.RELEASE_BODY; + + const release = await github.repos.updateRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: '${{ env.RELEASE_ID}}', + body: body + }); diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e25c24c --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/build +/tags +/compile_commands.json +*.bak +*.pyc +*.swp +*.tmp +.tags +*.user + +polybar-*.tar diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4b6f7f5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,8 @@ +[submodule "lib/i3ipcpp"] + path = lib/i3ipcpp + url = https://github.com/polybar/i3ipcpp + branch = master +[submodule "lib/xpp"] + path = lib/xpp + url = https://github.com/polybar/xpp + branch = master diff --git a/.valgrind-suppressions b/.valgrind-suppressions new file mode 100644 index 0000000..6d33fd4 --- /dev/null +++ b/.valgrind-suppressions @@ -0,0 +1,101 @@ +{ + xft/fontconfig + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:FcPatternCreate + fun:FcFontRenderPrepare + fun:FcFontMatch + fun:XftFontMatch + fun:XftFontOpenName + ... + ... + ... + ... + ... + ... +} +{ + xft/fontconfig + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + fun:FcPatternAddDouble + obj:/usr/lib/libXft.so.* + obj:/usr/lib/libXft.so.* + obj:/usr/lib/libXft.so.* + obj:/usr/lib/libXft.so.* + fun:XftDefaultHasRender + fun:XftDefaultSubstitute + fun:XftFontMatch + fun:XftFontOpenName +} +{ + xft/fontconfig + Memcheck:Leak + match-leak-kinds: definite + fun:malloc + fun:XftFontCheckGlyph + fun:XftGlyphRender + fun:XftDrawGlyphs + fun:XftDrawString16 + ... + ... + ... + ... + ... + ... + ... +} +{ + xft/fontconfig + Memcheck:Leak + match-leak-kinds: definite + fun:realloc + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + fun:FcFontRenderPrepare + fun:FcFontMatch + fun:XftFontMatch + fun:XftFontOpenName + ... + ... + ... + ... + ... +} +{ + xresource manager + Memcheck:Leak + match-leak-kinds: definite + fun:realloc + obj:/usr/lib/libX11.so.* + obj:/usr/lib/libX11.so.* + obj:/usr/lib/libX11.so.* + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XOpenLC + fun:_XrmInitParseInfo + obj:/usr/lib/libX11.so.* + fun:XrmGetStringDatabase + ... + ... +} +{ + xft conditional jump + Memcheck:Cond + obj:/usr/lib/libfreetype.so.* + obj:/usr/lib/libfreetype.so.* + fun:FT_Outline_Decompose + obj:/usr/lib/libfreetype.so.* + obj:/usr/lib/libfreetype.so.* + obj:/usr/lib/libfreetype.so.* + obj:/usr/lib/libfreetype.so.* + obj:/usr/lib/libfreetype.so.* + fun:XftFontLoadGlyphs + fun:XftGlyphExtents + ... + ... +} diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 0000000..4942991 --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,126 @@ +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} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..68708ce --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,194 @@ +# Changelog + +All notable changes to this project will be documented in this file. +Each release should have the following subsections, if entries exist, in the +given order: `Breaking`, `Build`, `Deprecated`, `Removed`, `Added`, `Changed`, +`Fixed`, `Security`. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [3.6.3] - 2022-05-04 +### Fixed +- `custom/script`: Output clearing when `exec-if` fails ([`#2674`](https://github.com/polybar/polybar/issues/2674)) +- `internal/battery`: `poll-interval` not working ([`#2649`](https://github.com/polybar/polybar/issues/2649), [`#2677`](https://github.com/polybar/polybar/pull/2677)) +- ipc: Polybar failing to open IPC channel after another user already ran polybar, if `XDG_RUNTIME_DIR` is not set ([`#2683`](https://github.com/polybar/polybar/issues/2683), [`#2684`](https://github.com/polybar/polybar/pull/2684)) +- No overlines/underlines being drawn when using offsets ([`#2685`](https://github.com/polybar/polybar/pull/2685)) +- Update struts (`_NET_WM_STRUT_PARTIAL`) when hiding the bar ([`#2702`](https://github.com/polybar/polybar/pull/2702)) +- `internal/pulseaudio`: Hanging during startup ([`#2707`](https://github.com/polybar/polybar/issues/2707), [`#2709`](https://github.com/polybar/polybar/pull/2709)) +- `internal/xworkspaces`: Updates of `_NET_DESKTOP_VIEWPORT` being ignored ([`#2693`](https://github.com/polybar/polybar/issues/2693), [`#2698`](https://github.com/polybar/polybar/pull/2698)) + +## [3.6.2] - 2022-04-03 +### Fixed +- `format-offset` being ignored ([`#2643`](https://github.com/polybar/polybar/pull/2643)) +- Negative struts (`margin-bottom`, `margin-top`) being ignored ([`#2642`](https://github.com/polybar/polybar/issues/2642), [`#2644`](https://github.com/polybar/polybar/pull/2644)) +- Positioning in awesomeWM ([`#2651`](https://github.com/polybar/polybar/pull/2651)) +- `internal/xworkspaces`: The module sometimes crashed polybar when windows were closed. ([`#2655`](https://github.com/polybar/polybar/pull/2655)) +- Mouseover error when only one cursor is defined ([`#2656`](https://github.com/polybar/polybar/pull/2656)) +- `custom/script`: Timing inconsistencies ([`#2650`](https://github.com/polybar/polybar/issues/2650), first described at [`#2630`](https://github.com/polybar/polybar/pull/2630)) + +## [3.6.1] - 2022-03-05 +### Build +- Fixed compiler warning in Clang 13 ([`#2613`](https://github.com/polybar/polybar/pull/2613)) +- Fixed compiler error in GCC 12 ([`#2616`](https://github.com/polybar/polybar/pull/2616), [`#2614`](https://github.com/polybar/polybar/issues/2614)) +- Fixed installation of docs when some are not generated (man, html...) ([`#2612`](https://github.com/polybar/polybar/pull/2612)) +- Fix `LDFLAGS` not being respected ([`#2619`](https://github.com/polybar/polybar/pull/2619)) + +### Fixed +- `tray-offset-x`, `tray-offset-y`, `offset-x`, and `offset-y` were mistakenly capped below at 0 ([`#2620`](https://github.com/polybar/polybar/pull/2620)) +- `custom/script`: Polybar shutdown being stalled by hanging script ([`#2621`](https://github.com/polybar/polybar/pull/2621)) +- `polybar-msg`: Wrong hint when using deprecated `hook` ([`#2624`](https://github.com/polybar/polybar/pull/2624)) + +## [3.6.0] - 2022-03-01 +### Breaking +- We added the backslash escape character (\\) for configuration values. This means that the literal backslash character now has special meaning in configuration files, therefore if you want to use it in a value as a literal backslash, you need to escape it with the backslash escape character. The parser logs an error if any unescaped backslashes are found in a value. This affects you only if you are using two consecutive backslashes in a config value, which will now be interpreted as a single literal backslash. ([`#2354`](https://github.com/polybar/polybar/issues/2354)) +- We rewrote our formatting tag parser. This shouldn't break anything, if you experience any problems, please let us know. The new parser now gives errors for certain invalid tags where the old parser would just silently ignore them. Adding extra text to the end of a valid tag now produces an error. For example, tags like `%{T-a}`, `%{T2abc}`, `%{rfoo}`, and others will now start producing errors. This does not affect you unless you are producing your own invalid formatting tags (for example in a script). +- For security reasons, the named pipe at `/tmp/polybar_mqueue.` had its permission bits changed from `666` to `600` to prevent sending ipc messages to polybar processes running under a different user. + +### Build +- New dependency: [libuv](https://github.com/libuv/libuv). At least version 1.3 is required. +- Bump the minimum cmake version to 3.5 +- The `BUILD_IPC_MSG` option has been renamed to `BUILD_POLYBAR_MSG` +- Building the documentation is now enabled by default and not just when `sphinx-build` is found. +- Users can control exactly which targets should be available with the following cmake options (together with their default value): + - `BUILD_POLYBAR=ON` - Builds the `polybar` executable + - `BUILD_POLYBAR_MSG=ON` - Builds the `polybar-msg` executable + - `BUILD_TESTS=OFF` - Builds the test suite + - `BUILD_DOC=ON` - Builds the documentation + - `BUILD_DOC_HTML=BUILD_DOC` - Builds the html documentation (depends on `BUILD_DOC`) + - `BUILD_DOC_MAN=BUILD_DOC` - Builds the manpages (depends on `BUILD_DOC`) + - `BUILD_CONFIG=ON` - Generates the default config + - `BUILD_SHELL=ON` - Generates shell completion files + - `DISABLE_ALL=OFF` - Disables all above targets by default. Individual targets can still be enabled explicitly. +- The documentation can no longer be built by directly configuring the `doc` directory. +- The `POLYBAR_FLAGS` cmake variable can be used to pass extra C++ compiler flags. +- The sample config file has been removed. +- Polybar now ships a default config that is installed to `/etc/polybar/config.ini`, it lives in `doc/config.ini`. It will also be placed in the `examples` directory in the documentation folder. ([`#2405`](https://github.com/polybar/polybar/issues/2405)) +- The `userconfig` target has been removed, you can no longer use `make userconfig`. As an alternative, you can copy the default config from `/etc/polybar/config.ini`. +- The `DEBUG_SHADED` cmake variable and its associated functionality has been removed. + +### Deprecated +- `[settings]`: `throttle-output` and `throttle-output-for` have been removed. The new event loop already does a similar thing where it coalesces update triggers if they happen directly after one another, leading to only a single bar update. +- When not specifying the config file with `--config`, naming your config file `config` is deprecated. Rename your config file to `config.ini`. +- Directly writing ipc messages to `/tmp/polybar_mqueue.` is deprecated, users should always use `polybar-msg`. As a consequence the message format used for IPC is deprecated as well. +- `polybar-msg hook` is deprecated in favor of using the hook action. `polybar-msg` will tell you the correct command to use. + +### Added +- Support `px` and `pt` units everyhwere where before only a number of spaces or pixels could be specified. ([`#2578`](https://github.com/polybar/polybar/pull/2578), [`#1651`](https://github.com/polybar/polybar/issues/1651), [`#951`](https://github.com/polybar/polybar/issues/951)) +- `internal/alsa`: Right and middle click settings. ([`#2566`](https://github.com/polybar/polybar/issues/2566), [`#2573`](https://github.com/polybar/polybar/pull/2573)) +- `internal/network`: + - New token `%mac%` shows MAC address of selected interface ([`#2568`](https://github.com/polybar/polybar/issues/2568), [`#2569`](https://github.com/polybar/polybar/pull/2569)) + - New token `%netspeed%` that provides the total speed of the internet (up + down speed) ([`#2590`](https://github.com/polybar/polybar/pull/2590), [`#1083`](https://github.com/polybar/polybar/issues/1083)) + - `speed-unit = B/s` can be used to customize how network speeds are displayed. ([`#2068`](https://github.com/polybar/polybar/pull/2068)) + - `interface-type` may be used in place of `interface` to automatically select a network interface ([`#2025`](https://github.com/polybar/polybar/pull/2025), [`#339`](https://github.com/polybar/polybar/issues/339)) +- Polybar can now read config files from stdin: `polybar -c /dev/stdin`. ([`#2545`](https://github.com/polybar/polybar/pull/2545)) +- `custom/script`: + - Setting environment variables using `env-*` config option. ([`#2090`](https://github.com/polybar/polybar/issues/2090), [`#2512`](https://github.com/polybar/polybar/pull/2512)) + - Add formatting for script failure (`format-fail`, `label-fail`) ([`#2588`](https://github.com/polybar/polybar/issues/2588), [`#2596`](https://github.com/polybar/polybar/pull/2596)) +- Support for ramp weights. ([`#1750`](https://github.com/polybar/polybar/issues/1750), [`#2505`](https://github.com/polybar/polybar/pull/2505)) +- `internal/memory`: New tokens `%used%`, `%free%`, `%total%`, `%swap_total%`, `%swap_free%`, and `%swap_used%` that automatically switch between MiB and GiB when below or above 1GiB. ([`#2472`](https://github.com/polybar/polybar/issues/2472), [`#2488`](https://github.com/polybar/polybar/pull/2488)) +- `internal/i3`: `show-urgent` option to always show urgent windows when `pin-workspace` is active ([`#2374`](https://github.com/polybar/polybar/issues/2374), [`#2378`](https://github.com/polybar/polybar/pull/2378)) +- `internal/xworkspaces`: + - `reverse-scroll` can be used to reverse the scroll direction when cycling through desktops. ([`#2365`](https://github.com/polybar/polybar/pull/2365)) + - `%nwin%` can be used to display the number of open windows per workspace ([`#604`](https://github.com/polybar/polybar/issues/604), [`#2329`](https://github.com/polybar/polybar/pull/2329)) +- Initial support for the backslash escape character (\\) in configs. ([`#2354`](https://github.com/polybar/polybar/issues/2354), [`#2361`](https://github.com/polybar/polybar/pull/2361)) +- Warn states for the cpu, memory, fs, and battery modules. ([`#570`](https://github.com/polybar/polybar/issues/570), [`#956`](https://github.com/polybar/polybar/issues/956), [`#1871`](https://github.com/polybar/polybar/issues/1871), [`#2141`](https://github.com/polybar/polybar/issues/2141), [`#2199`](https://github.com/polybar/polybar/pull/2199)) + - `internal/battery`: `format-low`, `label-low`, `animation-low`, `low-at = 10`. + - `internal/cpu`: `format-warn`, `label-warn`, `warn-percentage = 80` + - `internal/fs`: `format-warn`, `label-warn`, `warn-percentage = 90` + - `internal/memory`: `format-warn`, `label-warn`, `warn-percentage = 90` +- `radius` now affects the bar border as well ([`#1566`](https://github.com/polybar/polybar/issues/1566), [`#2359`](https://github.com/polybar/polybar/pull/2359)) +- Per-corner radius with `radius-{bottom,top}-{left,right}` ([`#2294`](https://github.com/polybar/polybar/issues/2294), [`#2297`](https://github.com/polybar/polybar/pull/2297)) +- `internal/xkeyboard`: + - `%variant%` token to display the keyboard layout variant ([`#316`](https://github.com/polybar/polybar/issues/316), [`#2163`](https://github.com/polybar/polybar/pull/2163)) + - Allow matching of variants in `layout-icon` ([`#2414`](https://github.com/polybar/polybar/issues/2414), [`#2521`](https://github.com/polybar/polybar/pull/2521)) +- Config option to hide a certain module (`hidden = false`) ([`#2108`](https://github.com/polybar/polybar/issues/2108), [`#2342`](https://github.com/polybar/polybar/pull/2342)) +- Actions to control visibility of modules (`module_toggle`, `module_show`, and `module_hide`) ([`#2108`](https://github.com/polybar/polybar/issues/2108), [`#2426`](https://github.com/polybar/polybar/pull/2426)) +- `internal/backlight`: `use-actual-brightness` option to use the `actual_brightness` file to get the brightness ([`#2380`](https://github.com/polybar/polybar/pull/2380)) +- `wm-restack = generic` option that lowers polybar to the bottom of the window stack. Fixes the issue where the bar is being drawn on top of fullscreen windows in xmonad. ([`#2205`](https://github.com/polybar/polybar/issues/2205), [`#2404`](https://github.com/polybar/polybar/pull/2404)) +- `internal/bspwm`: `occupied-scroll = true` option allows scrolling through occupied desktops only. ([`#2427`](https://github.com/polybar/polybar/issues/2427), [`#2428`](https://github.com/polybar/polybar/pull/2428)) +- `custom/ipc`: + - `send` action to send arbitrary strings to be displayed in the module. ([`#2455`](https://github.com/polybar/polybar/issues/2455), [`#2463`](https://github.com/polybar/polybar/pull/2463)) + - `hook`, `next`, `prev`, `reset` actions to control the module through actions instead of the deprecated hook messages ([`#2464`](https://github.com/polybar/polybar/issues/2464), [`#2528`](https://github.com/polybar/polybar/pull/2528)) +- Added `double-click-interval` setting to the bar section to control the time interval in which a double-click is recognized. Defaults to 400 (ms) ([`#1441`](https://github.com/polybar/polybar/issues/1441), [`#2510`](https://github.com/polybar/polybar/pull/2510)) +- Added a new `tray-foreground` setting to give hints to tray icons about what color they should be. ([`#2235`](https://github.com/polybar/polybar/issues/2235), [`#2552`](https://github.com/polybar/polybar/pull/2552)) +- `polybar-msg`: + - For module actions, you can now also specify the module name, action name, and optional data as separate arguments. ([`#2539`](https://github.com/polybar/polybar/pull/2539)) + - Added man page: `man 1 polybar-msg` ([`#2539`](https://github.com/polybar/polybar/pull/2539)) + +### Changed +- Polybar now also reads `config.ini` when searching for config files. ([`#2323`](https://github.com/polybar/polybar/issues/2323), [`#2324`](https://github.com/polybar/polybar/pull/2324)) +- Polybar additionally searches in `XDG_CONFIG_DIRS/polybar/config.ini` (or `/etc/xdg/polybar/config.ini` if it is not set) and `/etc/polybar/config.ini` for config files. ([`#2016`](https://github.com/polybar/polybar/issues/2016), [`#2511`](https://github.com/polybar/polybar/pull/2511)) +- We rewrote polybar's main event loop. This shouldn't change any behavior for the user, but be on the lookout for X events, click events, or ipc messages not arriving and the bar not shutting down/restarting properly and let us know if you find any issues. ([`#2384`](https://github.com/polybar/polybar/pull/2384)) +- Slight changes to the value ranges the different ramp levels are responsible for in the cpu, memory, fs, and battery modules. The first level is used for everything at and below the start of the value range and the last level for everything at and above the end of the value range. The other levels are evenly distributed over the value range as before. The value range is bounded by the new warning thresholds. ([`#2199`](https://github.com/polybar/polybar/pull/2199)) +- `custom/script`: `interval` now defaults to 0 if `tail = true` as per the documentation. ([`#2240`](https://github.com/polybar/polybar/pull/2240)) +- `internal/network`: Increased precision for upload and download speeds: 0 decimal places for KB/s (as before), 1 for MB/s and 2 for GB/s. ([`#2054`](https://github.com/polybar/polybar/pull/2054)) +- Clicks arriving in close succession, no longer get dropped. Before polybar would drop any click that arrived within 5ms of the previous one. ([`#2510`](https://github.com/polybar/polybar/pull/2510)) +- Increased the double click interval from 150ms to 400ms. ([`#2510`](https://github.com/polybar/polybar/pull/2510)) +- Stop ignoring actions if they arrive while the previous one hasn't been processed yet. ([`#2469`](https://github.com/polybar/polybar/issues/2469), [`#2517`](https://github.com/polybar/polybar/pull/2517)) +- Polybar can now be run without passing the bar name as argument given that the configuration file only defines one bar ([`#2525`](https://github.com/polybar/polybar/issues/2525), [`#2526`](https://github.com/polybar/polybar/pull/2526)) +- `include-directory` and `include-file` now support relative paths. The paths are relative to the folder of the file where those directives appear. ([`#2523`](https://github.com/polybar/polybar/issues/2523), [`#2535`](https://github.com/polybar/polybar/issues/2535)) +- `custom/ipc`: Empty output strings are no longer formatted. This prevents extraneous spaces and separators from appearing in the bar when the output of an ipc module is empty. ([`#2549`](https://github.com/polybar/polybar/pull/2549)) + +### Fixed +- Broken positioning in Openbox when the bar is hidden and shown again ([`#2021`](https://github.com/polybar/polybar/issues/2021), [`#2600`](https://github.com/polybar/polybar/pull/2600)) +- Handling of action blocks that contain negative offsets ([`#1814`](https://github.com/polybar/polybar/issues/1814), [`#2601`](https://github.com/polybar/polybar/pull/2601)) +- `polybar -m` used to show both physical outputs and RandR monitors, even if the outputs were covered by monitors. ([`#2481`](https://github.com/polybar/polybar/issues/2481), [`#2485`](https://github.com/polybar/polybar/pull/2485)) +- Parser error if click command contained `}` ([`#2040`](https://github.com/polybar/polybar/issues/2040), [`#2303`](https://github.com/polybar/polybar/pull/2303)) +- Some modules stop updating when system time moves backwards. ([`#857`](https://github.com/polybar/polybar/issues/857), [`#1932`](https://github.com/polybar/polybar/issues/1932), [`#2559`](https://github.com/polybar/polybar/pull/2559)) +- `custom/script`: Concurrency issues with fast-updating tailed scripts. ([`#1978`](https://github.com/polybar/polybar/issues/1978), [`#2518`](https://github.com/polybar/polybar/pull/2518)) +- `internal/alsa`: Slight imprecision when calculating percentages. This caused the volume reported to be off by one. ([`#2399`](https://github.com/polybar/polybar/issues/2399), [`#2401`](https://github.com/polybar/polybar/pull/2401)) +- `internal/backlight`: With amdgpu backlights, the brightness indicator was slightly behind. ([`#2367`](https://github.com/polybar/polybar/issues/2367), [`#2380`](https://github.com/polybar/polybar/pull/2380)) +- `internal/bspwm`: Warning message regarding T@ ([`#2371`](https://github.com/polybar/polybar/issues/2371), [`#2439`](https://github.com/polybar/polybar/pull/2439)) +- `internal/xkeyboard`: Trailing space after the layout label when indicators are empty and made sure right amount of spacing is added between the indicator labels ([`#2292`](https://github.com/polybar/polybar/issues/2292), [`#2306`](https://github.com/polybar/polybar/pull/2306)) +- `internal/xworkspaces`: + - Broken scroll-wrapping and order of workspaces when scrolling ([`#2491`](https://github.com/polybar/polybar/issues/2491), [`#2492`](https://github.com/polybar/polybar/pull/2492)) + - Module would error if WM was not full started up. ([`#1915`](https://github.com/polybar/polybar/issues/1915), [`#2429`](https://github.com/polybar/polybar/pull/2429)) + - Make the urgent hint persistent ([`#1081`](https://github.com/polybar/polybar/issues/1081), [`#2340`](https://github.com/polybar/polybar/pull/2340)) + - Crash when the WM sets -1 for `_NET_WM_DESKTOP` ([`#2352`](https://github.com/polybar/polybar/issues/2352), [`#2353`](https://github.com/polybar/polybar/issues/2353)) +- `internal/network`: The module now properly supports 'altnames' for interfaces. ([`#2540`](https://github.com/polybar/polybar/pull/2540)) +- `internal/battery`: More accurate battery state ([`#2563`](https://github.com/polybar/polybar/issues/2563), [`#2556`](https://github.com/polybar/polybar/pull/2556)) +- Offset tag does not respect current background color ([`#2578`](https://github.com/polybar/polybar/pull/2578), [`#1700`](https://github.com/polybar/polybar/issues/1700)) +- Crash when negative margin or padding was specified ([`#2578`](https://github.com/polybar/polybar/pull/2578), [`#1265`](https://github.com/polybar/polybar/issues/1265)) + +## [3.5.7] - 2021-09-21 +### Fixed +- The tray mistakenly removed tray icons that did not support XEMBED + ([`#2479`](https://github.com/polybar/polybar/issues/2479), + [`#2442`](https://github.com/polybar/polybar/issues/2442)) +- `custom/ipc`: Only the first appearance of the `%pid%` token was replaced + ([`#2500`](https://github.com/polybar/polybar/issues/2500)) + +## [3.5.6] - 2021-05-24 +### Build +- Support building documentation on sphinx 4.0 ([`#2424`](https://github.com/polybar/polybar/issues/2424)) +### Fixed +- Tray icons sometimes appears outside of bar ([`#2430`](https://github.com/polybar/polybar/issues/2430), [`#1679`](https://github.com/polybar/polybar/issues/1679)) +- Crash in the i3 module ([`#2416`](https://github.com/polybar/polybar/issues/2416)) + +## [3.5.5] - 2021-03-01 +### Build +- Support older python sphinx versions again ([`#2356`](https://github.com/polybar/polybar/issues/2356)) + +## [3.5.4] - 2021-01-07 +### Fixed +- Wrong text displayed if module text ends with `}` ([`#2331`](https://github.com/polybar/polybar/issues/2331)) + +## [3.5.3] - 2020-12-23 +### Build +- Don't use `git` when building documentation ([`#2309`](https://github.com/polybar/polybar/issues/2309)) +### Fixed +- 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 +[3.6.3]: https://github.com/polybar/polybar/releases/tag/3.6.3 +[3.6.2]: https://github.com/polybar/polybar/releases/tag/3.6.2 +[3.6.1]: https://github.com/polybar/polybar/releases/tag/3.6.1 +[3.6.0]: https://github.com/polybar/polybar/releases/tag/3.6.0 +[3.5.7]: https://github.com/polybar/polybar/releases/tag/3.5.7 +[3.5.6]: https://github.com/polybar/polybar/releases/tag/3.5.6 +[3.5.5]: https://github.com/polybar/polybar/releases/tag/3.5.5 +[3.5.4]: https://github.com/polybar/polybar/releases/tag/3.5.4 +[3.5.3]: https://github.com/polybar/polybar/releases/tag/3.5.3 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f71801c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Build configuration +# +cmake_minimum_required(VERSION 3.5.0 FATAL_ERROR) +project(polybar CXX) + +# Extract version information from version.txt. The first line that looks like +# a version string is used, so the file supports comments +file(STRINGS version.txt version_txt REGEX "^[0-9]+\\.[0-9]+\\.[0-9]+.*$" LIMIT_COUNT 1) + +# If we are in a git repo we can get the version information from git describe +execute_process(COMMAND git describe --tags --dirty=-dev + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_describe + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + +if(git_result EQUAL "0") + set(APP_VERSION "${git_describe}") +else() + message(STATUS "Could not detect version with git, falling back to built-in version information.") + set(APP_VERSION "${version_txt}") +endif() + +list(APPEND CMAKE_MODULE_PATH + ${PROJECT_SOURCE_DIR}/cmake + ${PROJECT_SOURCE_DIR}/cmake/common + ${PROJECT_SOURCE_DIR}/cmake/modules) + +include(GNUInstallDirs) +include(utils) +include(01-core) +include(02-opts) +include(04-targets) + +if(BUILD_DOC) + add_subdirectory(doc) +endif() + +if (BUILD_SHELL) + add_subdirectory(contrib/bash) + add_subdirectory(contrib/zsh) +endif() + +# Setup everything that uses a C++ compiler (polybar, polybar-msg, tests) +if(HAS_CXX_COMPILATION) + include(cxx) + if(BUILD_LIBPOLY) + include(libpoly) + add_subdirectory(lib) + endif() + add_subdirectory(include) + add_subdirectory(src bin) +endif() + +# We need to enable testing in the root folder so that 'ctest' and 'make test' +# can be run in the build directory +if(BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() + + +if(BUILD_CONFIG) + install(FILES ${CMAKE_SOURCE_DIR}/doc/config.ini + DESTINATION /etc/${PROJECT_NAME} + COMPONENT config) +endif() + +include(05-summary) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..059eca8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,166 @@ +# Contributing + +First of all, thank you very much for considering contributing to polybar. You +are awesome! :tada: + +**Table of Contents:** +* [Bug Reports](#bug-reports) +* [Pull Requests](#pull-requests) + + [Testing](#testing) + + [Changelog](#changelog) + + [Documentation](#documentation) + + [Style](#style) +* [Donations](#donations) + +## Bug Reports + +Bugs should be reported at the polybar issue tracker, using the [bug report +template](https://github.com/polybar/polybar/issues/new?template=bug_report.yml). +Make sure you fill out all the required sections. + +Before opening a bug report, please search our [issue +tracker](https://github.com/polybar/polybar/issues?q=is%3Aissue) and [known +issues page](https://github.com/polybar/polybar/wiki/Known-Issues) for your +problem to avoid duplicates. + +If your issue has already been reported but is already marked as fixed and the +version of polybar you are using includes this supposed fix, feel free to open a +new issue. + +You should also go through our [debugging +guide](https://github.com/polybar/polybar/wiki/Debugging-your-Config) to confirm +what you are experiencing is indeed a polybar bug and not an issue with your +configuration. +This will also help you narrow down the issue which, in turn, will help us +resolve it, if it turns out to be a bug in polybar. + +If this bug was not present in a previous version of polybar and you know how +to, doing a `git bisect` and providing us with the commit ID that introduced the +issue would be immensely helpful. + +## Pull Requests + +If you want to start contributing to polybar, a good place to start are issues +labeled with +[help wanted](https://github.com/polybar/polybar/labels/help%20wanted) +or +[good first issue](https://github.com/polybar/polybar/labels/good%20first%20issue). + +Except for small changes, PRs should always address an already open and accepted +issue. +Otherwise you run the risk of spending time implementing something and then the +PR being rejected because the feature you implemented was not actually something +we want in polybar. + +Issues with any of the following labels are generally safe to start working on, +unless someone else has already claimed them: + +* [bug](https://github.com/polybar/polybar/labels/bug) +* [confirmed](https://github.com/polybar/polybar/labels/confirmed) +* [good first issue](https://github.com/polybar/polybar/labels/good%20first%20issue) +* [help wanted](https://github.com/polybar/polybar/labels/help%20wanted) +* [hacktoberfest](https://github.com/polybar/polybar/labels/Hacktoberfest) (can also be worked on outside of October :wink:) + +For anything else, it's a good idea to first comment under the issue to ask +whether it is something that can/should be worked on right now. +This is especially true for issues labeled with `feature` (and none of the +labels listed above), here a feature may depend on some other things being +implemented first or it may need to be split into many smaller features, because +it is too big otherwise. +In particular, this means that you should not open a feature request and +immediately start working on that feature, unless you are very sure it will be +accepted or accept the risk of it being rejected. + +Things like documentation changes or refactorings, don't necessarily need an +issue associated with them. +These changes are less likely to be rejected since they don't change the +behavior of polybar. +Nevertheless, for bigger changes or when in doubt, open an issue and ask whether +such changes would be desirable. + +To claim an issue, comment under it to let others know that you are working on +it. + +Feel free to ask for feedback about your changes at any time. +Especially when implementing features, this can be very useful because it allows +us to make sure you are going in the direction we had envisioned for that +feature and you don't lose time on something that ultimately has to be +rewritten. +In that case, a [draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/) +is a useful tool. + +When creating a PR, please fill out the PR template. + +### Testing + +Your PR must pass all existing tests. +If possible, you should also add tests for the things you write. +However, this is not always possible, for example when working on modules. +But at least isolated components should be tested. + +See the [testing page](https://github.com/polybar/polybar/wiki/Testing) on the +wiki for more information. +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. + +### Changelog + +We use the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format for +keeping track of changes in a release. + +If your PR introduces notable changes to polybar, please add them the correct +subsection in the `Unreleased` section in the `CHANGELOG.md` file at the root +of this repository. +Notable changes are any user-visible changes, like bug fixes, new config +options, changes to the build, etc., but not, for example, code cleanup that +doesn't change polybar's behavior or minor documentation changes. +One thing that also should not be added to the changelog are bugfixes for +unreleased features. + +An entry in the changelog should include a link to the issue(s) that the PR +addresses, to the PR itself, and to your username: + +``` +- A short description of the change + ([`#XYZ`](https://github.com/polybar/polybar/issues/XYZ), + [`#UVW`](https://github.com/polybar/polybar/pull/UVW)) + by [@yourname](https://github.com/yourname). +``` + +You will first need to open the PR before you can link to it though :wink:. + + +If you are unsure whether something is a notable change, just add it to the +changelog and we can determine whether it is a notable change when reviewing. + +### Documentation + +Right now, documentation for polybar lives in two places: The GitHub wiki and +the git repo itself. + +Ultimately, most of the documentation is supposed to live in the repo itself. + +For now, if your PR requires documentation changes in the repo, those changes +need to be in the PR as well. + +Changes on the wiki should not be made right away because the wiki should +reflect the currently released version and not the development version. +In that case, outline the documentation changes that need to be made (for +example, which new config options are available). +If your PR would introduce a lot of new documentation on the wiki, let us know +and we can decide if we want to put some of the documentation directly into the +repo. + +### Style + +Please read our [style guide](https://github.com/polybar/polybar/wiki/Style-Guide). + +## Donations + +Donations support the sustained development of polybar. +We accept donations through [our open collective page]( +https://opencollective.com/polybar). +This can be either a one time or a recurring donation. + +Our [blog post](https://polybar.github.io/2020/12/21/Polybar-Funding.html) lays +out the why and how behind our decision to accept donations. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..13e205a --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +The MIT License (MIT) +Copyright (c) 2016 Michael Carlberg + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2695b61 --- /dev/null +++ b/README.md @@ -0,0 +1,229 @@ +

+ Polybar +

+ +

+A fast and easy-to-use tool for creating status bars. +

+ +

+ +GitHub All Releases + + + + + + + + +

+ +**[Documentation](https://github.com/polybar/polybar/wiki/) | [Installation](#installation) | [Support](SUPPORT.md) | [Donate](#donations)** + +**Polybar** aims to help users build beautiful and highly customizable status bars +for their desktop environment, without the need of having a black belt in shell scripting. + +![default configuration screenshot](doc/_static/default.png) + +## Table of Contents + +* [Introduction](#introduction) +* [Getting Help](#getting-help) +* [Contributing](#contributing) +* [Getting started](#getting-started) + * [Installation](#installation) + * [First Steps](#first-steps) +* [Community](#community) +* [Contributors](#contributors) +* [Donations](#donations) + * [Sponsors](#sponsors) + * [Backers](#backers) +* [License](#license) + +## Introduction + +The main purpose of **Polybar** is to help users create awesome status bars. +It has built-in functionality to display information about the most commonly used services. +Some of the services included so far: + +- Systray icons +- Window title +- Playback controls and status display for [MPD](https://www.musicpd.org/) using [libmpdclient](https://www.musicpd.org/libs/libmpdclient/) +- [ALSA](https://www.alsa-project.org/main/index.php/Main_Page) and [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/) volume controls +- Workspace and desktop panel for [bspwm](https://github.com/baskerville/bspwm) and [i3](https://github.com/i3/i3) +- Workspace module for [EWMH compliant](https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130320786080) window managers +- Keyboard layout and indicator status +- CPU and memory load indicator +- Battery display +- Network connection details +- Backlight level +- Date and time label +- Time-based shell script execution +- Command output tailing +- User-defined menu tree +- Inter-process messaging +- And more... + +[See the wiki for more details](https://github.com/polybar/polybar/wiki). + +## Getting Help + +If you find yourself stuck, have a look at our [Support](SUPPORT.md) page for resources where you can find help. + +## Contributing + +Read our [contributing guidelines](CONTRIBUTING.md) for how to get started with contributing to polybar. + +## Getting started + +### Installation + + + Packaging status + + +Polybar is already available in the package manager for many repositories. +We list some of the more prominent ones here. +Also click the [image on the +right](https://repology.org/project/polybar/versions) to see a more complete +list of available polybar packages. + +If you are using **Debian** (bullseye/11/stable) or later, you can install [polybar](https://tracker.debian.org/pkg/polybar) +using `sudo apt install polybar`. Newer releases of polybar are sometimes provided in the [backports](https://wiki.debian.org/Backports) +repository for stable users, you need to enable [backports](https://wiki.debian.org/Backports) and then install using +`sudo apt -t buster-backports install polybar`. + +If you are using **Ubuntu** 20.10 (Groovy Gorilla) or later, you can install polybar +using `sudo apt install polybar`. + +If you are using **Arch Linux**, you can install the AUR package +[polybar](https://aur.archlinux.org/packages/polybar/) to get the latest +version, or [polybar-git](https://aur.archlinux.org/packages/polybar-git/) for +the most up-to-date (unstable) changes. + +If you are using **Void Linux**, you can install [polybar](https://github.com/void-linux/void-packages/blob/master/srcpkgs/polybar/template) using `xbps-install -S polybar`. + +If you are using **NixOS**, polybar is available in both the stable and unstable channels and can be installed with the command `nix-env -iA nixos.polybar`. + +If you are using **Slackware**, polybar is available from the [SlackBuilds](https://slackbuilds.org/repository/14.2/desktop/polybar/) repository. + +If you are using **Source Mage GNU/Linux**, polybar spell is available in test grimoire and can be installed via `cast polybar`. + +If you are using **openSUSE Tumbleweed**, polybar is available from the +[official +repositories](https://build.opensuse.org/package/show/openSUSE%3AFactory/polybar) +and can be installed via `zypper install polybar`. + +If you are using **openSUSE Leap**, polybar is available from +[OBS](https://build.opensuse.org/package/show/X11:Utilities/polybar/). +The package is available for openSUSE Leap 15.1 and above. + +If you are using **FreeBSD**, [polybar](https://svnweb.freebsd.org/ports/head/x11/polybar/) can be installed using `pkg install polybar`. Make sure you are using the `latest` package branch. + +If you are using **Gentoo**, both release and git-master versions are available in the [main](https://packages.gentoo.org/packages/x11-misc/polybar) repository. + +If you are using **Fedora**, you can install [polybar](https://src.fedoraproject.org/rpms/polybar) using `sudo dnf install polybar`. + +If you can't find your distro here, you will have to [build from source](https://github.com/polybar/polybar/wiki/Compiling). + +### First Steps +[See the wiki for details on how to run and configure polybar](https://github.com/polybar/polybar/wiki). + +## Community +Want to get in touch? + +* Join our Gitter room at [gitter.im/polybar/polybar](https://gitter.im/polybar/polybar) +* We have our own subreddit at [r/polybar](https://www.reddit.com/r/polybar). +* Chat with us in the `#polybar` IRC channel on the [`irc.libera.chat:6697`](https://libera.chat/) server. + +## Contributors + +### Owner +* Michael Carlberg [**@jaagr**](https://github.com/jaagr/) + +### Maintainers +* [**@NBonaparte**](https://github.com/NBonaparte) +* Chase Geigle [**@skystrife**](https://github.com/skystrife) +* Patrick Ziegler [**@patrick96**](https://github.com/patrick96) + +### Logo Design by +* [**@Tobaloidee**](https://github.com/Tobaloidee) + + +### [All Contributors](https://github.com/polybar/polybar/graphs/contributors) + +## Donations + +Polybar accepts donations through [open collective](https://opencollective.com/polybar). + +[Become a backer](https://opencollective.com/polybar) and support polybar! +### Sponsors + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +### Backers + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## License + +Polybar is licensed under the MIT license. [See LICENSE for more information](https://github.com/polybar/polybar/blob/master/LICENSE). diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..b502609 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,14 @@ +Getting Help +============ + +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). +* 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. +* Join our Gitter room at [gitter.im/polybar/polybar](https://gitter.im/polybar/polybar) +* Ask in our reddit community at [r/polybar](https://www.reddit.com/r/polybar) +* Join the official IRC channel `#polybar` on the [`irc.libera.chat:6697`](https://libera.chat/) network. If you don't get an answer try asking on [Gitter](https://gitter.im/polybar/polybar). +* Ask on [Unix & Linux StackExchange](https://unix.stackexchange.com/). Though not all questions may be suited over there, make sure you're [on topic](https://unix.stackexchange.com/help/on-topic). + +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. diff --git a/banner.png b/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..6fb984f1df484ead45e3b6d0a755e46057927cdf GIT binary patch literal 12078 zcmc(lWmuF=ALwTnmM%$YPy}g^Mq&XG>24$?1!)1PrAtCl>6UisQfeuclu&A=ML`VcnoudNgSeC5h_vJ}%kc#hpegp;vAbnv>9;P+VZ+3$?r zdn>j_ZsOsJ{h}rjM!8;7(adv?f(+JQ5sM%+qV9-*DN5c`_eiGdS822iY2qrmIoEdS zrXj_kk+wUOc|3HO^COL;FUz$rczUa4>|`&m0IG)|(1LKmVI_bn_y7CFJ%x}rnmKK2 z?^4?A12umPw$5ac9vpbd+|eXnN5d!XuNn9RIk_B;-XC+A8i4&rVJ+Pd5$S%7=P?&I zAnol)i&m+EVjLNl+{WUyFY0a0zna%Q{$nOQl;F+ks-)8VR%L5>O8ZZt)nBIaHs16% z<>nK~oeu`c|CJiD$hCdcrzqsOf4wOp@=#U0DMF>a0~RA5c$7)vjFmo{Ei$m-p|eN;&A22>9JB7 z|HSfUE)*LMWr0*77;_Yh{t0Y|H8&iv0df#0jZ?MvM@KC<3=e^6XbHJ36Q}kk33?1r zxM1tHo$}+p7dys3_->EVz{6~9l|42G~b;(un`nssYLee7_IGgttNEEkxGaecs=Bh{pz~ z{adV7OaIA0mMbu4h+CFXU?d5{Z*}duaEVzkG7|sF$b}jZOhV_8N<3_5S1v>wL(qmi zH6}Pku;DWQTLOPQEAYF`KJL&BjJ;xwAsHlDN`PoggqHhn12+OP;1^x^#5HH|^76py z7d~R)9f!>yPeHiI?m{rm8^$>*>mmnTd#dkM{w)xel0SYGaGvjo_|8C1?PO3WS2Urx ztE3mx9Q4B9o|)y+GyRC7+k*XqeP@nlj{AaRF^BxJZGPE+XMxTv`Ouu`Jrqr)3J?Ua{-J7Ly|oNAR7P;68k9WKVI6U#@|+?Irh zHADW!^ljSgC;AN`vtRB{ynnP5GCGziB`<%C=V>q%Y23F|xQT#?5XN{r$sU5jsVF}@ zHUp#}qx5fg)TJhAfTwm>-oRcWI+S`oeW91TnjC@g2VwO!>>J=NS(-B2n?J$y`k9-a ztaOjiQktxL_6~z&UR*K8yV>LHoQ?-pCP1CiKDF-O5NibLc-3S!L|E12c_=(gA0!iGV7jK|7u{LO=15=3If&jBW>M~;sNcLQsE)H0F= z8LC}Gt6b;a1kcGB&&e;b$=fPH1wLdzP1#^91fQy|IBTYiZ_FFR5 z|4PnG@=3zFnZh&Kya7)FsdoP5)g0SDCvCJL|A_7VAF&(we$O+tg49T!zIH<>Tqni+ zg*JuZE$$~7SAQrF)l3Ab1~3XtZj*jzZ@{EwfZE4K2AOu=HzAnsb&ceBi%(J$CT(=+ zi+{Vtf&L=c2wWxMadDm zN0#;CB|%(PU+*5>&VDyj^0fFr&QkravwmSAQZqF(TOL-hCIO?`R$}+{!!8xn(TlS< zZZml}3lfp=Qg=xRnw$NKPVfp4(R;vftd9U!AB++SUU5zM6Ur<6{!JV_#7~N%18g&)ww761%>0IfxGLE|k;rXUhn_FC zPE>VCXTtbD_CJY+X`ftp@Xb`Ht?gFt(hbV^ z;r;?1!ZlNGC_`+fKi>f7J?^&`n-8j4Vi!B4d7cSs{(4uW2%Zuk&?z{i$OD?u^hk@h zzE@zV?~=yCT=ss~j>Ebyjd!qS?y6N*T4T+Nm9r1`^?u$D?jpa^Ifx8}O`PcmHF_pL zeGf&&JWsUmSrQJcjrsbz@*2rr@>XOCUX-}zbJw677t3Xm!klp~sUGKxNoa*dn^_IF zCV6^AQ-|+Wu~uk<^d95WEo^uocoTjdH7`aw%TF&^)$XFuNFZz7&s*dD{1ta<&q)Hf zN(Dw%Mfjt}aZpIMU}lf2>u*jXyDhk-*vSD(yz$xCYWXCH_GcC0MGd z&VfVHr-)rK1X7jmQ4a@*grRO3bnq6ZfWFcV>^avw9|TKyB^ER~Lr~DCw(_3`fh;Luo9$ebeOtCYvOsL79L@`cI6C zi135Hc;gT<%o3BXy0v~*jM+o~+$~^UQo3`m{{kAZ^AjOS-MY?+N7Yi{V=*+{ivX1#}EnN zW^)C^Q&rPWl4oFa;QI7g0}d?_41su^x^1{gI=sDsv-}u8v~9sDi(tfJ&3Iqzo{Wzh zXKsgB^UXS4p6iCqwN%q_at9BwS;2cOI2dQ-rnWs__Nwmbe!%cJlR>KExhGMQr+V1$ zC{=ftNmQRe=V@a!uMPj?+G$&UBX+eB3K|Vk&B{KoY)~xdzCd$o45c@bfuln3g#Huc z2IHKoj&HxfDc8g^^)%-$>o3>4L->h-6jJ4|k*l7j|0fTO1H6a95o73s=`Rg(^ijd{ zlXY9zY~U^owcHohfM)qMZ780kC3EcXHCy3K%ZZ$WWm{=cVZGD|2IT!2o{Wrt?e4Uj zHg7A*Y`;!SF^-M$WE&*Css6pqI|50?Ec_Y8K6!Wf$u6&b!Il+lcC^S1$4Uf{O&Gsq zJV_d7atT|Xz>^10NfA|}5kK$EC1G(?jK94)cLfwc=V@MNIT{0ZWLR8R#Ai@uz!UTK zK*%9d_tnSdqK8yqvv886FFk#|TIdVOL`KuN{=QGuMXHIL2xNPxds=+D%8oIQPY}o9 zi|$ijw{nD|sens)+Y)Ec)0Z>4vFD@0mzAVSzefhhLK`KVRgh!xjubMCtyf9mIhnF0%A08=KGzV7W$$K0Fn*@(oO)hniH#Zu^ApS66}yNQ z&bGtB^cQezQ& zBY}_J1kop*oNj|Ocj{j8gbf6XeAlbW{;lHxn|nCVL!kWu`4vK-_6bQ$lLvMnGUwIIS-*zF+eUz{MCRRP^PlXt^*r&peG zv;{EErXFPJ_4@^N+!9g*a0k!qLcaLWC0l|F(dY6;Jg_BrX5=rI@fzPrGg z7|67E7$+sj0k1V&5(`HSrfF4_IIQGt3!=fv28Ooiv?0BpBsv@FE4Z>GNo6si0`APV zSKyhJp#1}2&$e<5-)LseH@K$he8oZE004*d~vvT;9}=yFxd=Jo#b*R}Dbc;21$biiFUy~se^ZDGx=F;n?|MtHUKe(6+{`tC%ZzzPQ) z35z2-ax=x%OumbHOBrW&>6owR5Dn0l*ag0;2s%b_rnW4%&DK|TCDa?51holQx&|KxM;z1JlEgeRB=Z&?5-c2 zjt)1ys`d31)cpKs%$`R$kAzbz0Vnlyi&uw&Ks=Z3mgRrc+r2nEeV9eJO&lUELITr?eEp9Y!rn{C}z z%U@!cRyj_l1lyL&G4%muBZ|~@#=J*a%bqNhu+zxwB-$8JWZ&IV8483uBPpy`e zMxZOVK2HW0Ncc5DS(q|pRi$2WC?II29hQ3v2ld|FfCqQqs*Jk<(K=fK#~~3TUkU-@ zW3!!UhrU7u$)SQ%d{`Ibt-PtIhc9gkzLk!TS?t$H8eMFQ?3ieoWpNn&PzxRqd0rdP zA;ptQ6RXswAOX)UVrn~tk^_aXEXOlH989_3dlDQCq*34_@*?vmK9o!NScKqra%4tzQpnH1mE$PL*s^N<+do8u8?MQKkS}%V<}+K zn00at?e%l6jWk`_YD&MemOGrB;GI7eRlaY=?MJtgODH2@(sCeU{*BbzyTvA(OBSth zL5lk1<-Dz~638fRFN&mmO*-H1ghR(BYt_Ss!X4JFWx=n zW)yl!0IZn{i}Yaz4yHb-)=UOd?B)cOQ&HS#ToSV*lj*7)vFVq0IT-GjO(BQ2hhYbx*B&^AjOs4RMG(^rb9AP0ueao;>X%Hn!_{0_u!J?ACdA>W@hW5K=fnty>BNjO*jpnnvWQBR3aulI!pA=KcV=L>8f@v>&D$7P z2~QuV%(Se>jLBktcUa2Xsg@{C`hf}hY5?EL_+}UDD?@jbeCD-Gz5sv;r_rV#*=GTXp3vQ%2p}Md_vW*ox z+6d>AXkq?euon)kCR!4?oj>y=o>^NIAyx6gvqRPHhxM$PK+HSp<`>v2p}^@_QIK!O znt9;(*lcQ)3m1hpl$tGSQCRXzshprJJopV1 z%1)S7CAvMw1$d>eOd7o=2mOxK3#lO02VFL8oTeVzPOm9IK zoJcS^z58v?9Zh5uJ`waWC|hwFFP#ot(-cSLeJQe||G87AlP->#fQ2F3S8|>TA5$NO zW0YL1nW=Tum0}3(h=Vs>uOSLZKR$G+)ke8X11-?|@Nsd*z8>d+;Xfmn35LgxSYzn>G zW&M;pIe^{cn=S=tpLsK%9sB_T84QyBA|zWc^C7UPoyy|vi}EykWK+O&`~kV!R|V!T z^>+agA>xp!mJRKBq=k$$70Vtw%uYgXt>(i7P$dQ&Ducb(eNRh-{4A@o7ddHPIoI!Q zHOm$oYai$haQB_{*x?(TODlpq)M8veN7pZIBU@7qO`R;bo9vinlvris^L^W`8S^$a zD_>af_%Hd%Img`V?VE5=Q-J|UpN!v5r99N~DhQaLETlDG*4nHSS)v~vc{anJ>v$5X z!riq)7EQ-BbAET$^J0q{~sM{V^e)Md(t z&66gSUrk5hpoTdf-lkf^3*3am&h1nfRxatN?;{1f*_fDDM(e<$V)nQsG?xiftQlwD z|02S1+o?0v89pb#5%`ceJMP0%wTo>fT1k9_Q`Li8!(Rx(3b`_FU!)Uj@!wQiSq`vH zG`|-monVq1CbiUqOP^8(BkQj*snj@oNFnED)LFmrs=aHsGIFdAMB>1CrkomPmZY(} zA3uvzoi9$~n0st>637L7^OYD^0#rc2lBKZK>ASEc*P-tq?$~zUDAQUU&!@8N3UdyAiIbh`sw&I zfw%@O*l9^G?+T$A40vl>bZ$D_v^0dL64BT~nNZRXw z;AWG5Bs`vp_o$w}^^L+qtocv8o=LZWQyYC=K*ZCL|XHV zZ&6`J*+3fQprO)4DOxv%J#JxSCu$4sXxG)1;?hjeX$;4|*ZHR1e+3M_?5^Pt+IBcN zd^M1!6R8Kt_%rLquYfSMkJ@wx6C~*w+-uCd2ygWC%Uc9e>`Y=8vf6YG5So`vVOyHr zms(N>*@1FW2x!JaAdc`Hjisnfy!P0t5e2kS!SPE61aPamW=W)}@QAB$h$>Ar;-@$N?d9xP&~3hopjoo%lBCRh1E;Vn6D@+@du-tl^!g?mg7&XeNy zZ-@B=MtmS$vYSi0$O1+c0nl8Nf?F;DvkOIuR~uHfR9s0mG0~x`=XXx{R6dsZ!kmZ) z3aNUFqNijxsf%&cSMJc+KpWKM;15s$4XxoykIjy3O^PTlkzir{Pr;MA(Wk;Yq5=oe zH~y)o_erc8b+QNA z9;8J{VU|Kq76qQUW*JyK3%embC*D~9x!HIdlWKgA#<2yH&+VH&o1#yAn!8tZ60uQs z$f;$_7RHubuaB0{NzmvvYsSIZvinq{2W@IG;$cH0X0LaQfWrSR={$)<&T^Wa0t>rz z!G+z`&A>tOHz)o~fXw)!3F-_Cs=k>&M))&tD72*KVwQ9{p+v71FP z2ip~P_@YO*A;StS?{dh2{_U4`xHAkBG08rI%OQy-nnPCrngob2mwsTgvQBejB;Ys5 z93GZUF}7pl2jT{Og;vML+N1V0@&QpsPA=qT6qv_##?gg+3gq#!a@SL*%xS(K$Ivd} zHQ06Vguv*RCni3{qdzk?u;h`-8!{nhSOJ!DX9 z@5q7tVhdmqZc~-xZV@E%iLs}bYh56Bbt%S296q$KxF*As=5!#KEcT|}+(j<9>kDUF z0$3@xL~dc`LWw%lIHs zt7M|4u=kKe!iJn0@{chg{`u_h`gimJ+X1To_XwFd@zK!$rw*k_@dR+S99P zHON^Sf35>eju{aA91d`2$L(cYrJZm3@DJQhPZG(DpnQCUL!)n=5?bA`B&<(@B+8wO z^vCCZemm~r-F@wj<5-|vmIpP>DT_rI3BsGtT;KjDOyZ?BMH^3kv>;oW&|$P|%Z z&l1I{`rvrqOTMP@LMpQHK4E->3qAtCa+KQ)+K*Eg?%0yApY|Pl&J?GLf$)Yz?uYhR zLWrmZcB=KOcQL~?r1aQKnRd;*KI?)V`Sb+^W^Yr!D*to1}4utAc*u z=Al658#-85_>Wp_V?v_?j{!p_h+7UdbY3U{<7;Xt7%{K%8Ew?Gpw6AKKAxZqsykrJ zXHFDGCP^;1`PF?VRnsMQvQ_fTB=lQ;nf9#?w7Gj+Y-bz}RG7S4KQsWPo~Pm`B`>Sz_OutL)jbPEG8y zY%*CX4-sx3ye2FD#o0u2u=Bpnvq#>;`n$}+NK7Rel?p(%K-E z!UTj65%$1rCvYQg{LZfKhh8iLT;~T9;j-VhSU#N1*S0|Ck7EUfiKw|QH*HD_+s9zvGZ4TgL8{!5~hPrxZoX|uG5Vpb5 z8k?kBDK$)NVDmM?Xl*&QXLrsjEv#qo5T$lq-DL~eqNq*pfY?*d&f%V5&5rMaye8X7 z07eFB)NoHi7P+CB-4AiO=!0u3Ka~%SdtwSalTZ&Z&@WAedWtdKS0lUJkr z*bg=BEFs7-1a}0-vCAf&4Ci|%DD1?Kw57p#fOS8{ahd|D+*;XYGMv zd#7=BqVweFl9gl6)vuFT=93V}H&@W;d+GfY3y};SOs`s5-9yoEwLq zTJD#e?~Fi63BcnEACGZ8^Z_k>deM>#Rh12lBG)iFtnu4!Q@V*0azLsCFlSqKMnkOI z1=$o1%@CHpUs))Fyc>P#VzEOskK7i1RYKPmPOxyI9#7#EP%>aBZo9`hsk{07Wov=Ee=s1 z2s!CwWrp^Kqk#jVQ(ot9QEP&n-waqNH{2rb$OTs~4&}sy!N5R}o6LLo_gig0f8Y#dcDl-0id}l>Hl@4bMKhQuXlcLsLp<(2+ zy{$YRr@S;isb{2_h=VVc<{9u7-(~x9x|8g};mrV&UQ9Vbu{0q+KJ`tM3}K22MHhB5 zv^)2ROD>IC?{h3}<+ZQ8LGQ@nlXu5703K?jto&JnJXgdaEY)3o*ZtiY<3#sSk#4Dw z`Hv=(fRffA(a~&{kZM^EB?V$V$kk%9F;DO4j(TyRw5ksiZ3{Z4WA2PVsHE5^)C zH>bK6Fi$XT=W)I?4)1-8PVPu?A}qYqp7G~knK!Y56ayQ@+_bJl#knU6%wFCpPa4wt zF51KX@hZ7M3Iem@nu)ox$|WG5f7|E`S0(J?{x1J3CX0&ndxCP-#<;~Sf)XtjXU`Vh zaapq}phwkE?&w!vKK#(fnRylKT02DXDI`8l(!7oLlnl(N0T9+8B(|3W~+)mLv&IcUNvQmh?~ zFSDOF37eNYXciiCagmw)W|ES?)psd^L0rSs1etH}f~%fvC#aB{g`>_ z+dU_!(+P>_+iuKz8DTYzfxV*tkVi=h5Da2OOqp6t6kK(|o4<(ptIp_;;K@aekKan+ z?+6%Zz{RFoW77aF)yy#AwN0LB9_D3nLkXPJ@I7fF)`Zr$b2JO4j zKE6JFmi?-|L|PE8?Q{$!cGOB0S3`LgA2sCpR=;&sj5$qOqWS!za9?WZ(EhI5=`+Gw z%p-fhGpLC-hc1xG!=~jzcwdwG8ycO-BP{#|q;nauZD>p2=$rFUgw9bBS&u-^@Jeh? zEgr%}h^~qSrfr$|f}+@M=ZyN`$npOAR|oSI-slD%cB+qw7(T-qVRDm&1AH&86e`xs zeU19{EVq&<+_&u0-i(>SZ$_~CA9^Qn9utr9;#-VdxkX^sAmMFnSD{6Hnav$NxHg8} z_#7heJ(vClFErQM{(+tzO9J$^$}QHz6a56~6crOj_t+ji40l9%*M+4=hCHuQ{}EGqvbSeRLj2a_Y?wWo%t*XWE&RaFW`+q+*sT(G}9_1*EzL! z{IQS8{Yq<38jFG|`@z{{km{Rbdr*Q1h59QqupU4zj29V8lVtD8!Ajr`|MZ$qf}GdP zW>>rd^AW#_t^fre$@iKtlS;tjHGK+#dEIy4rHoJTdct7?7#9`cA{1~BTxo&1aIhp~ z_|2LCCDq4f=;2L1tR>V313#MZ<6>w8#sR5JfMgxrXbXIYf^;#rCpw7HB$Rub2?oNc zcAR%weiovLV-!D?Vq&ug$ijB1PCpGidfu2|bE@zm@f!GE$1jA|L+OMVlh4{S&kOCI z-{}{o&BQoP@3$8C2!i$jBz#CjIvc7{$RWh6hcXEX+U-##3B05_{(f!k^U?3RaOC`r z#7U}wjD_bIU?SKCvSF>>M>E+S|G^XrUJjYQ&j*{eo8 zxL#fl5|L(@lee+zkRGmZs3$#`H#tTJ?6iD-OQs$Y!IOz81mCp8;Y6LoKjq)Tu(^b literal 0 HcmV?d00001 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..d1bfbb7 --- /dev/null +++ b/build.sh @@ -0,0 +1,258 @@ +#!/usr/bin/env bash + +readonly SELF=${0##*/} +declare -rA COLORS=( + [RED]=$'\033[0;31m' + [GREEN]=$'\033[0;32m' + [BLUE]=$'\033[0;34m' + [PURPLE]=$'\033[0;35m' + [CYAN]=$'\033[0;36m' + [WHITE]=$'\033[0;37m' + [YELLOW]=$'\033[0;33m' + [BOLD]=$'\033[1m' + [OFF]=$'\033[0m' +) + +usage() { + echo " + Builds and installs polybar. + + ${COLORS[GREEN]}${COLORS[BOLD]}Usage:${COLORS[OFF]} + ${COLORS[CYAN]}${SELF}${COLORS[OFF]} [options] + + ${COLORS[GREEN]}${COLORS[BOLD]}Options:${COLORS[OFF]} + ${COLORS[GREEN]}-3, --i3${COLORS[OFF]} + Include support for internal/i3 (requires i3); disabled by default. + ${COLORS[GREEN]}-a, --alsa${COLORS[OFF]} + Include support for internal/alsa (requires alsalib); disabled by default. + ${COLORS[GREEN]}-p, --pulseaudio${COLORS[OFF]} + Include support for internal/pulseaudio (requires libpulse); disabled by default. + ${COLORS[GREEN]}-n, --network${COLORS[OFF]} + Include support for internal/network (requires libnl/libiw); disabled by default. + ${COLORS[GREEN]}-m, --mpd${COLORS[OFF]} + Include support for internal/mpd (requires libmpdclient); disabled by default. + ${COLORS[GREEN]}-c, --curl${COLORS[OFF]} + Include support for internal/github (requires libcurl); disabled by default. + ${COLORS[GREEN]}-i, --ipc${COLORS[OFF]} + Build polybar-msg used to send ipc messages; disabled by default. + ${COLORS[GREEN]}--all-features${COLORS[OFF]} + Enable all abovementioned features; + equal to -3 -a -p -n -m -c -i + ${COLORS[GREEN]}-g, --gcc${COLORS[OFF]} + Use GCC even if Clang is installed; disabled by default. + ${COLORS[GREEN]}-j, --jobs${COLORS[OFF]} + Use make -j to use make jobs with $(nproc) jobs; disabled by default. + ${COLORS[GREEN]}-f${COLORS[OFF]} + Remove existing build dir; disabled by default. + ${COLORS[GREEN]}-I, --no-install${COLORS[OFF]} + Do not execute 'sudo make install'; enabled by default. + ${COLORS[GREEN]}-A, --auto${COLORS[OFF]} + Automatic, non-interactive installation; disabled by default. + When set, script defaults options not explicitly set. + ${COLORS[GREEN]}-h, --help${COLORS[OFF]} + Displays this help. +" +} + +msg_err() { + echo -e "${COLORS[RED]}${COLORS[BOLD]}** ${COLORS[OFF]}$*\n" + exit 1 +} + +msg() { + echo -e "${COLORS[GREEN]}${COLORS[BOLD]}** ${COLORS[OFF]}$*\n" +} + +install() { + local p + + if [[ "$AUTO" == ON ]]; then + [[ -z "$INSTALL" ]] && INSTALL="ON" + fi + + if [[ -z "$INSTALL" ]]; then + read -r -p "$(msg "Execute 'sudo make install'? [Y/n] ")" -n 1 p && echo + [[ "${p^^}" != "N" ]] && INSTALL="ON" || INSTALL="OFF" + fi + + if [[ "$INSTALL" == ON ]]; then + sudo make install || msg_err "Failed to install executables..." + fi +} + +set_build_opts() { + local p + + msg "Setting build options" + + if [[ "$AUTO" == ON ]]; then + [[ -z "$USE_GCC" ]] && USE_GCC="OFF" + [[ -z "$ENABLE_I3" ]] && ENABLE_I3="OFF" + [[ -z "$ENABLE_ALSA" ]] && ENABLE_ALSA="OFF" + [[ -z "$ENABLE_PULSEAUDIO" ]] && ENABLE_PULSEAUDIO="OFF" + [[ -z "$ENABLE_NETWORK" ]] && ENABLE_NETWORK="OFF" + [[ -z "$ENABLE_MPD" ]] && ENABLE_MPD="OFF" + [[ -z "$ENABLE_CURL" ]] && ENABLE_CURL="OFF" + [[ -z "$ENABLE_IPC_MSG" ]] && ENABLE_IPC_MSG="OFF" + [[ -z "$JOB_COUNT" ]] && JOB_COUNT=1 + fi + + if [[ -z "$USE_GCC" ]]; then + read -r -p "$(msg "Use GCC even if Clang is installed ----------------------------- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && USE_GCC="OFF" || USE_GCC="ON" + fi + + if [[ -z "$ENABLE_I3" ]]; then + read -r -p "$(msg "Include support for \"internal/i3\" (requires i3) ---------------- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_I3="OFF" || ENABLE_I3="ON" + fi + + if [[ -z "$ENABLE_ALSA" ]]; then + read -r -p "$(msg "Include support for \"internal/alsa\" (requires alsalib) --------- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_ALSA="OFF" || ENABLE_ALSA="ON" + fi + + if [[ -z "$ENABLE_PULSEAUDIO" ]]; then + read -r -p "$(msg "Include support for \"internal/pulseaudio\" (requires libpulse) -- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_PULSEAUDIO="OFF" || ENABLE_PULSEAUDIO="ON" + fi + + if [[ -z "$ENABLE_NETWORK" ]]; then + read -r -p "$(msg "Include support for \"internal/network\" (requires libnl/libiw) -- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_NETWORK="OFF" || ENABLE_NETWORK="ON" + fi + + if [[ -z "$ENABLE_MPD" ]]; then + read -r -p "$(msg "Include support for \"internal/mpd\" (requires libmpdclient) ----- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_MPD="OFF" || ENABLE_MPD="ON" + fi + + if [[ -z "$ENABLE_CURL" ]]; then + read -r -p "$(msg "Include support for \"internal/github\" (requires libcurl) ------- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_CURL="OFF" || ENABLE_CURL="ON" + fi + + if [[ -z "$ENABLE_IPC_MSG" ]]; then + read -r -p "$(msg "Build \"polybar-msg\" used to send ipc messages ------------------ [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && ENABLE_IPC_MSG="OFF" || ENABLE_IPC_MSG="ON" + fi + + if [[ -z "$JOB_COUNT" ]]; then + read -r -p "$(msg "Parallelize the build using make -j$(nproc) --------------------------- [y/N]: ")" -n 1 p && echo + [[ "${p^^}" != "Y" ]] && JOB_COUNT=1 || JOB_COUNT=$(nproc) + fi + + + CXX="c++" + + if [[ "$USE_GCC" == OFF ]]; then + if command -v clang++ >/dev/null; then + msg "Using compiler: clang++/clang" + CXX="clang++" + elif command -v g++ >/dev/null; then + msg "Using compiler: g++/gcc" + CXX="g++" + fi + else + CXX="g++" + fi +} + +main() { + [[ -d ./.git ]] && { + msg "Fetching submodules" + git submodule update --init --recursive || msg_err "Failed to clone submodules" + } + + [[ -d ./build ]] && { + if [[ "$REMOVE_BUILD_DIR" == ON ]]; then + msg "Removing existing build dir (-f)" + rm -rf ./build >/dev/null || msg_err "Failed to remove existing build dir" + else + msg "A build dir already exists (pass -f to replace)" + fi + } + + mkdir -p ./build || msg_err "Failed to create build dir" + cd ./build || msg_err "Failed to enter build dir" + + set_build_opts + + msg "Executing cmake command" + cmake \ + -DCMAKE_CXX_COMPILER="${CXX}" \ + -DENABLE_ALSA:BOOL="${ENABLE_ALSA}" \ + -DENABLE_PULSEAUDIO:BOOL="${ENABLE_PULSEAUDIO}"\ + -DENABLE_I3:BOOL="${ENABLE_I3}" \ + -DENABLE_MPD:BOOL="${ENABLE_MPD}" \ + -DENABLE_NETWORK:BOOL="${ENABLE_NETWORK}" \ + -DENABLE_CURL:BOOL="${ENABLE_CURL}" \ + -DBUILD_POLYBAR_MSG:BOOL="${ENABLE_IPC_MSG}" \ + .. || msg_err "Failed to generate build... read output to get a hint of what went wrong" + + msg "Building project" + if [ -z ${JOB_COUNT} ]; then + make || msg_err "Failed to build project" + else + make -j$JOB_COUNT || msg_err "Failed to build project" + fi + install + msg "Build complete!" + + exit 0 +} + + +################# +###### Entry +################# +while [[ "$1" == -* ]]; do + case "$1" in + -3|--i3) + ENABLE_I3=ON; shift ;; + -a|--alsa) + ENABLE_ALSA=ON; shift ;; + -p|--pulseaudio) + ENABLE_PULSEAUDIO=ON; shift ;; + -n|--network) + ENABLE_NETWORK=ON; shift ;; + -m|--mpd) + ENABLE_MPD=ON; shift ;; + -c|--curl) + ENABLE_CURL=ON; shift ;; + -i|--ipc) + ENABLE_IPC_MSG=ON; shift ;; + --all-features) + ENABLE_I3=ON + ENABLE_ALSA=ON + ENABLE_PULSEAUDIO=ON + ENABLE_NETWORK=ON + ENABLE_MPD=ON + ENABLE_CURL=ON + ENABLE_IPC_MSG=ON + shift ;; + + -g|--gcc) + USE_GCC=ON; shift ;; + -j|--jobs) + JOB_COUNT=$(nproc); shift ;; + -f) + REMOVE_BUILD_DIR=ON; shift ;; + -I|--no-install) + INSTALL=OFF; shift ;; + -A|--auto) + AUTO=ON; shift ;; + -h|--help) + usage + exit 0 + ;; + --) shift; break ;; + *) + usage + [[ "$1" =~ ^-[0-9a-zA-Z]{2,}$ ]] && msg_err "don't combine options: ie do [-c -i] instead of [-ci]" || msg_err "unknown option [$1]" + ;; + esac +done + +main + diff --git a/cmake/01-core.cmake b/cmake/01-core.cmake new file mode 100644 index 0000000..e490e83 --- /dev/null +++ b/cmake/01-core.cmake @@ -0,0 +1,45 @@ +# +# Core setup +# +option(DISABLE_ALL "Set this to ON disable all targets. Individual targets can be enabled explicitly." OFF) + +# If all targets are disabled, we set the default value for options that are on +# by default to OFF +if (DISABLE_ALL) + set(DEFAULT_ON OFF) +else() + set(DEFAULT_ON ON) +endif() + +option(BUILD_POLYBAR "Build the main polybar executable" ${DEFAULT_ON}) +option(BUILD_POLYBAR_MSG "Build polybar-msg" ${DEFAULT_ON}) +option(BUILD_TESTS "Build testsuite" OFF) +option(BUILD_DOC "Build documentation" ${DEFAULT_ON}) +option(BUILD_CONFIG "Generate default configuration" ${DEFAULT_ON}) +option(BUILD_SHELL "Generate shell completion files" ${DEFAULT_ON}) + +include(CMakeDependentOption) +CMAKE_DEPENDENT_OPTION(BUILD_DOC_HTML "Build HTML documentation" ON "BUILD_DOC" OFF) +CMAKE_DEPENDENT_OPTION(BUILD_DOC_MAN "Build manpages" ON "BUILD_DOC" OFF) + +if (BUILD_POLYBAR OR BUILD_TESTS OR BUILD_POLYBAR_MSG) + set(BUILD_LIBPOLY ON) +else() + set(BUILD_LIBPOLY OFF) +endif() + +if (BUILD_POLYBAR OR BUILD_POLYBAR_MSG OR BUILD_TESTS) + set(HAS_CXX_COMPILATION ON) +else() + set(HAS_CXX_COMPILATION OFF) +endif() + +# Export compile commands used for custom targets +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set default build type if not specified +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") + message_colored(STATUS "No build type specified; using ${CMAKE_BUILD_TYPE}" 33) +endif() +string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER) diff --git a/cmake/02-opts.cmake b/cmake/02-opts.cmake new file mode 100644 index 0000000..5c3ea91 --- /dev/null +++ b/cmake/02-opts.cmake @@ -0,0 +1,22 @@ +set(SETTING_ALSA_SOUNDCARD "default" + CACHE STRING "Name of the ALSA soundcard driver") +set(SETTING_BSPWM_SOCKET_PATH "/tmp/bspwm_0_0-socket" + CACHE STRING "Path to bspwm socket") +set(SETTING_BSPWM_STATUS_PREFIX "W" + CACHE STRING "Prefix prepended to the bspwm status line") +set(SETTING_CONNECTION_TEST_IP "8.8.8.8" + CACHE STRING "Address to ping when testing network connection") +set(SETTING_PATH_ADAPTER "/sys/class/power_supply/%adapter%" + CACHE STRING "Path to adapter") +set(SETTING_PATH_BACKLIGHT "/sys/class/backlight/%card%" + CACHE STRING "Path to backlight sysfs folder") +set(SETTING_PATH_BATTERY "/sys/class/power_supply/%battery%" + CACHE STRING "Path to battery") +set(SETTING_PATH_CPU_INFO "/proc/stat" + CACHE STRING "Path to file containing cpu info") +set(SETTING_PATH_MEMORY_INFO "/proc/meminfo" + CACHE STRING "Path to file containing memory info") +set(SETTING_PATH_MESSAGING_FIFO "/tmp/polybar_mqueue.%pid%" + CACHE STRING "Path to file containing the current temperature") +set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp" + CACHE STRING "Path to file containing the current temperature") diff --git a/cmake/04-targets.cmake b/cmake/04-targets.cmake new file mode 100644 index 0000000..7424341 --- /dev/null +++ b/cmake/04-targets.cmake @@ -0,0 +1,64 @@ +# +# Custom targets +# + +# Target: uninstall {{{ + +configure_file( + ${PROJECT_SOURCE_DIR}/cmake/templates/uninstall.cmake.in + ${PROJECT_BINARY_DIR}/cmake/uninstall.cmake + ESCAPE_QUOTES @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/cmake/uninstall.cmake) + +# }}} + +# folders where the clang tools should operate +set(CLANG_SEARCH_PATHS ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/tests) + +# Target: codeformat (clang-format) {{{ + +add_custom_target(codeformat) +add_custom_command(TARGET codeformat + COMMAND ${PROJECT_SOURCE_DIR}/common/clang-format.sh ${CLANG_SEARCH_PATHS}) + +# }}} +# Target: codecheck (clang-tidy) {{{ + +add_custom_target(codecheck) +add_custom_command(TARGET codecheck + COMMAND ${PROJECT_SOURCE_DIR}/common/clang-tidy.sh + ${PROJECT_BINARY_DIR} ${CLANG_SEARCH_PATHS}) + +# }}} +# Target: codecheck-fix (clang-tidy + clang-format) {{{ + +add_custom_target(codecheck-fix) +add_custom_command(TARGET codecheck-fix + COMMAND ${PROJECT_SOURCE_DIR}/common/clang-tidy.sh + ${PROJECT_BINARY_DIR} -fix ${CLANG_SEARCH_PATHS}) + +# }}} + +# Target: memcheck (valgrind) {{{ + +add_custom_target(memcheck) +add_custom_command(TARGET memcheck + COMMAND valgrind + --leak-check=summary + --suppressions=${PROJECT_SOURCE_DIR}/.valgrind-suppressions + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME} + example --config=${PROJECT_SOURCE_DIR}/doc/config) + +add_custom_target(memcheck-full) +add_custom_command(TARGET memcheck-full + COMMAND valgrind + --leak-check=full + --track-origins=yes + --track-fds=yes + --suppressions=${PROJECT_SOURCE_DIR}/.valgrind-suppressions + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME} + example --config=${PROJECT_SOURCE_DIR}/doc/config) + +# }}} diff --git a/cmake/05-summary.cmake b/cmake/05-summary.cmake new file mode 100644 index 0000000..5f71936 --- /dev/null +++ b/cmake/05-summary.cmake @@ -0,0 +1,59 @@ +# +# Output build summary +# +message(STATUS " Build:") +message_colored(STATUS " Version: ${APP_VERSION}" "32;1") +message_colored(STATUS " Type: ${CMAKE_BUILD_TYPE}" "37;2") +if (HAS_CXX_COMPILATION) + message_colored(STATUS " CXX: ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} ${cxx_flags_str}" "37;2") + message_colored(STATUS " LD: ${CMAKE_LINKER} ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_${CMAKE_BUILD_TYPE_UPPER}} ${cxx_linker_flags_str}" "37;2") +endif() +if (BUILD_DOC) + message_colored(STATUS " sphinx-build: ${BIN_SPHINX} ${SPHINX_FLAGS}" "37;2") +endif() + +message(STATUS " Install Paths:") +message_colored(STATUS " PREFIX: ${CMAKE_INSTALL_PREFIX}" "32") +message_colored(STATUS " BINDIR: ${CMAKE_INSTALL_FULL_BINDIR}" "32") +message_colored(STATUS " DATADIR: ${CMAKE_INSTALL_FULL_DATADIR}" "32") +message_colored(STATUS " DOCDIR: ${CMAKE_INSTALL_FULL_DOCDIR}" "32") +message_colored(STATUS " MANDIR: ${CMAKE_INSTALL_FULL_MANDIR}" "32") + +message(STATUS " Targets:") +colored_option(" polybar" BUILD_POLYBAR) +colored_option(" polybar-msg" BUILD_POLYBAR_MSG) +colored_option(" testsuite" BUILD_TESTS) +colored_option(" documentation" BUILD_DOC) +colored_option(" html" BUILD_DOC_HTML) +colored_option(" man" BUILD_DOC_MAN) +colored_option(" default config" BUILD_CONFIG) +colored_option(" shell files" BUILD_SHELL) + +if (BUILD_LIBPOLY) + message(STATUS " Module support:") + colored_option(" alsa" ENABLE_ALSA ALSA_VERSION) + colored_option(" curl" ENABLE_CURL CURL_VERSION) + colored_option(" i3" ENABLE_I3) + colored_option(" mpd" ENABLE_MPD MPD_VERSION) + colored_option(" network (${WIRELESS_LIB})" ENABLE_NETWORK NETWORK_LIBRARY_VERSION) + colored_option(" pulseaudio" ENABLE_PULSEAUDIO PULSEAUDIO_VERSION) + colored_option(" xkeyboard" WITH_XKB Xcb_XKB_VERSION) + + message(STATUS " X extensions:") + colored_option(" xcb-randr" Xcb_RANDR_FOUND Xcb_RANDR_VERSION) + colored_option(" xcb-randr (monitor support)" WITH_XRANDR_MONITORS Xcb_RANDR_VERSION) + colored_option(" xcb-composite" Xcb_COMPOSITE_FOUND Xcb_COMPOSITE_VERSION) + colored_option(" xcb-xkb" WITH_XKB Xcb_XKB_VERSION) + colored_option(" xcb-xrm" WITH_XRM Xcb_XRM_VERSION) + colored_option(" xcb-cursor" WITH_XCURSOR Xcb_CURSOR_VERSION) + + message(STATUS " Log options:") + colored_option(" Trace logging" DEBUG_LOGGER) + + if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG) + message(STATUS " Debug options:") + colored_option(" Trace logging (verbose)" DEBUG_LOGGER_VERBOSE) + colored_option(" Draw clickable areas" DEBUG_HINTS) + colored_option(" Print fc-match details" DEBUG_FONTCONFIG) + endif() +endif() diff --git a/cmake/common/utils.cmake b/cmake/common/utils.cmake new file mode 100644 index 0000000..a7cf77e --- /dev/null +++ b/cmake/common/utils.cmake @@ -0,0 +1,116 @@ +# +# Collection of cmake utility functions +# + +# message_colored {{{ + +function(message_colored message_level text color) + string(ASCII 27 esc) + message(${message_level} "${esc}[${color}m${text}${esc}[0m") +endfunction() + +# }}} +# colored_option {{{ + +function(colored_option text flag) + if(ARGC GREATER 2 AND NOT "${${ARGV2}}" STREQUAL "") + set(text "${text} (${${ARGV2}})") + endif() + + if(${flag}) + message_colored(STATUS "[X]${text}" "32;1") + else() + message_colored(STATUS "[ ]${text}" "37;2") + endif() +endfunction() + +# }}} + +# find_package_impl {{{ + +# Uses PkgConfig to search for pkg_config_name +# +# Defines the following variables: +# ${find_pkg_name}_FOUND - True if the package has been found +# ${find_pkg_name}_INCLUDE_DIR - <...>_INCLUDE_DIRS exported by pkg_check_modules +# ${find_pkg_name}_INCLUDE_DIRS - Same as ${find_pkg_name}_INCLUDE_DIR +# ${find_pkg_name}_LIBRARY - <...>_LIBRARIES exported by pkg_check_modules +# ${find_pkg_name}_LIBRARIES - Same as ${find_pkg_name}_LIBRARY +# ${find_pkg_name}_VERSION - <...>_VERSION exported by pkg_check_modules +# +macro(find_package_impl pkg_config_name find_pkg_name header_to_find) + find_package(PkgConfig REQUIRED) + include(FindPackageHandleStandardArgs) + + pkg_check_modules(PC_${find_pkg_name} REQUIRED ${pkg_config_name}) + + if (NOT ${header_to_find} STREQUAL "") + find_path(PC_${find_pkg_name}_INCLUDE_DIRS_ + NAMES "${header_to_find}" + HINTS "${PC_${find_pkg_name}_INCLUDE_DIRS}" + ) + set(PC_${find_pkg_name}_INCLUDE_DIRS ${PC_${find_pkg_name}_INCLUDE_DIRS_}) + endif() + + set(${find_pkg_name}_INCLUDE_DIR ${PC_${find_pkg_name}_INCLUDE_DIRS}) + set(${find_pkg_name}_INCLUDE_DIRS ${${find_pkg_name}_INCLUDE_DIR}) + set(${find_pkg_name}_LIBRARY ${PC_${find_pkg_name}_LIBRARIES}) + set(${find_pkg_name}_VERSION ${PC_${find_pkg_name}_VERSION}) + set(${find_pkg_name}_LIBRARIES ${${find_pkg_name}_LIBRARY}) + + find_package_handle_standard_args(${find_pkg_name} + REQUIRED_VARS + ${find_pkg_name}_INCLUDE_DIRS + ${find_pkg_name}_LIBRARIES + VERSION_VAR + ${find_pkg_name}_VERSION + ) + + mark_as_advanced(${find_pkg_name}_INCLUDE_DIR ${find_pkg_name}_LIBRARY) +endmacro() + +# }}} +# create_imported_target {{{ +function(create_imported_target library_name includes libraries) + add_library(${library_name} INTERFACE IMPORTED) + set_target_properties(${library_name} PROPERTIES + INTERFACE_LINK_LIBRARIES "${libraries}" + INTERFACE_INCLUDE_DIRECTORIES "${includes}" + ) +endfunction() +# }}} +# checklib {{{ + +function(checklib flag type pkg) + if(NOT DEFINED ${flag}) + if(${type} STREQUAL "cmake") + find_package(${pkg} QUIET) + set(${flag} ${${pkg}_FOUND} CACHE BOOL "") + elseif(${type} STREQUAL "pkg-config") + find_package(PkgConfig REQUIRED) + pkg_check_modules(PKG_${flag} QUIET ${pkg}) + set(${flag} ${PKG_${flag}_FOUND} CACHE BOOL "") + elseif(${type} STREQUAL "binary") + find_program(BIN_${flag} ${pkg}) + set(${flag} ${BIN_${flag}} CACHE BOOL "") + else() + message(FATAL_ERROR "Invalid lookup type '${type}'") + endif() + mark_as_advanced(${flag}) + endif() +endfunction() + +function(get_include_dirs output) + get_filename_component(generated_sources_dir ${CMAKE_BINARY_DIR}/generated-sources ABSOLUTE) + get_filename_component(include_dir ${CMAKE_SOURCE_DIR}/include ABSOLUTE) + + set(${output} ${include_dir} ${generated_sources_dir} PARENT_SCOPE) +endfunction() + +function(get_sources_dirs output) + get_filename_component(src_dir ${CMAKE_SOURCE_DIR}/src ABSOLUTE) + + set(${output} ${src_dir} PARENT_SCOPE) +endfunction() + +# }}} diff --git a/cmake/cxx.cmake b/cmake/cxx.cmake new file mode 100644 index 0000000..ecc0194 --- /dev/null +++ b/cmake/cxx.cmake @@ -0,0 +1,111 @@ +option(ENABLE_CCACHE "Enable ccache support" ON) +if(ENABLE_CCACHE) + find_program(BIN_CCACHE ccache) + mark_as_advanced(BIN_CCACHE) + + if(NOT BIN_CCACHE) + message_colored(STATUS "Couldn't locate ccache, disabling ccache..." "33") + else() + # Enable only if the binary is found + message_colored(STATUS "Using compiler cache ${BIN_CCACHE}" "32") + set(CMAKE_CXX_COMPILER_LAUNCHER ${BIN_CCACHE} CACHE STRING "") + endif() +endif() + +option(CXXLIB_CLANG "Link against libc++" OFF) +option(CXXLIB_GCC "Link against stdlibc++" OFF) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(THREADS_PREFER_PTHREAD_FLAG ON) + + +set(POLYBAR_FLAGS "" CACHE STRING "C++ compiler flags used for compiling polybar") + +list(APPEND cxx_base -Wall -Wextra -Wpedantic) +list(APPEND cxx_debug -DDEBUG -g2) +list(APPEND cxx_minsizerel "") +list(APPEND cxx_sanitize -O0 -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls) +list(APPEND cxx_coverage --coverage) + +list(APPEND cxx_linker_base "") +list(APPEND cxx_linker_minsizerel "") + +# Compiler flags +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag("-Wsuggest-override" HAS_SUGGEST_OVERRIDE) +if (HAS_SUGGEST_OVERRIDE) + list(APPEND cxx_base -Wsuggest-override) +endif() +unset(HAS_SUGGEST_OVERRIDE) + +if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + # Need dprintf() for FreeBSD 11.1 and older + # libinotify uses c99 extension, so suppress this error + list(APPEND cxx_base -D_WITH_DPRINTF -Wno-c99-extensions) + # Ensures that libraries from dependencies in LOCALBASE are used + list(APPEND cxx_linker_base -L/usr/local/lib) +endif() + +# Check compiler +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + list(APPEND cxx_base -Wno-error=parentheses-equality -Wno-zero-length-array) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.4.0") + message_colored(FATAL_ERROR "Compiler not supported (Requires clang-3.4+ or gcc-5.1+)" 31) + else() + message_colored(STATUS "Using supported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 32) + endif() +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + list(APPEND cxx_minsizerel -fdata-sections -ffunction-sections -flto) + list(APPEND cxx_linker_minsizerel -Wl,--gc-sections) + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1.0") + message_colored(FATAL_ERROR "Compiler not supported (Requires clang-3.4+ or gcc-5.1+)" 31) + else() + message_colored(STATUS "Using supported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}" 32) + endif() +else() + message_colored(WARNING "Using unsupported compiler ${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION} !" 31) +endif() + +# Set compiler and linker flags for preferred C++ library +if(CXXLIB_CLANG) + message_colored(STATUS "Linking against libc++" 32) + list(APPEND cxx_base -stdlib=libc++) + list(APPEND cxx_linker_base -lc++ -lc++abi) +elseif(CXXLIB_GCC) + message_colored(STATUS "Linking against libstdc++" 32) + list(APPEND cxx_linker_base -lstdc++) +endif() + +# Custom build type 'Coverage', inherits the debug flags +list(APPEND cxx_coverage ${cxx_debug} ${cxx_coverage}) +SET(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_COVERAGE}") +SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${CMAKE_EXE_LINKER_FLAGS_COVERAGE}") +SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${CMAKE_SHARED_LINKER_FLAGS_COVERAGE}") + +list(APPEND cxx_flags ${cxx_base}) +list(APPEND cxx_linker_flags ${cxx_linker_base}) + +if (CMAKE_BUILD_TYPE_UPPER STREQUAL "DEBUG") + list(APPEND cxx_flags ${cxx_debug}) +elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "MINSIZEREL") + list(APPEND cxx_flags ${cxx_minsizerel}) + list(APPEND cxx_linker_flags ${cxx_linker_minsizerel}) +elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "SANITIZE") + list(APPEND cxx_flags ${cxx_sanitize}) +elseif (CMAKE_BUILD_TYPE_UPPER STREQUAL "COVERAGE") + list(APPEND cxx_flags ${cxx_coverage}) +endif() + +string(REPLACE " " ";" polybar_flags_list "${POLYBAR_FLAGS}") +list(APPEND cxx_flags ${polybar_flags_list}) + +list(APPEND cxx_linker_flags ${cxx_flags}) + +string(REPLACE ";" " " cxx_flags_str "${cxx_flags}") +string(REPLACE ";" " " cxx_linker_flags_str "${cxx_linker_flags}") + +# TODO use target_link_options once min cmake version is >= 3.13 +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${cxx_linker_flags_str}") diff --git a/cmake/libpoly.cmake b/cmake/libpoly.cmake new file mode 100644 index 0000000..d7ec359 --- /dev/null +++ b/cmake/libpoly.cmake @@ -0,0 +1,106 @@ +# Sets up options and dependencies for libpoly + + +# Automatically enable all optional dependencies that are available on the machine +checklib(ENABLE_ALSA "pkg-config" alsa) +checklib(ENABLE_CURL "pkg-config" libcurl) +checklib(ENABLE_I3 "binary" i3) +checklib(ENABLE_MPD "pkg-config" libmpdclient) +checklib(WITH_LIBNL "pkg-config" libnl-genl-3.0) +if(WITH_LIBNL) + checklib(ENABLE_NETWORK "pkg-config" libnl-genl-3.0) + set(WIRELESS_LIB "libnl") +else() + checklib(ENABLE_NETWORK "cmake" Libiw) + set(WIRELESS_LIB "wireless-tools") +endif() +checklib(ENABLE_PULSEAUDIO "pkg-config" libpulse) +checklib(WITH_XKB "pkg-config" xcb-xkb) +checklib(WITH_XRM "pkg-config" xcb-xrm) +checklib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12") +checklib(WITH_XCURSOR "pkg-config" "xcb-cursor") + +option(ENABLE_ALSA "Enable alsa support" ON) +option(ENABLE_CURL "Enable curl support" ON) +option(ENABLE_I3 "Enable i3 support" ON) +option(ENABLE_MPD "Enable mpd support" ON) +option(WITH_LIBNL "Use netlink interface for wireless" ON) +option(ENABLE_NETWORK "Enable network support" ON) +option(ENABLE_XKEYBOARD "Enable xkeyboard support" ON) +option(ENABLE_PULSEAUDIO "Enable PulseAudio support" ON) + +option(WITH_XRANDR_MONITORS "xcb-randr monitor support" ON) +option(WITH_XKB "xcb-xkb support" ON) +option(WITH_XRM "xcb-xrm support" ON) +option(WITH_XCURSOR "xcb-cursor support" ON) + +option(DEBUG_LOGGER "Trace logging" ON) + +if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG) + option(DEBUG_LOGGER_VERBOSE "Trace logging (verbose)" OFF) + option(DEBUG_HINTS "Debug clickable areas" OFF) + option(DEBUG_WHITESPACE "Debug whitespace" OFF) + option(DEBUG_FONTCONFIG "Debug fontconfig" OFF) +endif() + +# Load all packages for enabled components + +find_package(Threads REQUIRED) +find_package(CairoFC REQUIRED) + +find_package(LibUV 1.3.0 REQUIRED) + +if (ENABLE_ALSA) + find_package(ALSA REQUIRED) +endif() + +if (ENABLE_CURL) + find_package(CURL REQUIRED) +endif() + +if (ENABLE_MPD) + find_package(LibMPDClient REQUIRED) + set(MPD_VERSION ${LibMPDClient_VERSION}) +endif() + +if (ENABLE_NETWORK) + if(WITH_LIBNL) + find_package(LibNlGenl3 REQUIRED) + set(NETWORK_LIBRARY_VERSION ${LibNlGenl3_VERSION}) + else() + find_package(Libiw REQUIRED) + endif() +endif() + +if (ENABLE_PULSEAUDIO) + find_package(LibPulse REQUIRED) + set(PULSEAUDIO_VERSION ${LibPulse_VERSION}) +endif() + +# xcomposite is required +list(APPEND XORG_EXTENSIONS COMPOSITE) +if (WITH_XKB) + list(APPEND XORG_EXTENSIONS XKB) +endif() +if (WITH_XCURSOR) + list(APPEND XORG_EXTENSIONS CURSOR) +endif() +if (WITH_XRM) + list(APPEND XORG_EXTENSIONS XRM) +endif() + +# Set min xrandr version required +if (WITH_XRANDR_MONITORS) + set(XRANDR_VERSION "1.12") +else () + set(XRANDR_VERSION "") +endif() + +# Randr is required. Searches for randr only because we may do a version check +find_package(Xcb ${XRANDR_VERSION} REQUIRED COMPONENTS RANDR) +find_package(Xcb REQUIRED COMPONENTS ${XORG_EXTENSIONS}) + +# FreeBSD Support +if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + find_package(LibInotify REQUIRED) +endif() diff --git a/cmake/modules/FindALSA.cmake b/cmake/modules/FindALSA.cmake new file mode 100644 index 0000000..742f8ea --- /dev/null +++ b/cmake/modules/FindALSA.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `ALSA::ALSA` if alsa is found +# +# Defines the following Variables (see find_package_impl for more info): +# ALSA_FOUND +# ALSA_INCLUDE_DIR +# ALSA_INCLUDE_DIRS +# ALSA_LIBRARY +# ALSA_LIBRARIES +# ALSA_VERSION +find_package_impl("alsa" "ALSA" "alsa/asoundlib.h") + +if(ALSA_FOUND AND NOT TARGET ALSA::ALSA) + create_imported_target("ALSA::ALSA" "${ALSA_INCLUDE_DIR}" "${ALSA_LIBRARY}") +endif() diff --git a/cmake/modules/FindCURL.cmake b/cmake/modules/FindCURL.cmake new file mode 100644 index 0000000..2d13b38 --- /dev/null +++ b/cmake/modules/FindCURL.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `CURL::libcurl` if libcurl is found +# +# Defines the following Variables (see find_package_impl for more info): +# CURL_FOUND +# CURL_INCLUDE_DIR +# CURL_INCLUDE_DIRS +# CURL_LIBRARY +# CURL_LIBRARIES +# CURL_VERSION +find_package_impl("libcurl" "CURL" "curl/curl.h") + +if(CURL_FOUND AND NOT TARGET CURL::libcurl) + create_imported_target("CURL::libcurl" "${CURL_INCLUDE_DIR}" "${CURL_LIBRARY}") +endif() diff --git a/cmake/modules/FindCairoFC.cmake b/cmake/modules/FindCairoFC.cmake new file mode 100644 index 0000000..a6928e3 --- /dev/null +++ b/cmake/modules/FindCairoFC.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `Cairo::CairoFC` if cairo-fc is found +# +# Defines the following Variables (see find_package_impl for more info): +# CairoFC_FOUND +# CairoFC_INCLUDE_DIR +# CairoFC_INCLUDE_DIRS +# CairoFC_LIBRARY +# CairoFC_LIBRARIES +# CairoFC_VERSION +find_package_impl("cairo-fc" "CairoFC" "") + +if(CairoFC_FOUND AND NOT TARGET Cairo::CairoFC) + create_imported_target("Cairo::CairoFC" "${CairoFC_INCLUDE_DIR}" "${CairoFC_LIBRARY}") +endif() diff --git a/cmake/modules/FindLibInotify.cmake b/cmake/modules/FindLibInotify.cmake new file mode 100644 index 0000000..9c61d11 --- /dev/null +++ b/cmake/modules/FindLibInotify.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `LibInotify::LibInotify` if libinotify is found +# +# Defines the following Variables (see find_package_impl for more info): +# LibInotify_FOUND +# LibInotify_INCLUDE_DIR +# LibInotify_INCLUDE_DIRS +# LibInotify_LIBRARY +# LibInotify_LIBRARIES +# LibInotify_VERSION +find_package_impl("libinotify" "LibInotify" "") + +if(LibInotify_FOUND AND NOT TARGET LibInotify::LibInotify) + create_imported_target("LibInotify::LibInotify" "${LibInotify_INCLUDE_DIR}" "${LibInotify_LIBRARY}") +endif() diff --git a/cmake/modules/FindLibMPDClient.cmake b/cmake/modules/FindLibMPDClient.cmake new file mode 100644 index 0000000..7a75520 --- /dev/null +++ b/cmake/modules/FindLibMPDClient.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `LibMPDClient::LibMPDClient` if libmpdclient is found +# +# Defines the following Variables (see find_package_impl for more info): +# LibMPDClient_FOUND +# LibMPDClient_INCLUDE_DIR +# LibMPDClient_INCLUDE_DIRS +# LibMPDClient_LIBRARY +# LibMPDClient_LIBRARIES +# LibMPDClient_VERSION +find_package_impl("libmpdclient" "LibMPDClient" "mpd/player.h") + +if(LibMPDClient_FOUND AND NOT TARGET LibMPDClient::LibMPDClient) + create_imported_target("LibMPDClient::LibMPDClient" "${LibMPDClient_INCLUDE_DIR}" "${LibMPDClient_LIBRARY}") +endif() diff --git a/cmake/modules/FindLibNlGenl3.cmake b/cmake/modules/FindLibNlGenl3.cmake new file mode 100644 index 0000000..bca029c --- /dev/null +++ b/cmake/modules/FindLibNlGenl3.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `LibNlGenl3::LibNlGenl3` if libnl-genl-3.0 is found +# +# Defines the following Variables (see find_package_impl for more info): +# LibNlGenl3_FOUND +# LibNlGenl3_INCLUDE_DIR +# LibNlGenl3_INCLUDE_DIRS +# LibNlGenl3_LIBRARY +# LibNlGenl3_LIBRARIES +# LibNlGenl3_VERSION +find_package_impl("libnl-genl-3.0" "LibNlGenl3" "") + +if(LibNlGenl3_FOUND AND NOT TARGET LibNlGenl3::LibNlGenl3) + create_imported_target("LibNlGenl3::LibNlGenl3" "${LibNlGenl3_INCLUDE_DIR}" "${LibNlGenl3_LIBRARY}") +endif() diff --git a/cmake/modules/FindLibPulse.cmake b/cmake/modules/FindLibPulse.cmake new file mode 100644 index 0000000..bbd307d --- /dev/null +++ b/cmake/modules/FindLibPulse.cmake @@ -0,0 +1,14 @@ +# This module defines an imported target `LibPulse::LibPulse` if libpulse is found +# +# Defines the following Variables (see find_package_impl for more info): +# LibPulse_FOUND +# LibPulse_INCLUDE_DIR +# LibPulse_INCLUDE_DIRS +# LibPulse_LIBRARY +# LibPulse_LIBRARIES +# LibPulse_VERSION +find_package_impl("libpulse" "LibPulse" "pulse/version.h") + +if(LibPulse_FOUND AND NOT TARGET LibPulse::LibPulse) + create_imported_target("LibPulse::LibPulse" "${LibPulse_INCLUDE_DIR}" "${LibPulse_LIBRARY}") +endif() diff --git a/cmake/modules/FindLibUV.cmake b/cmake/modules/FindLibUV.cmake new file mode 100644 index 0000000..e5e40bb --- /dev/null +++ b/cmake/modules/FindLibUV.cmake @@ -0,0 +1,13 @@ +# This module defines +# LibUV_FOUND +# LibUV_INCLUDE_DIR +# LibUV_INCLUDE_DIRS +# LibUV_LIBRARY +# LibUV_LIBRARIES +# LibUV_VERSION + +find_package_impl("libuv" "LibUV" "uv.h") + +if(LibUV_FOUND AND NOT TARGET LibUV::LibUV) + create_imported_target("LibUV::LibUV" "${LibUV_INCLUDE_DIR}" "${LibUV_LIBRARY}") +endif() diff --git a/cmake/modules/FindLibiw.cmake b/cmake/modules/FindLibiw.cmake new file mode 100644 index 0000000..43405e0 --- /dev/null +++ b/cmake/modules/FindLibiw.cmake @@ -0,0 +1,21 @@ +# This module defines +# LIBIW_FOUND - whether the libiw library was found +# LIBIW_LIBRARIES - the libiw library +# LIBIW_INCLUDE_DIR - the include path of the libiw library + +find_library(LIBIW_LIBRARY iw) + +if(LIBIW_LIBRARY) + set(LIBIW_LIBRARIES ${LIBIW_LIBRARY}) +endif(LIBIW_LIBRARY) + +find_path(LIBIW_INCLUDE_DIR NAMES iwlib.h) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libiw DEFAULT_MSG LIBIW_LIBRARY LIBIW_INCLUDE_DIR) + +mark_as_advanced(LIBIW_INCLUDE_DIR LIBIW_LIBRARY) + +if(Libiw_FOUND AND NOT TARGET Libiw::Libiw) + create_imported_target("Libiw::Libiw" "${LIBIW_INCLUDE_DIR}" "${LIBIW_LIBRARIES}") +endif() diff --git a/cmake/modules/FindXcb.cmake b/cmake/modules/FindXcb.cmake new file mode 100644 index 0000000..064359e --- /dev/null +++ b/cmake/modules/FindXcb.cmake @@ -0,0 +1,59 @@ +# Loads multiple XCB components +# Version checks will be made against all requested components +# +# For each component ${comp} it does the following: +# +# Defines an imported target `Xcb::${comp}` if xcb-${comp} is found +# +# Defines the following Variables (see find_package_impl for more info): +# Xcb_${comp}_FOUND +# Xcb_${comp}_INCLUDE_DIR +# Xcb_${comp}_INCLUDE_DIRS +# Xcb_${comp}_LIBRARY +# Xcb_${comp}_LIBRARIES +# Xcb_${comp}_VERSION + +# This script only supports the following components of XCB +set(XCB_known_components + XCB + RANDR + COMPOSITE + XKB + XRM + CURSOR) + +# Deducing header from the name of the component +foreach(_comp ${XCB_known_components}) + string(TOLOWER "${_comp}" _lc_comp) + set(XCB_${_comp}_pkg_config "xcb-${_lc_comp}") + set(XCB_${_comp}_header "xcb/${_lc_comp}.h") +endforeach() +# Exception cases +set(XCB_XRM_header "xcb/xcb_xrm.h") +set(XCB_CURSOR_header "xcb/xcb_cursor.h") + +foreach(_comp ${Xcb_FIND_COMPONENTS}) + if (NOT ${_comp} IN_LIST XCB_known_components) + message(FATAL_ERROR "Unknow component \"${_comp}\" of XCB") + endif() + + # Forward the different find options set for FindXcb to the individual + # components. This is required because find_package_handle_standard_args in + # find_package_impl uses these variables for version checks and other things. + set(Xcb_${_comp}_FIND_VERSION ${Xcb_FIND_VERSION}) + set(Xcb_${_comp}_FIND_QUIETLY ${Xcb_FIND_QUIETLY}) + set(Xcb_${_comp}_FIND_REQUIRED ${Xcb_FIND_REQUIRED}) + + # Bypass developer warning that the first argument to + # find_package_handle_standard_args (Xcb_...) does not match the name of the + # calling package (Xcb) + # https://cmake.org/cmake/help/v3.17/module/FindPackageHandleStandardArgs.html + set(FPHSA_NAME_MISMATCHED TRUE) + find_package_impl(${XCB_${_comp}_pkg_config} "Xcb_${_comp}" "${XCB_${_comp}_header}") + + if(Xcb_${_comp}_FOUND AND NOT TARGET Xcb::${_comp}) + create_imported_target("Xcb::${_comp}" "${Xcb_${_comp}_INCLUDE_DIRS}" "${Xcb_${_comp}_LIBRARIES}") + elseif(NOT Xcb_${_comp}_FOUND AND Xcb_FIND_REQUIRED) + message(FATAL_ERROR "Xcb: Required component \"${_comp}\" was not found") + endif() +endforeach() diff --git a/cmake/templates/uninstall.cmake.in b/cmake/templates/uninstall.cmake.in new file mode 100644 index 0000000..79e6e89 --- /dev/null +++ b/cmake/templates/uninstall.cmake.in @@ -0,0 +1,23 @@ +set(INSTALL_MANIFEST "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +if(NOT EXISTS ${INSTALL_MANIFEST}) + message(FATAL_ERROR "Cannot find install manifest: ${INSTALL_MANIFEST}") +endif() + +file(READ ${INSTALL_MANIFEST} files) +string(REGEX REPLACE "\n" ";" files "${files}") +list(REVERSE files) + +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(EXISTS "$ENV{DESTDIR}${file}") + execute_process(COMMAND "@CMAKE_COMMAND@" + -E remove "$ENV{DESTDIR}${file}" + OUTPUT_VARIABLE rm_out + RESULT_VARIABLE rm_retval) + if(NOT ${rm_retval} EQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif() + else() + message(STATUS "File $ENV{DESTDIR}${file} does not exist") + endif() +endforeach() diff --git a/common/ci/configure.sh b/common/ci/configure.sh new file mode 100755 index 0000000..9700ac1 --- /dev/null +++ b/common/ci/configure.sh @@ -0,0 +1,45 @@ +#!/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}" \ + -DPOLYBAR_FLAGS="${CXXFLAGS} -Werror" \ + -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \ + -DBUILD_TESTS:BOOL="${BUILD_TESTS:-OFF}" \ + -DBUILD_DOC:BOOL=OFF \ + -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}" \ + .. diff --git a/common/ci/summary.sh b/common/ci/summary.sh new file mode 100755 index 0000000..a6bfcf8 --- /dev/null +++ b/common/ci/summary.sh @@ -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}" diff --git a/common/clang-format.sh b/common/clang-format.sh new file mode 100755 index 0000000..0a912c8 --- /dev/null +++ b/common/clang-format.sh @@ -0,0 +1,20 @@ +#!/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 "$@" diff --git a/common/clang-tidy.sh b/common/clang-tidy.sh new file mode 100755 index 0000000..f0de51f --- /dev/null +++ b/common/clang-tidy.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +main() { + if [ $# -lt 2 ]; then + echo "$0 build_path [-fix] DIR..." 1>&2 + exit 1 + fi + + args="-p $1"; shift + + if [ "$1" = "-fix" ]; then + args="${args} -fix"; shift + fi + + # Search paths + search="${*:-.}" + + echo "$0 in $search" + + # shellcheck disable=2086 + find $search -iname "*.cpp" \ + -exec printf "\\033[32;1m** \\033[0mProcessing %s\\n" {} \; \ + -exec clang-tidy $args {} \; +} + +main "$@" diff --git a/contrib/bash/CMakeLists.txt b/contrib/bash/CMakeLists.txt new file mode 100644 index 0000000..7b18a0d --- /dev/null +++ b/contrib/bash/CMakeLists.txt @@ -0,0 +1,6 @@ +# +# Bash completion template +# +install(FILES polybar + DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions + COMPONENT tools) diff --git a/contrib/bash/polybar b/contrib/bash/polybar new file mode 100644 index 0000000..a071ac9 --- /dev/null +++ b/contrib/bash/polybar @@ -0,0 +1,107 @@ +_polybar_default_file() { + local suffix=/polybar/config.ini + + local home_path=${XDG_CONFIG_HOME:-$HOME/.config}${suffix} + local etc_xdg_path=${XDG_CONFIG_DIRS:-/etc/xdg}${suffix} + local etc_path=/etc${suffix} + + if [ -r "$home_path" ]; then + echo "$home_path" + elif [ -r "$etc_xdg_path" ]; then + echo "$etc_xdg_path" + elif [ -r "$etc_path" ]; then + echo "$etc_path" + fi +} + +_polybar_config_file() { + for ((i = 0; i < COMP_CWORD; i++)); do + case ${COMP_WORDS[i]} in + --config) + echo "${COMP_WORDS[i + 2]}" + return + ;; + -c) + echo "${COMP_WORDS[i + 1]}" + return + ;; + esac + done + + _polybar_default_file +} + +_polybar_bars() { + local config_file=$(_polybar_config_file) + + if [ -r "$config_file" ]; then + sed -nE 's|[[:space:]]*\[bar/([^\]+)\][[:space:]]*$|\1|p' "$config_file" + fi +} + +_polybar() { + local options='-h --help + -v --version + -l --log= + -q --quiet + -c --config= + -r --reload + -d --dump= + -m --list-monitors + -M --list-all-monitors + -w --print-wmname + -s --stdout + -p --png=' + + local log_levels='error + warning + notice + info + trace' + + COMPREPLY=() + + local cur=${COMP_WORDS[COMP_CWORD]} + case "$cur" in + -*) + COMPREPLY=( $(compgen -W "$options" -- "$cur") ) + ;; + *) + local prev=${COMP_WORDS[COMP_CWORD - 1]} + if [ "$prev" = "=" ]; then + prev=${COMP_WORDS[COMP_CWORD - 2]} + fi + + case "$prev" in + -l|--log) + COMPREPLY=( $(compgen -W "$log_levels" -- "$cur") ) + return 0 + ;; + -c|--config) + COMPREPLY=( $(compgen -f "$cur") ) + return 0 + ;; + -p|--png) + COMPREPLY=( $(compgen -f -X "!*.png" "$cur") ) + return 0 + ;; + -d|--dump) + return 0 + ;; + *) + COMPREPLY=( $(compgen -W "$options $(_polybar_bars)" -- "$cur") ) + ;; + esac + esac + + for ((i = 0; i < ${#COMPREPLY[@]}; i++)); do + case ${COMPREPLY[i]} in + --*=) ;; + -*) COMPREPLY[i]+=" " + esac + done + + return 0 +} + +complete -o filenames -o noquote -o nospace -F _polybar polybar diff --git a/contrib/polybar-git.aur/PKGBUILD b/contrib/polybar-git.aur/PKGBUILD new file mode 100644 index 0000000..b280cac --- /dev/null +++ b/contrib/polybar-git.aur/PKGBUILD @@ -0,0 +1,44 @@ +# Maintainer: Patrick Ziegler +_pkgname=polybar +pkgname="${_pkgname}-git" +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=("libuv" "cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm" + "xcb-util-cursor" "alsa-lib" "libpulse" "libmpdclient" "libnl" + "jsoncpp" "curl") +optdepends=("i3-wm: i3 module support" + "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" + "python-packaging" "i3-wm") +provides=("polybar") +conflicts=("polybar") +install="${_pkgname}.install" +source=("${_pkgname}::git+${url}.git") +sha256sums=("SKIP") + +pkgver() { + git -C "${_pkgname}" describe --long --tags | sed "s/-/.r/;s/-/./g" +} + +prepare() { + git -C "${_pkgname}" submodule update --init --recursive + mkdir -p "${_pkgname}/build" +} + +build() { + cd "${_pkgname}/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 "${_pkgname}/build" --target install -- DESTDIR="${pkgdir}" + install -Dm644 "${_pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${_pkgname}/LICENSE" +} diff --git a/contrib/polybar.aur/PKGBUILD b/contrib/polybar.aur/PKGBUILD new file mode 100644 index 0000000..98feff2 --- /dev/null +++ b/contrib/polybar.aur/PKGBUILD @@ -0,0 +1,36 @@ +# Maintainer: Patrick Ziegler +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" +} diff --git a/contrib/vim/autoload/ft/cpphpp.vim b/contrib/vim/autoload/ft/cpphpp.vim new file mode 100644 index 0000000..2176abb --- /dev/null +++ b/contrib/vim/autoload/ft/cpphpp.vim @@ -0,0 +1,19 @@ +" +" Get the filename of the swap file +" +func! ft#cpphpp#GetFilename() + let ext = expand('%:e') + let root = expand('%:p:r') + if (ext == 'cpp') + return fnameescape(substitute(root, '\(src/.*/\)\?src/', '\1include/', '') . '.hpp') + elseif (ext == 'hpp') + return fnameescape(substitute(root, '\(include/.*/\)\?include/', '\1src/', '') . '.cpp') + endif +endfunc + +" +" Swap between source/header using given cmd +" +func! ft#cpphpp#Swap(cmd) + execute a:cmd . ' ' . ft#cpphpp#GetFilename() +endfunc diff --git a/contrib/vim/ftplugin/cpp.vim b/contrib/vim/ftplugin/cpp.vim new file mode 100644 index 0000000..66eebfd --- /dev/null +++ b/contrib/vim/ftplugin/cpp.vim @@ -0,0 +1,8 @@ +" Swap between source/header +nnoremap af :call ft#cpphpp#Swap('edit') +nnoremap as :call ft#cpphpp#Swap('new') +nnoremap av :call ft#cpphpp#Swap('vnew') + +" Code formatting using clang-format +set formatprg=/usr/bin/clang-format +nmap :ClangFormat diff --git a/contrib/vim/ftplugin/dosini.vim b/contrib/vim/ftplugin/dosini.vim new file mode 100644 index 0000000..c36e41e --- /dev/null +++ b/contrib/vim/ftplugin/dosini.vim @@ -0,0 +1,11 @@ +" +" Enables syntax folding for the configuration file. +" Removes the need to clutter the file with fold markers. +" +" Put the file in $VIM/after/syntax/dosini.vim +" +syn region dosiniSection start="^\[" end="\(\n\+\[\)\@=" contains=dosiniLabel,dosiniHeader,dosiniComment keepend fold +setlocal foldmethod=syntax + +" Uncomment to start with folds open +"setlocal foldlevel=20 diff --git a/contrib/zsh/CMakeLists.txt b/contrib/zsh/CMakeLists.txt new file mode 100644 index 0000000..93e010e --- /dev/null +++ b/contrib/zsh/CMakeLists.txt @@ -0,0 +1,6 @@ +# +# Zsh completion template +# +install(FILES _polybar _polybar_msg + DESTINATION ${CMAKE_INSTALL_DATADIR}/zsh/site-functions + COMPONENT tools) diff --git a/contrib/zsh/_polybar b/contrib/zsh/_polybar new file mode 100644 index 0000000..f02989c --- /dev/null +++ b/contrib/zsh/_polybar @@ -0,0 +1,61 @@ +#compdef polybar +# +# Completion for polybar (https://github.com/polybar/polybar) +# jaagr +# +_polybar() { + local L='-l --log' + local Q='-q --quiet' + local C='-c --config' + local R='-r --reload' + local D='-d --dump' + local M='-m --list-monitors' + local MM='-M --list-all-monitors' + local W='-w --print-wmname' + local S='-s --stdout' + + _arguments -n : \ + '(-)'{-h,--help}'[Display help text and exit]' \ + '(-)'{-v,--version}'[Display build details and exit]' \ + "($L $Q)"{-l,--log=}'[Set the logging verbosity (default: notice)]:verbosity level:(error warning notice info trace)' \ + "($L $Q)"{-q,--quiet}'[Be quiet (will override -l)]' \ + "($C)"{-c,--config=}'[Path to the configuration file]:configuration file:_files' \ + "($R)"{-r,--reload}'[Reload when the configuration has been modified]' \ + "($D $R $M $W $S)"{-d,--dump=}'[Print parameter value in bar section and exit]:parameter name' \ + "($MM $M $D $R $W $S)"{-m,--list-monitors}'[Print list of available monitors (Excluding cloned monitors) and exit]' \ + "($MM $M $D $R $W $S)"{-M,--list-all-monitors}'[Print list of all available monitors (Including cloned monitors) and exit]' \ + "($W $R $D $M $S)"{-w,--print-wmname}'[Print the generated WM_NAME and exit]' \ + "($S)"{-s,--stdout}'[Output data to stdout instead of drawing the X window]' \ + '::bar name:_polybar_list_names' +} + +(( $+functions[_polybar_default_file] )) || _polybar_default_file() { + local suffix=/polybar/config.ini + + local home_path=${XDG_CONFIG_HOME:-$HOME/.config}${suffix} + local etc_xdg_path=${XDG_CONFIG_DIRS:-/etc/xdg}${suffix} + local etc_path=/etc${suffix} + + if [ -r "$home_path" ]; then + echo "$home_path" + elif [ -r "$etc_xdg_path" ]; then + echo "$etc_xdg_path" + elif [ -r "$etc_path" ]; then + echo "$etc_path" + fi +} + +(( $+functions[_polybar_list_names] )) || _polybar_list_names() { + local conf + if (( $+opt_args[-c] )); then + conf=${(e)opt_args[-c]} + elif (( $+opt_args[--config] )); then + conf=${(e)opt_args[--config]} + else + conf=$(_polybar_default_file) + fi + local names; names=(${(f)"$(sed -nE 's|[[:space:]]*\[bar/([^\]+)\][[:space:]]*$|\1|p' ${conf} 2>/dev/null)"}) + _describe -t names 'configuration name' names +} + +_polybar "$@" diff --git a/contrib/zsh/_polybar_msg b/contrib/zsh/_polybar_msg new file mode 100644 index 0000000..946c464 --- /dev/null +++ b/contrib/zsh/_polybar_msg @@ -0,0 +1,32 @@ +#compdef polybar-msg +# +# Completion for polybar-msg (https://github.com/polybar/polybar) +# jaagr +# +_polybar_msg() { + integer ret=1 + + _arguments -n : \ + '-p[Process id of target instance]:process id:_polybar_msg_pids' \ + '(-p)1:message type:(action cmd hook)' \ + '*:: :->args' + + case $state in + args) + case $words[1] in + hook) _arguments ':module name:' ':hook index:'; ret=0 ;; + action) _arguments ':action payload:'; ret=0 ;; + cmd) _arguments ':command payload:(show hide toggle restart quit)'; ret=0 ;; + esac + ;; + esac + + return $ret +} + +(( $+functions[_polybar_msg_pids] )) || _polybar_msg_pids() { + local pids; pids=(${(f)"$(ls -1 /tmp/polybar_mqueue.* | egrep -o '[0-9]+$')"}) + _describe -t pids 'process id of target instance' pids +} + +_polybar_msg "$@" diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +build diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..abecc6b --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,80 @@ +set(SPHINX_BUILD "sphinx-build" CACHE STRING "Name/Path of the sphinx-build executable to use.") +set(SPHINX_FLAGS "" CACHE STRING "Flags to pass to sphinx-build") + +find_program(BIN_SPHINX "${SPHINX_BUILD}") + +if(NOT BIN_SPHINX) + message(FATAL_ERROR "sphinx-build executable '${SPHINX_BUILD}' not found.") +endif() + +separate_arguments(sphinx_flags UNIX_COMMAND "${SPHINX_FLAGS}") + +set(doc_path "${CMAKE_CURRENT_SOURCE_DIR}") + +# Configures conf.py in the current folder and puts it in the build folder +configure_file(conf.py conf.py @ONLY) + +# We want to run `sphinx-build` with the following builders +if (BUILD_DOC_HTML) + list(APPEND doc_builders "html") +endif() + +if (BUILD_DOC_MAN) + list(APPEND doc_builders "man") +endif() + +# Name of all documentation targets +set(doc_targets "") + +foreach(builder ${doc_builders}) + set(doc_target "doc_${builder}") + set(builder_log "builder-${builder}.log") + add_custom_target(${doc_target} + COMMAND ${BIN_SPHINX} + -b ${builder} + # conf.py dir + -c "${CMAKE_CURRENT_BINARY_DIR}" + -d "${CMAKE_CURRENT_BINARY_DIR}/doctrees" + -n + ${sphinx_flags} + # Documentation source file dir + "${CMAKE_CURRENT_SOURCE_DIR}" + # Output dir + "${CMAKE_CURRENT_BINARY_DIR}/${builder}" > ${builder_log} + COMMENT "sphinx-build ${builder}: see doc/${builder_log}") + + list(APPEND doc_targets ${doc_target}) +endforeach() + +# Dummy target that depends on all documentation targets +add_custom_target(doc ALL DEPENDS ${doc_targets}) + +if (BUILD_DOC_HTML) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT doc + PATTERN ".buildinfo" EXCLUDE) +endif() + +install(FILES ${CMAKE_SOURCE_DIR}/CHANGELOG.md + DESTINATION ${CMAKE_INSTALL_DOCDIR} + COMPONENT doc) + +install(FILES ${CMAKE_CURRENT_LIST_DIR}/config.ini + DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples + COMPONENT doc) + +if (BUILD_DOC_MAN) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar.1 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 + COMPONENT doc) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar-msg.1 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 + COMPONENT doc) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/polybar.5 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man5 + COMPONENT doc) +endif() + diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..16e7f9d --- /dev/null +++ b/doc/README.md @@ -0,0 +1,19 @@ +Polybar Manual +============== + +The official polybar documentation lives here. + +The html documentation and man pages are built automatically when you build with cmake (cmake creates the custom +target `doc`). + +## Preview Locally +The documentation uses [Sphinx](https://www.sphinx-doc.org/en/stable/) to generate the documentation, so you will need to +have that installed. + +If you build polybar normally while having Sphinx installed during configuration, the documentation will be enabled and +built as well. Building the documentation can be disabled by passing `-DBUILD_DOC=OFF` to `cmake`. + +Once configured, all of the documentation can be generated with `make doc` or use `make doc_html` or `make doc_man` to +only generate the html documentation or the man pages respectively. + +The HTML documentation is in `doc/html/index.html` in your build directory and the man pages are in `doc/man`. diff --git a/doc/_static/.gitignore b/doc/_static/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/doc/_static/default.png b/doc/_static/default.png new file mode 100644 index 0000000000000000000000000000000000000000..2b94b1c6d95ff5af6db5d7aff13cd5501a0e79c8 GIT binary patch literal 18104 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 FV1m>_KNbK0 literal 0 HcmV?d00001 diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 0000000..b6672c7 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# https://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +from pathlib import Path +import datetime +import sphinx +import packaging.version + +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)) + +# -- Project information ----------------------------------------------------- + +project = 'Polybar User Manual' +copyright = '2016-{}, Michael Carlberg & contributors'.format( + datetime.datetime.now().year + ) +author = 'Polybar Team' + +# is whether we are on readthedocs.io +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if on_rtd: + # On readthedocs, cmake isn't run so the version string isn't available + version = os.environ.get('READTHEDOCS_VERSION', None) +else: + # The short X.Y version + version = '@APP_VERSION@' + +# The full version, including alpha/beta/rc tags +release = version + +# Set path to documentation +if on_rtd: + # On readthedocs conf.py is already in the doc folder + doc_path = '.' +else: + # In all other builds conf.py is configured with cmake and put into the + # build folder. + doc_path = '@doc_path@' + +# 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 +# number +version_txt = get_version(Path(doc_path).absolute().parent) + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = [doc_path + '/_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + +highlight_language = 'none' + +smartquotes = False + + +# -- 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 +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# 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, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = [doc_path + '/_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'polybardoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'polybar.tex', 'polybar Documentation', + 'Polybar Team', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +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.5', 'polybar', 'configuration file for polybar(1)', [], 5) +] + +man_make_section_directory = False + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'polybar', 'polybar Documentation', + author, 'polybar', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# The 'versionadded' and 'versionchanged' directives are overridden. +suppress_warnings = ['app.add_directive'] + +# 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. +# 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 +# mention unreleased changes. Because of that it's not that important that this +# is added to local builds. +if packaging.version.parse(sphinx.__version__) >= packaging.version.parse("1.8.5"): + + from typing import List + from docutils.nodes import Node + from sphinx.domains.changeset import VersionChange + + def setup(app): + app.add_directive('deprecated', VersionDirective) + app.add_directive('versionadded', VersionDirective) + app.add_directive('versionchanged', VersionDirective) + + class VersionDirective(VersionChange): + """ + Overwrites the Sphinx directive for versionchanged, versionadded, and + 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: + self.arguments[0] += " (unreleased)" + + return super().run() diff --git a/doc/config.ini b/doc/config.ini new file mode 100644 index 0000000..d407fe2 --- /dev/null +++ b/doc/config.ini @@ -0,0 +1,172 @@ +;========================================================== +; +; +; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗ +; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗ +; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝ +; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗ +; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║ +; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ +; +; +; To learn more about how to configure Polybar +; go to https://github.com/polybar/polybar +; +; The README contains a lot of information +; +;========================================================== + +[colors] +background = #282A2E +background-alt = #373B41 +foreground = #C5C8C6 +primary = #F0C674 +secondary = #8ABEB7 +alert = #A54242 +disabled = #707880 + +[bar/example] +width = 100% +height = 24pt +radius = 6 + +; dpi = 96 + +background = ${colors.background} +foreground = ${colors.foreground} + +line-size = 3pt + +border-size = 4pt +border-color = #00000000 + +padding-left = 0 +padding-right = 1 + +module-margin = 1 + +separator = | +separator-foreground = ${colors.disabled} + +font-0 = monospace;2 + +modules-left = xworkspaces xwindow +modules-right = filesystem pulseaudio xkeyboard memory cpu wlan eth date + +cursor-click = pointer +cursor-scroll = ns-resize + +enable-ipc = true + +; tray-position = right + +; wm-restack = generic +; wm-restack = bspwm +; wm-restack = i3 + +; override-redirect = true + +[module/xworkspaces] +type = internal/xworkspaces + +label-active = %name% +label-active-background = ${colors.background-alt} +label-active-underline= ${colors.primary} +label-active-padding = 1 + +label-occupied = %name% +label-occupied-padding = 1 + +label-urgent = %name% +label-urgent-background = ${colors.alert} +label-urgent-padding = 1 + +label-empty = %name% +label-empty-foreground = ${colors.disabled} +label-empty-padding = 1 + +[module/xwindow] +type = internal/xwindow +label = %title:0:60:...% + +[module/filesystem] +type = internal/fs +interval = 25 + +mount-0 = / + +label-mounted = %{F#F0C674}%mountpoint%%{F-} %percentage_used%% + +label-unmounted = %mountpoint% not mounted +label-unmounted-foreground = ${colors.disabled} + +[module/pulseaudio] +type = internal/pulseaudio + +format-volume-prefix = "VOL " +format-volume-prefix-foreground = ${colors.primary} +format-volume = + +label-volume = %percentage%% + +label-muted = muted +label-muted-foreground = ${colors.disabled} + +[module/xkeyboard] +type = internal/xkeyboard +blacklist-0 = num lock + +label-layout = %layout% +label-layout-foreground = ${colors.primary} + +label-indicator-padding = 2 +label-indicator-margin = 1 +label-indicator-foreground = ${colors.background} +label-indicator-background = ${colors.secondary} + +[module/memory] +type = internal/memory +interval = 2 +format-prefix = "RAM " +format-prefix-foreground = ${colors.primary} +label = %percentage_used:2%% + +[module/cpu] +type = internal/cpu +interval = 2 +format-prefix = "CPU " +format-prefix-foreground = ${colors.primary} +label = %percentage:2%% + +[network-base] +type = internal/network +interval = 5 +format-connected = +format-disconnected = +label-disconnected = %{F#F0C674}%ifname%%{F#707880} disconnected + +[module/wlan] +inherit = network-base +interface-type = wireless +label-connected = %{F#F0C674}%ifname%%{F-} %essid% %local_ip% + +[module/eth] +inherit = network-base +interface-type = wired +label-connected = %{F#F0C674}%ifname%%{F-} %local_ip% + +[module/date] +type = internal/date +interval = 1 + +date = %H:%M +date-alt = %Y-%m-%d %H:%M:%S + +label = %date% +label-foreground = ${colors.primary} + +[settings] +screenchange-reload = true +pseudo-transparency = true + +; vim:ft=dosini diff --git a/doc/dev/packaging.rst b/doc/dev/packaging.rst new file mode 100644 index 0000000..c0436b1 --- /dev/null +++ b/doc/dev/packaging.rst @@ -0,0 +1,88 @@ +Packaging Polybar +================= + +Do you want to package polybar for a distro? Great! Read this page to get +started. + +First Steps +----------- + +Before you get started, have a look at the `Packaging Label +`_ on our GitHub +repo and `Repology `_ to see if +polybar is already packaged for that distro or if there are efforts to do so. + +Even if a package already exists, it might still make sense for you to package +polybar in some cases. Some of these cases are: + +- The existing package is out-of-date and the packager is no longer able/willing + to continue maintaining the package (or they are simply not reachable + anymore). +- The existing package exist in some non-official repository and you are able to + introduce the package into the official package repository for the + distro/package manager. For example if there is a PPA providing polybar for + Ubuntu and you can add polybar to the official Ubuntu repositories, please do + :) + +The list above is not exhaustive, if you are unsure, feel free to ask in a new +GitHub issue or on `Gitter `_. Please also ask if you +run into any polybar related issues while packaging. + +Packaging +--------- + +If you haven't already, carefully read the `Compiling +`_ wiki page to make sure you +fully understand all the dependencies involved and how to build polybar +manually. + +We can't really tell you how to create a package for your distro, you need to +figure that out yourself. But we can give you some guidance on building polybar +for a package + +Gathering the Source Code +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Unless you are creating a package that tracks the ``master`` branch, don't clone +the git repository. We provide a tarball with all the required source code on +our `Release Page `_, use that in +your build. + +Configuring and Compiling +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + + Do not use the ``build.sh`` script for building polybar for your package. The + usage and flags of the script may change without notice and we don't consider + that a breaking change. + +You can mostly follow the instructions on the `wiki +`_ for how to +compile polybar, but there are some additional ``cmake`` arguments you might +want to use: + +- ``-DCMAKE_BUILD_TYPE=Release``: As of writing this is already the default, but + use it just to be on the safe side. +- ``-DCMAKE_INSTALL_PREFIX=/usr``: Without this all the polybar files will be + installed under ``/usr/local``. However, for packages it is often recommended + they directly install to ``/usr``. So this flag will install polybar to + ``/usr/bin/polybar`` instead of ``/usr/local/bin/polybar``. The packaging + guidelines for your distro may disagree with this, in that case be sure to + follow your distro's guidelines. + +Instead of ``sudo make install``, you will most likely want to use +``DESTDIR= make install``. That way the files will be installed into +```` instead of your filesystem root. + +Finishing Up +------------ + +Finally, subscribe to our `GitHub thread for package maintainers +`_ to get notified about new +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 +Started `_ section of our +README. + +Thank you very much for maintaining a polybar package! 🎉 diff --git a/doc/dev/release-workflow.rst b/doc/dev/release-workflow.rst new file mode 100644 index 0000000..8fd4dd2 --- /dev/null +++ b/doc/dev/release-workflow.rst @@ -0,0 +1,235 @@ +Release Workflow +================ + +We try to follow `Semantic Versioning `_ in this project. +Patch releases (e.g. ``3.3.X``) contain only bug fixes. Minor releases (e.g. +``3.X.0``) can have backwards-compatible features. And major releases ( +``X.0.0``) can introduce incompatible changes. + +.. note:: + + This document replaces the "`Release Guidelines + `_" on the wiki + that we used between 3.2.0 and 3.4.3. Starting with 3.5.0, we will follow + the workflow described here to publish releases. + +Polybar uses the `OneFlow +`_ +branching model for publishing new releases and introducing hotfixes. + +The way we accept code from contributors does not change: Contributors fork +polybar, commit their changes to a new branch and open a PR to get that branch +merged. +After reviewing and approving the changes, a maintainer "merges" the PR. +"Merging" is done in the GitHub UI by either rebasing or squashing the +changes. +Regular merging is disabled because we do not want merge a merge commit for +every PR. + +This document is mainly concerned with how to properly release a new version of +polybar. +For that reason this might not be of interest to you, if you are not a +maintainer, but feel free to read on anyway. + +Drafting a new Release +---------------------- + +There a two processes for how to draft a new release. The process for major and +minor versions is the same as they both are "regular" releases. +Patch releases are triggered by bugfixes that cannot wait until the next regular +release and have a slightly different workflow. + +Regular Releases (Major, Minor) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Regular releases are created once we find that ``master`` is in a stable state +and that there are enough new features to justify a new release. +A release branch ``release/X.Y.0`` is branched off of a commit on ``master`` +that contains all the features we want in the release, this branch is pushed to +the official repository. +For example for version ``3.5.0`` the branch ``release/3.5.0`` would be created: + +.. code-block:: shell + + git checkout -b release/3.5.0 + +The release branch should typically only exist for at most a few days. + +Hotfix Releases (Patch) +~~~~~~~~~~~~~~~~~~~~~~~ + +A hotfix release is created whenever we receive a fix for a bug that we believe +should be released immediately instead of it only being part of the next regular +release. +Generally any bugfix qualifies, but it is up to the maintainers to decide +whether a hotfix release should be created. + +The hotfix release branch ``hotfix/X.Y.Z`` is created by branching off at the +previous release tag (``X.Y.Z-1``). +For example, if the latest version is ``3.5.2``, the next hotfix will be on +branch ``hotfix/3.5.3``: + +.. code-block:: shell + + git checkout -b hotfix/3.5.3 3.5.2 + +Since the PRs for such bugfixes are often not created by maintainers, they will +often not be based on the latest release tag, but just be branched off +``master`` because contributors don't necessarily know about this branching +model and also may well not know whether a hotfix will be created for a certain +bugfix. + +.. TODO create contributor page that describes where to branch off. And link to + that page. + +In case a PR containing a bugfix that is destined for a patch release is not +branched off the previous release, a maintainer creates the proper release +branch and cherry-picks the bugfix commits. + +.. note:: + + 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 + a maintainer to create the release branch since they will also need to add a + `Release Commit`_ to it. + +Once the release branch is created and contains the right commits, the +maintainer should follow `Publishing a new Release`_ to finish this patch +release. + +If multiple bugfixes are submitted in close succession, they can all be +cherry-picked onto the same patch release branch to not create many individual +release with only a single fix. +The maintainer can also decide to leave the release branch for this patch +release open for a week in order to possibly combine multiple bugfixes into a +single release. + +Publishing a new Release +------------------------ + +The process for publishing a release is the same for all release types. It goes +as follows: + +* A `Release commit`_ is added to the tip of the release branch. +* 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 + commandline. +* A `draft release`_ is created in GitHub's release publishing tools +* After approval, the GitHub release publishing tool is used to publish the + release and tag the tip of the release branch (the release commit). +* After the tag is created, the release branch is manually merged into + ``master``. + Here it is vitally important that the history of the release branch does not + change and so we use ``git merge``. We do it manually because using ``git + merge`` is disabled on PRs. + +.. code-block:: shell + + git checkout master + git merge + git push origin + +* After the tag is created, the release branch can be deleted with ``git push + origin :``. +* Work through the `After-Release Checklist`_. + +Here ```` is either a ``release/X.Y.0`` branch or a +``hotfix/X.Y.Z`` branch. + +Release Commit +~~~~~~~~~~~~~~ + +When merging, a release commit must be at the tip of the release branch. + +The release commit needs to update the version number in: + +* ``version.txt`` + +The release commit must also finalize the `Changelog`_ for this release. + +Changelog +~~~~~~~~~ + +The ``CHANGELOG.md`` file at the root of the repo should already contain all the +changes for the upcoming release in a format based on +`keep a changelog `_. +For each release those changes should be checked to make sure we did not miss +anything. + +For all releases, a new section of the following form should be created below +the ``Unreleased`` section: + +.. code-block:: md + + ## [X.Y.Z] - YYYY-MM-DD + +In addition, the reference link for the release should be added and the +reference link for the unreleased section should be updated at the bottom of the +document: + +.. code-block:: md + + [Unreleased]: https://github.com/polybar/polybar/compare/X.Y.Z...HEAD + [X.Y.Z]: https://github.com/polybar/polybar/releases/tag/X.Y.Z + +Since the release tag doesn't exist yet, both of these links will be invalid +until the release is published. + +All changes from the ``Unreleased`` section that apply to this release should be +moved into the new release section. +For regular releases this is generally the entire ``Unreleased`` section, while +for patch releases it will only be a few entries. + +The contents of the release section can be copied into the draft release in +GitHub's release tool with a heading named ``## Changelog``. + +Since major releases generally break backwards compatibility in some way, their +changelog should also prominently feature precisely what breaking changes were +introduced. If suitable, maybe even separate documentation dedicated to the +migration should be written. + +Draft Release +~~~~~~~~~~~~~ + +On `GitHub `_ a new release +should be drafted. +The release targets the tip of the release branch (the release commit), the +name of the release and the tag is simply the release number. + +The content of the release message should contain the changelog copied from +``CHANGELOG.md`` under the heading ``## Changelog``. +In addition using GitHub's "Auto-generate release notes" feature, the list of +new contributors should be generated and put at the end of the release notes. +The generated list of PRs can be removed. + +After-Release Checklist +~~~~~~~~~~~~~~~~~~~~~~~ + +* Make sure all the new functionality is documented on the wiki +* Mark deprecated features appropriately (see `Deprecations`_) +* Remove all unreleased notes from the wiki (not for patch releases) +* Inform packagers of new release in `#1971 + `_. Mention any dependency + changes and any changes to the build workflow. Also mention any new files are + created by the installation. +* 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. +* 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 `_ + for the new release and move open issues (if any) to a later release. +* Activate the version on `Read the Docs + `_ and deactivate all + previous versions for the same minor release (e.g. for 3.5.4, deactivate all + other 3.5.X versions). + +Deprecations +~~~~~~~~~~~~ + +If any publicly facing part of polybar is being deprecated, it should be marked +as such in the code, through warnings/errors in the log, and by comments in the +wiki. Every deprecated functionality is kept until the next major release and +removed there, unless it has not been deprecated in a minor release before. diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000..b7ca577 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,45 @@ +Polybar Documentation +===================== + +.. note:: This is still very much a work-in-progress. Most information is still + to be found on our `GitHub Wiki `_. + We will migrate the wiki content step-by-step. + + +Welcome to the official polybar documentation. + +.. toctree:: + :maxdepth: 1 + :caption: Content: + + user/actions + user/ipc + +.. toctree:: + :maxdepth: 1 + :caption: Manual Pages: + + man/polybar.1 + man/polybar-msg.1 + man/polybar.5 + +.. toctree:: + :maxdepth: 1 + :caption: For Contributors: + + dev/packaging + +.. toctree:: + :maxdepth: 1 + :caption: Developer Documentation: + + dev/release-workflow + +Getting Help +============ + +* `Polybar Wiki `_ +* `Gitter `_ +* `/r/polybar `_ on reddit +* ``#polybar`` on `irc.libera.chat:6697 `_ + diff --git a/doc/man/polybar-msg.1.rst b/doc/man/polybar-msg.1.rst new file mode 100644 index 0000000..0141b7a --- /dev/null +++ b/doc/man/polybar-msg.1.rst @@ -0,0 +1,75 @@ +polybar-msg(1) +============== + +SYNOPSIS +-------- +| **polybar-msg** [*OPTIONS*] **action** *action-string* +| **polybar-msg** [*OPTIONS*] **action** *module* *action* [*data*] +| **polybar-msg** [*OPTIONS*] **cmd** *command* + +DESCRIPTION +----------- +Polybar allows external control through *actions* and *commands*. +Actions control individual modules and commands control the bar itself. + +The full IPC documentation is linked at the end of this document. + +The available actions depend on the target module. +For actions, the payload is either a single action string or the module name, +the action name, and the optional data string specified separately. + +In order for **polybar-msg** being able to send a message to a running +**polybar** process, the bar must have IPC enabled and both **polybar-msg** and +**polybar** must run under the same user. + +OPTIONS +------- + +.. program:: polybar-msg + +.. option:: -h, --help + + Display help text and exit + +.. option:: -p PID + + Send message only to **polybar** process running under the given process ID. + If not specified, the message is sent to all running **polybar** processes. + +EXAMPLES +-------- + +**polybar-msg** **cmd** *quit* + Terminate all running **polybar** instances. + +**polybar-msg** **action** *mymodule* *module_hide* + +**polybar-msg** **action** "*#mymodule.module_hide*" + Hide the module named *mymodule*. + The first variant specifies the module and action names separately, the second uses an action string. + +AUTHORS +------- +| Polybar was created by Michael Carlberg and is currently maintained by Patrick Ziegler. +| Contributors can be listed on GitHub. + +REPORTING BUGS +-------------- +Report issues on GitHub + +SEE ALSO +-------- +.. only:: man + + :manpage:`polybar`\(1), + :manpage:`polybar`\(5) + + | IPC documentation: + + +.. only:: not man + + :doc:`polybar.1`, + :doc:`polybar.5` + + :doc:`/user/ipc` diff --git a/doc/man/polybar.1.rst b/doc/man/polybar.1.rst new file mode 100644 index 0000000..7f9bacd --- /dev/null +++ b/doc/man/polybar.1.rst @@ -0,0 +1,92 @@ +polybar(1) +========== + +SYNOPSIS +-------- +**polybar** [*OPTIONS*]... [*BAR*] + +DESCRIPTION +----------- +Polybar aims to help users build beautiful and highly customizable status bars for their desktop environment, without the need of having a black belt in shell scripting. +If the *BAR* argument is not provided and the configuration file only contains one bar definition, polybar will display this bar. + +OPTIONS +------- + +.. program:: polybar + +.. option:: -h, --help + + Display help text and exit + +.. option:: -v, --version + + Display build details and exit +.. option:: -l, --log=LEVEL + + | Set the logging verbosity (default: **notice**) + | *LEVEL* is one of: error, warning, notice, info, trace +.. option:: -q, --quiet + + Be quiet (will override -l) +.. option:: -c, --config=FILE + + Specify the path to the configuration file. By default, the configuration file is loaded from: + + * ``$XDG_CONFIG_HOME/polybar/config`` + * ``$XDG_CONFIG_HOME/polybar/config.ini`` + * ``$HOME/.config/polybar/config`` + * ``$HOME/.config/polybar/config.ini`` + * ``$XDG_CONFIG_DIRS/polybar/config.ini`` + * ``/etc/xdg/polybar/config.ini`` (only if ``XDG_CONFIG_DIRS`` is not set) + * ``/etc/polybar/config.ini`` +.. option:: -r, --reload + + Reload the application when the config file has been modified +.. option:: -d, --dump=PARAM + + Print the value of the specified parameter *PARAM* in bar section and exit +.. option:: -m, --list-monitors + + | Print list of available monitors and exit. + | If some monitors are cloned, this will exclude all but one of them. + | If polybar was compiled with RandR monitor support, only monitors are listed and not physical outputs. +.. option:: -M, --list-all-monitors + + | Print list of all available monitors and exit. + | This includes cloned monitors as well as both physical outputs and RandR monitors (if supported). + | Only the names listed here can be used as monitor names in polybar. +.. option:: -w, --print-wmname + + Print the generated *WM_NAME* and exit +.. option:: -s, --stdout + + Output the data to stdout instead of drawing it to the X window +.. option:: -p, --png=FILE + + Save png snapshot to *FILE* after running for 3 seconds + +AUTHORS +------- +| Polybar was created by Michael Carlberg and is currently maintained by Patrick Ziegler. +| Contributors can be listed on GitHub. + +REPORTING BUGS +-------------- +Report issues on GitHub + +SEE ALSO +-------- +.. only:: man + + :manpage:`polybar-msg`\(1), + :manpage:`polybar`\(5) + + +.. only:: not man + + :doc:`polybar-msg.1`, + :doc:`polybar.5` + +| Full documentation at: +| Project wiki: diff --git a/doc/man/polybar.5.rst b/doc/man/polybar.5.rst new file mode 100644 index 0000000..659c858 --- /dev/null +++ b/doc/man/polybar.5.rst @@ -0,0 +1,184 @@ +.. highlight:: ini + +polybar(5) +========== + +Description +----------- + +The polybar configuration file defines the behavior and look of polybar. It uses +a variant of the `INI `_ file format. +The exact syntax is described below but first a small snippet to get familiar +with the syntax: + +:: + + [section_name] + ; A comment + # Another comment + + background = #ff992a + width = 90% + monitor = HDMI-0 + + screenchange-reload = false + + ; Use double quotes if you want to keep the surrounding space. + text = " Some text " + +When started ``polybar`` will search for the config file in one of several +places in the following order: + +* If the ``-c`` or ``--config`` command line argument is specified, it will use + the path given there. +* ``$XDG_CONFIG_HOME/polybar/config`` +* ``$XDG_CONFIG_HOME/polybar/config.ini`` +* ``$HOME/.config/polybar/config`` +* ``$HOME/.config/polybar/config.ini`` +* ``$XDG_CONFIG_DIRS/polybar/config.ini`` +* ``/etc/xdg/polybar/config.ini`` (only if ``XDG_CONFIG_DIRS`` is not set) +* ``/etc/polybar/config.ini`` + +Syntax +------ + +The entire config is line-based so everything is constrained to a single line. +This means there are no multiline values or other multiline constructs (except +for sections). +Each line has one of four types: + +* Empty +* Comment +* Section Header +* Key + +Spaces at the beginning and end of each line will be ignored. + +.. note:: + + In this context "spaces" include the regular space character as well as the + tab character and any other character for which :manpage:`isspace(3)` returns + ``true`` (e.g. ``\r``). + +Any line that doesn't fit into one of these four types is a syntax error. + +.. note:: + + It is recommended that `section header` names and `key` names only use + alphanumeric characters as well as dashes (``-``), underscores (``_``) and + forward slashes (``/``). + + In practice all characters are allowed except for spaces and any of these: + ``"'=;#[](){}:.$\%`` + +Section Headers +^^^^^^^^^^^^^^^ + +Sections are used to group config options together. For example each module is +defined in its own section. + +A section is defined by placing the name of the section in square brackets +(``[`` and ``]``). For example: + +:: + + [module/wm] + +This declares a section with the name ``module/wm`` and all keys defined after +this line will belong to that section until a new section is declared. + +.. warning:: + The first non-empty and non-comment line in the main config file must be a + section header. It cannot be a key because that key would not belong to any + section. + +.. note:: + The following section names are reserved and cannot be used inside the config: + ``self``, ``root``, and ``BAR``. + +Keys +^^^^ + +Keys are defined by assigning a value to a name like this: + + +:: + + name = value + +This assigns ``value`` to the key ``name`` in whatever section this line is in. +Key names need to be unique per section. +If the value is enclosed by double-quotes (``"``), the quotes will be ignored. +So the following still assigns ``value`` to ``name``: + +:: + + name = "value" + +Spaces around the equal sign are ignored, the following are all equivalent: + +:: + + name=value + name = value + name = value + +Because spaces at the beginning and end of the line are also ignored, if you +want your value to begin and/or end with a space, the value needs to be enclosed +in double-quotes: + +:: + + name = " value " + +Here the value of the ``name`` key has a leading and trailing whitespace. + +To treat characters with special meaning as literal characters, you need to +prepend them with the backslash (``\``) escape character: + +:: + + name = "value\\value\\value" + +Value of this key ``name`` results in ``value\value\value``. + +.. note:: + + The only character with a special meaning right now is the backslash character + (``\``), which serves as the escape character. + More will be added in the future. + +Empty Lines & Comments +^^^^^^^^^^^^^^^^^^^^^^ + +Empty lines and comment lines are ignored when reading the config file, they do +not affect polybar's behavior. Comment lines start with either the ``;`` or the +``#`` character. + +.. note:: + + Inline comments are not supported. For example the following line does not end + with a comment, the value of ``name`` is actually set to ``value ; comment``: + + :: + + name = value ; comment + +AUTHORS +------- +| Polybar was created by Michael Carlberg and is currently maintained by Patrick Ziegler. +| Contributors can be listed on GitHub. + +SEE ALSO +-------- + +.. only:: man + + :manpage:`polybar`\(1), + :manpage:`polybar-msg`\(1) + + +.. only:: not man + + :doc:`polybar.1`, + :doc:`polybar-msg.1` diff --git a/doc/user/actions.rst b/doc/user/actions.rst new file mode 100644 index 0000000..24c6089 --- /dev/null +++ b/doc/user/actions.rst @@ -0,0 +1,457 @@ +Actions +======= + +.. versionadded:: 3.5.0 + +.. contents:: Table of Contents + :local: + +"Actions" are used to trigger certain behavior in modules. +For example, when you click on your volume module (pulseaudio or alsa), polybar +internally sends an action to that module that tells it to mute/unmute the +audio. + +These actions are not only used internally, but users can also send these +actions to polybar through `Inter Process Communication +`_ (IPC) to +trigger certain behavior in polybar modules. + +.. _action-string-format: + +Action String Format +-------------------- + +An action string follows the following format: + +:: + + #NAME.ACTION[.DATA] + +Where ``NAME`` is the name of the target module (not the type!) and ``ACTION`` +is the name of the action in that module. ``DATA`` is optional data attached to +an action (for example to say which menu level should be opened). + +For example the +`date module `_ supports +the ``toggle`` action to toggle between the regular and the alternative time and +date format. +If you have the following date module: + +.. code-block:: ini + + [module/mydate] + type = internal/date + ... + +The action string for toggling between the date formats would look like this: + +:: + + #mydate.toggle + +Note that we use the name of the module (``mydate``) and not the type. + +As an example for an action string with additional data, take the menu module: + +.. code-block:: ini + + [module/powermenu] + type = custom/menu + menu-0-0 = Poweroff + menu-0-0-exec = poweroff + menu-0-1 = Suspend + menu-0-1-exec = systemctl suspend + +The action name to open a certain menu level is ``open``, so to open level 0 +(`menu-0`), the action string additionally has the level attached to it: + +:: + + #powermenu.open.0 + +Triggering Actions +------------------ + +Most modules already use action strings to trigger actions when you click on or +scroll over a module. +But in some cases you may want or need to manually send action strings to +polybar to trigger a certain behavior. + +Everywhere where you can specify a command to run on click or scroll, you can +also specify an action string. +For example, in the bar section, you can specify a command that is triggered +when you click anywhere on the bar (where there isn't another click action): + +.. code-block:: ini + + [bar/mybar] + ... + click-left = #mydate.toggle + ... + +This will then trigger the ``toggle`` action on the ``mydate`` module when you +click anywhere on the bar. + +Similarly, we can use action strings in ``%{A}`` +`formatting tags `_ +just as we would regular commands: + +:: + + %{A1:firefox:}%{A3:#mydate.toggle:}Opens firefox on left-click and toggles the + date on right-click %{A}%{A} + +Finally, polybar's `Inter Process Communication +`_ (IPC) can +also be used to trigger actions: + +.. code-block:: bash + + polybar-msg action "#mydate.toggle" + +.. note:: + + The quotes around the action string are necessary, otherwise your shell may + interpret the ``#`` as the beginning of the comment and ignore the rest of the + line. + +Available Actions +----------------- + +The following modules have actions available. Most of them are already used by +the module by default for click and scroll events. + +All Modules +^^^^^^^^^^^ + +These actions are available to all modules and are prefixed with ``module_``. + +:``module_show``, ``module_hide``: + Shows/Hides a module. The module is still running in the background when + hidden, it is just not drawn. The starting state can be configured with the + `hidden` configuration option. + + .. versionadded:: 3.6.0 + +:``module_toggle``: + Toggles the visibility of a module. + + .. versionadded:: 3.6.0 + +internal/date +^^^^^^^^^^^^^ + +:``toggle``: + Toggles the date/time format between ``date``/``time`` and + ``date-alt``/``time-alt`` + +internal/alsa +^^^^^^^^^^^^^ + +:``inc``, ``dec``: + Increases/Decreases the volume by ``interval`` percentage points, where + ``interval`` is the config setting in the module. Volume changed like this + will never go above 100%. + +:``toggle``: + Toggles between muted and unmuted. + +internal/pulseaudio +^^^^^^^^^^^^^^^^^^^ + +:``inc``, ``dec``: + Increases/Decreases the volume by ``interval`` percentage points, where + ``interval`` is the config setting in the module. Volume changed like this + will never go above ~153% (if ``use-ui-max`` is set to ``true``) or 100% (if + not). + +:``toggle``: + Toggles between muted and unmuted. + +internal/xbacklight +^^^^^^^^^^^^^^^^^^^ + +:``inc``, ``dec``: + Increases/Decreases screen brightness 5 percentage points. + +internal/backlight +^^^^^^^^^^^^^^^^^^ + +:``inc``, ``dec``: + Increases/Decreases screen brightness 5 percentage points. + +internal/xkeyboard +^^^^^^^^^^^^^^^^^^ + +:``switch``: + Cycles through configured keyboard layouts. + +internal/mpd +^^^^^^^^^^^^ + +:``play``: Starts playing the current song. +:``pause``: Pauses the current song. +:``stop``: Stops playing. +:``prev``: Starts playing the previous song. +:``next``: Starts playing the next song. +:``repeat``: Toggles repeat mode. +:``single``: Toggles single mode. +:``random``: Toggles random mode. +:``consume``: Toggles consume mode. +:``seek``: *(Has Data)* Seeks inside the current song. + + The data must be of the form ``[+-]N``, where ``N`` is a number + between 0 and 100. + + If either ``+`` or ``-`` is used, it will seek forward or backward + from the current position by ``N%`` (relative to the length of the + song). + Otherwise it will seek to ``N%`` of the current song. + +internal/xworkspaces +^^^^^^^^^^^^^^^^^^^^ + +:``focus``: *(Has Data)* Switches to the given workspace. + + The data is the index of the workspace that should be selected. +:``next``: Switches to the next workspace. The behavior of this action is + affected by the ``pin-workspaces`` setting. +:``prev``: Switches to the previous workspace. The behavior of this action is + affected by the ``pin-workspaces`` setting. + +internal/bspwm +^^^^^^^^^^^^^^ + +:``focus``: *(Has Data)* Switches to the given workspace. + + The data has the form ``N+M``, where ``N`` is the index of the + monitor and ``M`` the index of the workspace on that monitor. + Both indices are 0-based and correspond to the position the monitor + and workspace appear in the output of ``bspc subscribe report``. +:``next``: Switches to the next workspace. The behavior of this action is + affected by the ``pin-workspaces`` setting. +:``prev``: Switches to the previous workspace. The behavior of this action is + affected by the ``pin-workspaces`` setting. + + +internal/i3 +^^^^^^^^^^^ + +:``focus``: *(Has Data)* Switches to the given workspace. + + The data is the name of the workspace defined in the i3 config. +:``next``: Switches to the next workspace. The behavior of this action is + affected by the ``pin-workspaces`` setting. +:``prev``: Switches to the previous workspace. The behavior of this action is + affected by the ``pin-workspaces`` setting. + +custom/menu +^^^^^^^^^^^ + +:``open``: *(Has Data)* Opens the given menu level + + The data is a single number specifying which menu level should be + opened. +:``close``: Closes the menu +:``exec``: *(Has Data)* Executes the command at the given menu element. + + The data has the form ``N-M`` and the action will execute the command + in ``menu-N-M-exec``. + + +.. _actions-ipc: + +custom/ipc +^^^^^^^^^^ + +.. versionadded:: 3.6.0 + +:``send``: *(Has Data)* Replace the contents of the module with the data passed in this action. +:``hook``: *(Has Data)* Trigger the given hook. + + The data is the 0-based index of the hook to trigger. +:``next``: Switches to the next hook and wrap around when the last hook was displayed. +:``prev``: Switches to the previous hook and wrap around when the first hook was displayed. +:``reset``: Reset the module to its startup state: either empty or according to the ``initial`` setting. + + +Deprecated Action Names +----------------------- + +.. deprecated:: 3.5.0 + +In earlier versions (< 3.5.0) action strings only included information about the +module type. +This meant in bars that contained multiple different modules of the same type, +actions for these modules were sometimes processed by the wrong module with the +same type. + +Since version 3.5.0, this no longer happens. However, this also means we had to +change what actions are recognized by polybar modules. + +If you explicitly use any polybar action names in your config or any of your +scripts, you are advised to change them, as they may stop working at some point +in the future. +For now polybar still supports the old action names, will convert them to the +appropriate new action name, and will print a warning to help you find old +action names in your config. + +If you use the `menu module +`_, you most likely use +old action names to open and close the menu (for example ``menu-open-1`` or +``menu-close``). +The ``i3wm-wsnext``, ``i3wm-wsprev``, ``bspwm-desknext``, and ``bspwm-deskprev`` +actions, to switch workspaces in i3 and bspwm, may also appear in your config. + +Migration +^^^^^^^^^ + +Updating your config to use the new action names is quite straightforward. + +For each action name, consult the table below to find the new action name. +Afterwards build the complete action string as described in +:ref:`action-string-format`. + +Please see :ref:`below ` for an example of migrating a typical menu module. + ++-------------------------+-----------------------+---------------+ +|Module Type |Deprecated Action Name |New Action Name| ++=========================+=======================+===============+ +|``internal/date`` |``datetoggle`` |``toggle`` | ++-------------------------+-----------------------+---------------+ +|``internal/alsa`` |``volup`` |``inc`` | +| +-----------------------+---------------+ +| |``voldown`` |``dec`` | +| +-----------------------+---------------+ +| |``volmute`` |``toggle`` | ++-------------------------+-----------------------+---------------+ +|``internal/pulseaudio`` |``pa_volup`` |``inc`` | +| +-----------------------+---------------+ +| |``pa_voldown`` |``dec`` | +| +-----------------------+---------------+ +| |``pa_volmute`` |``toggle`` | ++-------------------------+-----------------------+---------------+ +|``internal/xbacklight`` |``xbacklight+`` |``inc`` | +| +-----------------------+---------------+ +| |``xbacklight-`` |``dec`` | ++-------------------------+-----------------------+---------------+ +|``internal/backlight`` |``backlight+`` |``inc`` | +| +-----------------------+---------------+ +| |``backlight-`` |``dec`` | ++-------------------------+-----------------------+---------------+ +|``internal/xkeyboard`` |``xkeyboard/switch`` |``switch`` | ++-------------------------+-----------------------+---------------+ +|``internal/mpd`` |``mpdplay`` |``play`` | +| +-----------------------+---------------+ +| |``mpdpause`` |``pause`` | +| +-----------------------+---------------+ +| |``mpdstop`` |``stop`` | +| +-----------------------+---------------+ +| |``mpdprev`` |``prev`` | +| +-----------------------+---------------+ +| |``mpdnext`` |``next`` | +| +-----------------------+---------------+ +| |``mpdrepeat`` |``repeat`` | +| +-----------------------+---------------+ +| |``mpdsingle`` |``single`` | +| +-----------------------+---------------+ +| |``mpdrandom`` |``random`` | +| +-----------------------+---------------+ +| |``mpdconsume`` |``consume`` | +| +-----------------------+---------------+ +| |``mpdseekN`` |``seek.N`` | ++-------------------------+-----------------------+---------------+ +|``internal/xworkspaces`` |``xworkspaces-focus=N``|``focus.N`` | +| +-----------------------+---------------+ +| |``xworkspaces-next`` |``next`` | +| +-----------------------+---------------+ +| |``xworkspaces-prev`` |``prev`` | ++-------------------------+-----------------------+---------------+ +|``internal/bspwm`` |``bspwm-deskfocusN`` |``focus.N`` | +| +-----------------------+---------------+ +| |``bspwm-desknext`` |``next`` | +| +-----------------------+---------------+ +| |``bspwm-deskprev`` |``prev`` | ++-------------------------+-----------------------+---------------+ +|``internal/i3`` |``i3wm-wsfocus-N`` |``focus.N`` | +| +-----------------------+---------------+ +| |``i3-wsnext`` |``next`` | +| +-----------------------+---------------+ +| |``i3-wsprev`` |``prev`` | ++-------------------------+-----------------------+---------------+ +|``custom/menu`` |``menu-open-N`` |``open.N`` | +| +-----------------------+---------------+ +| |``menu-close`` |``close`` | ++-------------------------+-----------------------+---------------+ + +.. note:: + + Some deprecated action names are suffixed with ``N``, this means that that + action has some additional data (represented by that ``N``), in the new + action names this data will appear in exactly the same way, after a period. + +.. _menu-example: + +Menu Module Example +""""""""""""""""""" + +The menu module is the only module where we have to explicitly use actions for +it to work. Because of this, almost everyone will need to update their menu +module to use the new action format. + +Below you can see an example of a menu module: + +.. code-block:: ini + + [module/apps] + type = custom/menu + + label-open = Apps + + menu-0-0 = Browsers + menu-0-0-exec = menu-open-1 + menu-0-1 = Multimedia + menu-0-1-exec = menu-open-2 + + menu-1-0 = Firefox + menu-1-0-exec = firefox + menu-1-1 = Chromium + menu-1-1-exec = chromium + + menu-2-0 = Gimp + menu-2-0-exec = gimp + menu-2-1 = Scrot + menu-2-1-exec = scrot + +This module uses two actions: ``menu-open-1`` and ``menu-open-2``. +These are actions with data, the data specifies which level of the menu should +be opened. + +Looking at the table, we see that the new action name for ``menu-open-N`` is +``open.N``, where ``.N`` is the data attached to the action. +Putting this together with the name of the module gives us ``#apps.open.1`` and +``#apps.open.2`` as action strings. +Since your menu module likely has a different name, your action strings will +likely not use ``apps``, but the name of your module. + +.. code-block:: ini + + [module/apps] + type = custom/menu + + label-open = Apps + + menu-0-0 = Browsers + menu-0-0-exec = #apps.open.1 + menu-0-1 = Multimedia + menu-0-1-exec = #apps.open.2 + + menu-1-0 = Firefox + menu-1-0-exec = firefox + menu-1-1 = Chromium + menu-1-1-exec = chromium + + menu-2-0 = Gimp + menu-2-0-exec = gimp + menu-2-1 = Scrot + menu-2-1-exec = scrot diff --git a/doc/user/ipc.rst b/doc/user/ipc.rst new file mode 100644 index 0000000..9b1219b --- /dev/null +++ b/doc/user/ipc.rst @@ -0,0 +1,120 @@ +Inter-process-messaging +======================= + +Polybar supports controlling parts of the bar and its modules from the outside +through inter-process-messaging (IPC). + +IPC is disabled by default and can be enabled by setting ``enable-ipc = true`` +in the bar section. + +By default polybar ships with the ``polybar-msg`` tool that is needed to send +messages to polybar. + +.. note:: Starting with version 3.6.0, the underlying IPC mechanism has been + completely changed. + + Writing directly to the named pipe to send IPC messages has been + deprecated, ``polybar-msg`` should be used exclusively + Everything you could do by directly writing to the named pipe, you + can also do using ``polybar-msg``. + In addition, hook messages are also deprecated; they are replaced by + actions on the :ref:`ipc module `. + + Unless noted otherwise, everything in this guide is still valid for + older versions. + +Sending Messages +---------------- + +``polybar-msg`` can be called on the commandline like this: + +.. code-block:: shell + + polybar-msg [-p ] + +If the ``-p`` argument is specified, the message is only sent to the running +polybar instance with the given process ID. +Otherwise, the message is sent to all running polybar processes that have IPC +enabled. + +.. note:: IPC messages are only sent to polybar instances running under the + same user as ``polybar-msg`` is running as. + + Concretely, ``polybar`` and ``polybar-msg`` use the + ``$XDG_RUNTIME_DIR`` environment variable in accordance with the `XDG + Base Directory Specification`_ to determine where to find the socket + to communicate. + + If ``polybar`` and ``polybar-msg`` don't have the same value for + ``$XDG_RUNTIME_DIR``, they will likely not be able to communicate. + The variable may not be set if you use ``su`` or ``sudo`` to execute + ``polybar-msg`` as a different user, often a full user session is + required. + + .. _XDG Base Directory Specification: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + +The ```` argument is either :ref:`action ` or +:ref:`cmd `. +The allowed values for ```` depend on the type. + +Message Types +------------- + +.. _ipc-commands: + +Commands +^^^^^^^^ + +Using ``cmd`` for ````, you can control certain aspects of the bar. + +Available values for ```` are: + +* ``quit``: Terminates the bar +* ``restart``: Restarts the bar in-place +* ``hide``: Hides the bar +* ``show``: Makes the bar visible again, if it was hidden +* ``toggle``: Toggles between the hidden and visible state. + +.. _ipc-actions: + +Module Actions +^^^^^^^^^^^^^^ + +For the ```` ``action``, ``polybar-msg`` can execute +:doc:`module actions ` in the bar. + +An action consists of the name of the target module, the name of the action and an optional data string: + +:: + + #.[.] + +More information about action strings and available actions can be found in +:doc:`actions` + +For example, if you have a date module named ``date``, you can toggle between +the regular and alternative label with: + +.. code-block:: shell + + polybar-msg action "#date.toggle" + +As an example for an action with data, say you have a menu module named +``powermenu``, you can open the menu level 0 using: + +.. code-block:: shell + + polybar-msg action "#powermenu.open.0" + + +.. note:: + + For convenience, ``polybar-msg`` also allows you to pass the module name, + action name, and data as separate arguments: + + .. code-block:: shell + + polybar-msg action date toggle + polybar-msg action powermenu open 0 + + .. versionadded:: 3.6.0 diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..eb926fd --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Generate settings.hpp +# + +list(APPEND XPP_EXTENSION_LIST xpp::randr::extension) +list(APPEND XPP_EXTENSION_LIST xpp::composite::extension) +if(WITH_XKB) + list(APPEND XPP_EXTENSION_LIST xpp::xkb::extension) +endif() +string(REPLACE ";" ", " XPP_EXTENSION_LIST "${XPP_EXTENSION_LIST}") + +configure_file( + ${CMAKE_CURRENT_LIST_DIR}/settings.hpp.cmake + ${CMAKE_BINARY_DIR}/generated-sources/settings.hpp + ESCAPE_QUOTES) diff --git a/include/adapters/alsa/control.hpp b/include/adapters/alsa/control.hpp new file mode 100644 index 0000000..5641b13 --- /dev/null +++ b/include/adapters/alsa/control.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "common.hpp" +#include "settings.hpp" + +// fwd +struct _snd_ctl; +struct _snd_hctl_elem; +struct _snd_hctl; +typedef struct _snd_ctl snd_ctl_t; +typedef struct _snd_hctl_elem snd_hctl_elem_t; +typedef struct _snd_hctl snd_hctl_t; + +POLYBAR_NS + +namespace alsa { + class control { + public: + explicit control(int numid); + ~control(); + + control(const control& o) = delete; + control& operator=(const control& o) = delete; + + int get_numid(); + bool wait(int timeout = -1); + bool test_device_plugged(); + void process_events(); + + private: + int m_numid{0}; + + snd_ctl_t* m_ctl{nullptr}; + snd_hctl_t* m_hctl{nullptr}; + snd_hctl_elem_t* m_elem{nullptr}; + }; +} + +POLYBAR_NS_END diff --git a/include/adapters/alsa/generic.hpp b/include/adapters/alsa/generic.hpp new file mode 100644 index 0000000..2415946 --- /dev/null +++ b/include/adapters/alsa/generic.hpp @@ -0,0 +1,65 @@ +#pragma once + +#ifdef USE_ALSALIB_H +#include +#else +#include + +#ifndef __FreeBSD__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __GNUC__ +#define __inline__ inline +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "common.hpp" +#include "settings.hpp" +#include "errors.hpp" + +POLYBAR_NS + +namespace alsa { + DEFINE_ERROR(alsa_exception); + DEFINE_CHILD_ERROR(mixer_error, alsa_exception); + DEFINE_CHILD_ERROR(control_error, alsa_exception); + + template + void throw_exception(string&& message, int error_code) { + const char* snd_error = snd_strerror(error_code); + if (snd_error != nullptr) + message += ": " + string{snd_error}; + throw T(message.c_str()); + } +} + +POLYBAR_NS_END diff --git a/include/adapters/alsa/mixer.hpp b/include/adapters/alsa/mixer.hpp new file mode 100644 index 0000000..b8e17f5 --- /dev/null +++ b/include/adapters/alsa/mixer.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include + +#include "common.hpp" +#include "settings.hpp" + +// fwd +struct _snd_mixer; +struct _snd_mixer_elem; +struct _snd_mixer_selem_id; +typedef struct _snd_mixer snd_mixer_t; +typedef struct _snd_mixer_elem snd_mixer_elem_t; +typedef struct _snd_mixer_selem_id snd_mixer_selem_id_t; + +POLYBAR_NS + +namespace alsa { + class mixer { + public: + explicit mixer(string&& mixer_selem_name, string&& soundcard_name); + ~mixer(); + + mixer(const mixer& o) = delete; + mixer& operator=(const mixer& o) = delete; + + const string& get_name(); + const string& get_sound_card(); + + bool wait(int timeout = -1); + int process_events(); + + int get_volume(); + int get_normalized_volume(); + void set_volume(float percentage); + void set_normalized_volume(float percentage); + void set_mute(bool mode); + void toggle_mute(); + bool is_muted(); + + private: + snd_mixer_t* m_mixer{nullptr}; + snd_mixer_elem_t* m_elem{nullptr}; + + string m_name; + string s_name; + }; +} + +POLYBAR_NS_END diff --git a/include/adapters/mpd.hpp b/include/adapters/mpd.hpp new file mode 100644 index 0000000..d6f1b26 --- /dev/null +++ b/include/adapters/mpd.hpp @@ -0,0 +1,182 @@ +#pragma once + +#include +#include +#include +#include + +#include "common.hpp" +#include "errors.hpp" + +POLYBAR_NS + +// fwd +class logger; + +namespace chrono = std::chrono; + +namespace mpd { + extern sig_atomic_t g_connection_closed; + + DEFINE_ERROR(mpd_exception); + DEFINE_CHILD_ERROR(client_error, mpd_exception); + DEFINE_CHILD_ERROR(server_error, mpd_exception); + + void check_connection(mpd_connection* conn); + void check_errors(mpd_connection* conn); + + // types details {{{ + + enum class connection_state { NONE = 0, CONNECTED, DISCONNECTED }; + + enum class mpdstate { + UNKNOWN = 1 << 0, + STOPPED = 1 << 1, + PLAYING = 1 << 2, + PAUSED = 1 << 4, + }; + + namespace details { + struct mpd_connection_deleter { + void operator()(mpd_connection* conn); + }; + + struct mpd_status_deleter { + void operator()(mpd_status* status); + }; + + struct mpd_song_deleter { + void operator()(mpd_song* song); + }; + } + + using mpd_connection_t = unique_ptr; + using mpd_status_t = unique_ptr; + using mpd_song_t = unique_ptr; + + // }}} + // class : mpdsong {{{ + + class mpdsong { + public: + explicit mpdsong(mpd_song_t&& song) : m_song(forward(song)) {} + + operator bool(); + + string get_artist(); + string get_album_artist(); + string get_album(); + string get_title(); + string get_date(); + unsigned get_duration(); + + private: + mpd_song_t m_song; + }; + + // }}} + // class : mpdconnection {{{ + + class mpdstatus; + class mpdconnection { + public: + explicit mpdconnection( + const logger& logger, string host, unsigned int port = 6600, string password = "", unsigned int timeout = 15); + ~mpdconnection(); + + void connect(); + void disconnect(); + bool connected(); + bool retry_connection(int interval = 1); + + int get_fd(); + void idle(); + int noidle(); + + unique_ptr get_status(); + unique_ptr get_status_safe(); + unique_ptr get_song(); + + void play(); + void pause(bool state); + void toggle(); + void stop(); + void prev(); + void next(); + void seek(int songid, int pos); + + void set_repeat(bool mode); + void set_random(bool mode); + void set_single(bool mode); + void set_consume(bool mode); + + operator mpd_connection_t::element_type*(); + + protected: + void check_prerequisites(); + void check_prerequisites_commands_list(); + + private: + const logger& m_log; + mpd_connection_t m_connection{}; + + struct sigaction m_signal_action {}; + + bool m_listactive = false; + bool m_idle = false; + int m_fd = -1; + + string m_host; + unsigned int m_port; + string m_password; + unsigned int m_timeout; + }; + + // }}} + // class : mpdstatus {{{ + + class mpdstatus { + public: + explicit mpdstatus(mpdconnection* conn, bool autoupdate = true); + + void fetch_data(mpdconnection* conn); + void update(int event, mpdconnection* connection); + + bool random() const; + bool repeat() const; + bool single() const; + bool consume() const; + + bool match_state(mpdstate state) const; + + int get_songid() const; + int get_queuelen() const; + unsigned get_total_time() const; + unsigned get_elapsed_time() const; + unsigned get_elapsed_percentage(); + string get_formatted_elapsed(); + string get_formatted_total(); + int get_seek_position(int percentage); + + private: + mpd_status_t m_status{}; + unique_ptr m_song{}; + mpdstate m_state{mpdstate::UNKNOWN}; + + bool m_random{false}; + bool m_repeat{false}; + bool m_single{false}; + bool m_consume{false}; + + int m_songid{0}; + int m_queuelen{0}; + + unsigned long m_total_time{0UL}; + unsigned long m_elapsed_time{0UL}; + unsigned long m_elapsed_time_ms{0UL}; + }; + + // }}} +} + +POLYBAR_NS_END diff --git a/include/adapters/net.hpp b/include/adapters/net.hpp new file mode 100644 index 0000000..40ed214 --- /dev/null +++ b/include/adapters/net.hpp @@ -0,0 +1,191 @@ +#pragma once + +#include +#include + +#include +#include + +#include "common.hpp" +#include "components/logger.hpp" +#include "errors.hpp" +#include "settings.hpp" +#include "utils/math.hpp" + +#if WITH_LIBNL +#include + +struct nl_msg; +struct nlattr; +#else +#include + +/* + * wirless_tools 29 (and possibly earlier) redefines 'inline' in iwlib.h + * With clang this leads to a conflict in the POLYBAR_NS macro + * wirless_tools 30 doesn't have that issue anymore + */ +#ifdef inline +#undef inline +#endif +#endif + +POLYBAR_NS + +class file_descriptor; + +namespace net { + DEFINE_ERROR(network_error); + + bool is_interface_valid(const string& ifname); + std::pair get_canonical_interface(const string& ifname); + bool is_wireless_interface(const string& ifname); + std::string find_wireless_interface(); + std::string find_wired_interface(); + + // types {{{ + + struct quality_range { + int val{0}; + int max{0}; + + int percentage() const { + if (val < 0) { + return std::max(std::min(std::abs(math_util::percentage(val, max, -20)), 100), 0); + } + return std::max(std::min(math_util::percentage(val, 0, max), 100), 0); + } + }; + + using bytes_t = unsigned int; + + struct link_activity { + bytes_t transmitted{0}; + bytes_t received{0}; + std::chrono::steady_clock::time_point time; + }; + + struct link_status { + string ip; + string ip6; + string mac; + link_activity previous{}; + link_activity current{}; + }; + + // }}} + // class : network {{{ + + class network { + public: + explicit network(string interface); + virtual ~network() {} + + virtual bool query(bool accumulate = false); + virtual bool connected() const = 0; + virtual bool ping() const; + + string ip() const; + string ip6() const; + string mac() const; + string downspeed(int minwidth = 3, const string& unit = "B/s") const; + string upspeed(int minwidth = 3, const string& unit = "B/s") const; + string netspeed(int minwidth = 3, const string& unit = "B/s") const; + void set_unknown_up(bool unknown = true); + + protected: + void check_tuntap_or_bridge(); + bool test_interface() const; + string format_speedrate(float bytes_diff, int minwidth, const string& unit) const; + void query_ip6(); + + const logger& m_log; + unique_ptr m_socketfd; + link_status m_status{}; + string m_interface; + bool m_tuntap{false}; + bool m_bridge{false}; + bool m_unknown_up{false}; + }; + + // }}} + // class : wired_network {{{ + + class wired_network : public network { + public: + explicit wired_network(string interface) : network(interface) {} + + bool query(bool accumulate = false) override; + bool connected() const override; + string linkspeed() const; + + private: + int m_linkspeed{0}; + }; + + // }}} + +#if WITH_LIBNL + // class : wireless_network {{{ + + class wireless_network : public network { + public: + wireless_network(string interface) : network(interface), m_ifid(if_nametoindex(interface.c_str())){}; + + bool query(bool accumulate = false) override; + bool connected() const override; + string essid() const; + int signal() const; + int quality() const; + + protected: + static int scan_cb(struct nl_msg* msg, void* instance); + + bool associated_or_joined(struct nlattr** bss); + void parse_essid(struct nlattr** bss); + void parse_frequency(struct nlattr** bss); + void parse_quality(struct nlattr** bss); + void parse_signal(struct nlattr** bss); + + private: + unsigned int m_ifid{}; + string m_essid{}; + int m_frequency{}; + quality_range m_signalstrength{}; + quality_range m_linkquality{}; + }; + + // }}} +#else + // class : wireless_network {{{ + + class wireless_network : public network { + public: + wireless_network(string interface) : network(interface) {} + + bool query(bool accumulate = false) override; + bool connected() const override; + + string essid() const; + int signal() const; + int quality() const; + + protected: + void query_essid(const int& socket_fd); + void query_quality(const int& socket_fd); + + private: + shared_ptr m_info{}; + string m_essid{}; + quality_range m_signalstrength{}; + quality_range m_linkquality{}; + }; + + // }}} +#endif + + using wireless_t = unique_ptr; + using wired_t = unique_ptr; +} // namespace net + +POLYBAR_NS_END diff --git a/include/adapters/pulseaudio.hpp b/include/adapters/pulseaudio.hpp new file mode 100644 index 0000000..1ee10b5 --- /dev/null +++ b/include/adapters/pulseaudio.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include + +#include +#include + +#include "common.hpp" +#include "errors.hpp" +#include "settings.hpp" +#include "utils/math.hpp" +// fwd +struct pa_context; +struct pa_threaded_mainloop; +struct pa_cvolume; +typedef struct pa_context pa_context; +typedef struct pa_threaded_mainloop pa_threaded_mainloop; + +POLYBAR_NS +class logger; + +DEFINE_ERROR(pulseaudio_error); + +class pulseaudio { + // events to add to our queue + enum class evtype { NEW = 0, CHANGE, REMOVE, SERVER }; + using queue = std::queue; + + public: + explicit pulseaudio(const logger& logger, string&& sink_name, bool m_max_volume); + ~pulseaudio(); + + pulseaudio(const pulseaudio& o) = delete; + pulseaudio& operator=(const pulseaudio& o) = delete; + + const string& get_name(); + + bool wait(); + int process_events(); + + int get_volume(); + double get_decibels(); + void set_volume(float percentage); + void inc_volume(int delta_perc); + void set_mute(bool mode); + void toggle_mute(); + bool is_muted(); + + private: + void update_volume(pa_operation* o); + static void check_mute_callback(pa_context* context, const pa_sink_info* info, int eol, void* userdata); + static void get_sink_volume_callback(pa_context* context, const pa_sink_info* info, int is_last, void* userdata); + static void subscribe_callback(pa_context* context, pa_subscription_event_type_t t, uint32_t idx, void* userdata); + static void simple_callback(pa_context* context, int success, void* userdata); + static void sink_info_callback(pa_context* context, const pa_sink_info* info, int eol, void* userdata); + static void context_state_callback(pa_context* context, void* userdata); + + inline void wait_loop(pa_operation* op, pa_threaded_mainloop* loop); + + const logger& m_log; + + /** + * Has context_state_callback signalled the mainloop during connection. + */ + std::atomic_bool m_state_callback_signal{false}; + + // used for temporary callback results + int success{0}; + pa_cvolume cv{}; + bool muted{false}; + // default sink name + static constexpr auto DEFAULT_SINK = "@DEFAULT_SINK@"; + + pa_context* m_context{nullptr}; + pa_threaded_mainloop* m_mainloop{nullptr}; + + queue m_events; + + // specified sink name + string spec_s_name; + string s_name; + uint32_t m_index{0}; + + pa_volume_t m_max_volume{PA_VOLUME_UI_MAX}; +}; + +POLYBAR_NS_END diff --git a/include/adapters/script_runner.hpp b/include/adapters/script_runner.hpp new file mode 100644 index 0000000..5bb5a61 --- /dev/null +++ b/include/adapters/script_runner.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +#include "common.hpp" +#include "components/logger.hpp" + +POLYBAR_NS + +class script_runner { + public: + struct data { + int counter{0}; + int pid{-1}; + int exit_status{0}; + string output; + }; + + using on_update = std::function; + using interval = std::chrono::duration; + + script_runner(on_update on_update, const string& exec, const string& exec_if, bool tail, interval interval, + const vector>& env); + + bool check_condition() const; + interval process(); + + void clear_output(); + + void stop(); + + bool is_stopping() const; + + protected: + bool set_output(string&&); + bool set_exit_status(int); + + interval run_tail(); + interval run(); + + private: + const logger& m_log; + + const on_update m_on_update; + + const string m_exec; + const string m_exec_if; + const bool m_tail; + const interval m_interval; + const vector> m_env; + + data m_data; + std::atomic_bool m_stopping{false}; +}; + +POLYBAR_NS_END diff --git a/include/cairo/context.hpp b/include/cairo/context.hpp new file mode 100644 index 0000000..f0be75b --- /dev/null +++ b/include/cairo/context.hpp @@ -0,0 +1,373 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include "cairo/font.hpp" +#include "cairo/surface.hpp" +#include "cairo/types.hpp" +#include "cairo/utils.hpp" +#include "common.hpp" +#include "components/logger.hpp" +#include "components/types.hpp" +#include "errors.hpp" +#include "utils/color.hpp" +#include "utils/string.hpp" + +POLYBAR_NS + +namespace cairo { + /** + * @brief Cairo context + */ + class context { + public: + explicit context(const surface& surface, const logger& log) : m_c(cairo_create(surface)), m_log(log) { + auto status = cairo_status(m_c); + if (status != CAIRO_STATUS_SUCCESS) { + throw application_error(sstream() << "cairo_status(): " << cairo_status_to_string(status)); + } + cairo_set_antialias(m_c, CAIRO_ANTIALIAS_GOOD); + } + + virtual ~context() { + cairo_destroy(m_c); + } + + operator cairo_t*() const { + return m_c; + } + + context& operator<<(const surface& s) { + cairo_set_source_surface(m_c, s, 0.0, 0.0); + return *this; + } + + context& operator<<(cairo_operator_t o) { + cairo_set_operator(m_c, o); + return *this; + } + + context& operator<<(cairo_pattern_t* s) { + cairo_set_source(m_c, s); + return *this; + } + + context& operator<<(const abspos& p) { + if (p.clear) { + cairo_new_path(m_c); + } + cairo_move_to(m_c, p.x, p.y); + return *this; + } + + context& operator<<(const relpos& p) { + cairo_rel_move_to(m_c, p.x, p.y); + return *this; + } + + context& operator<<(const rgba& f) { + cairo_set_source_rgba(m_c, f.red_d(), f.green_d(), f.blue_d(), f.alpha_d()); + return *this; + } + + context& operator<<(const rect& f) { + cairo_rectangle(m_c, f.x, f.y, f.w, f.h); + return *this; + } + + context& operator<<(const line& l) { + struct line p { + l.x1, l.y1, l.x2, l.y2, l.w + }; + snap(&p.x1, &p.y1); + snap(&p.x2, &p.y2); + cairo_move_to(m_c, p.x1, p.y1); + cairo_line_to(m_c, p.x2, p.y2); + cairo_set_line_width(m_c, p.w); + cairo_stroke(m_c); + return *this; + } + + context& operator<<(const translate& d) { + cairo_translate(m_c, d.x, d.y); + return *this; + } + + context& operator<<(const linear_gradient& l) { + auto stops = l.steps.size(); + if (stops >= 2) { + auto pattern = cairo_pattern_create_linear(l.x1, l.y1, l.x2, l.y2); + auto step = 1.0 / (stops - 1); + auto offset = 0.0; + for (auto&& color : l.steps) { + // clang-format off + cairo_pattern_add_color_stop_rgba(pattern, offset, color.red_d(), color.green_d(), color.blue_d(), color.alpha_d()); + // clang-format on + offset += step; + } + *this << pattern; + cairo_pattern_destroy(pattern); + } + return *this; + } + + context& operator<<(const rounded_corners& c) { + cairo_new_sub_path(m_c); + cairo_arc( + m_c, c.x + c.w - c.radius.top_right, c.y + c.radius.top_right, c.radius.top_right, -90 * degree, 0 * degree); + cairo_arc(m_c, c.x + c.w - c.radius.bottom_right, c.y + c.h - c.radius.bottom_right, c.radius.bottom_right, + 0 * degree, 90 * degree); + cairo_arc(m_c, c.x + c.radius.bottom_left, c.y + c.h - c.radius.bottom_left, c.radius.bottom_left, 90 * degree, + 180 * degree); + cairo_arc(m_c, c.x + c.radius.top_left, c.y + c.radius.top_left, c.radius.top_left, 180 * degree, 270 * degree); + cairo_close_path(m_c); + return *this; + } + + context& operator<<(const circle_segment& segment) { + cairo_new_sub_path(m_c); + cairo_arc(m_c, segment.x, segment.y, segment.radius, segment.angle_from * degree, segment.angle_to * degree); + switch ((int)segment.angle_to) { + case 0: + cairo_rel_line_to(m_c, -segment.w, 0); + break; + case 90: + cairo_rel_line_to(m_c, 0, -segment.w); + break; + case 180: + cairo_rel_line_to(m_c, segment.w, 0); + break; + default: + cairo_rel_line_to(m_c, 0, segment.w); + break; + } + cairo_arc_negative(m_c, segment.x, segment.y, segment.radius - segment.w, segment.angle_to * degree, + segment.angle_from * degree); + cairo_close_path(m_c); + return *this; + } + + context& operator<<(const textblock& t) { + double x, y; + position(&x, &y); + + // Prioritize the preferred font + vector> fns(m_fonts.begin(), m_fonts.end()); + + if (t.font > 0 && t.font <= std::distance(fns.begin(), fns.end())) { + std::iter_swap(fns.begin(), fns.begin() + t.font - 1); + } + + string utf8 = string(t.contents); + utils::unicode_charlist chars; + utils::utf8_to_ucs4((const unsigned char*)utf8.c_str(), chars); + + while (!chars.empty()) { + auto remaining = chars.size(); + for (auto&& f : fns) { + unsigned int matches = 0; + + // Match as many glyphs as possible if the default/preferred font + // is being tested. Otherwise test one glyph at a time against + // the remaining fonts. Roll back to the top of the font list + // when a glyph has been found. + if (f == fns.front() && (matches = f->match(chars)) == 0) { + continue; + } else if (f != fns.front() && (matches = f->match(chars.front())) == 0) { + continue; + } + + string subset; + auto end = chars.begin(); + while (matches-- && end != chars.end()) { + subset += utf8.substr(end->offset, end->length); + end++; + } + + // Use the font + f->use(); + + // Get subset extents + cairo_text_extents_t extents; + f->textwidth(subset, &extents); + + // Draw the background + if (t.bg_rect.h != 0.0) { + save(); + cairo_set_operator(m_c, t.bg_operator); + *this << t.bg; + cairo_rectangle(m_c, t.bg_rect.x + *t.x_advance, t.bg_rect.y + *t.y_advance, + t.bg_rect.w + extents.x_advance, t.bg_rect.h); + cairo_fill(m_c); + restore(); + } + + // Render subset + auto fontextents = f->extents(); + f->render(subset, x, y - (fontextents.descent / 2 - fontextents.height / 4) + f->offset()); + + // Get updated position + position(&x, nullptr); + + // Increase position + *t.x_advance += extents.x_advance; + *t.y_advance += extents.y_advance; + + chars.erase(chars.begin(), end); + break; + } + + if (chars.empty()) { + break; + } else if (remaining != chars.size()) { + continue; + } + + char unicode[6]{'\0'}; + utils::ucs4_to_utf8(unicode, chars.begin()->codepoint); + m_log.warn("Dropping unmatched character %s (U+%04x) in '%s'", unicode, chars.begin()->codepoint, t.contents); + utf8.erase(chars.begin()->offset, chars.begin()->length); + for (auto&& c : chars) { + c.offset -= chars.begin()->length; + } + chars.erase(chars.begin(), ++chars.begin()); + } + + return *this; + } + + context& operator<<(shared_ptr&& f) { + m_fonts.emplace_back(forward(f)); + return *this; + } + + context& save(bool save_point = false) { + if (save_point) { + m_points.emplace_front(make_pair(0.0, 0.0)); + position(&m_points.front().first, &m_points.front().second); + } + m_activegroups++; + cairo_save(m_c); + return *this; + } + + context& restore(bool restore_point = false) { + if (!m_activegroups) { + throw application_error("Unmatched calls to save/restore"); + } + m_activegroups--; + cairo_restore(m_c); + if (restore_point && !m_points.empty()) { + *this << abspos{m_points.front().first, m_points.front().first}; + m_points.pop_front(); + } + return *this; + } + + context& paint() { + cairo_paint(m_c); + return *this; + } + + context& paint(double alpha) { + cairo_paint_with_alpha(m_c, alpha); + return *this; + } + + context& fill(bool preserve = false) { + if (preserve) { + cairo_fill_preserve(m_c); + } else { + cairo_fill(m_c); + } + return *this; + } + + context& mask(cairo_pattern_t* pattern) { + cairo_mask(m_c, pattern); + return *this; + } + + context& pop(cairo_pattern_t** pattern) { + *pattern = cairo_pop_group(m_c); + return *this; + } + + context& push() { + cairo_push_group(m_c); + return *this; + } + + context& destroy(cairo_pattern_t** pattern) { + cairo_pattern_destroy(*pattern); + *pattern = nullptr; + return *this; + } + + context& clear(bool paint = true) { + cairo_save(m_c); + cairo_set_operator(m_c, CAIRO_OPERATOR_CLEAR); + if (paint) { + cairo_paint(m_c); + } else { + cairo_fill_preserve(m_c); + } + cairo_restore(m_c); + return *this; + } + + context& clip(bool preserve = false) { + if (preserve) { + cairo_clip_preserve(m_c); + } else { + cairo_clip(m_c); + cairo_new_path(m_c); + } + return *this; + } + + context& clip(const rect& r) { + *this << r; + return clip(); + } + + context& reset_clip() { + cairo_reset_clip(m_c); + return *this; + } + + context& position(double* x, double* y = nullptr) { + if (cairo_has_current_point(m_c)) { + double x_, y_; + x = x != nullptr ? x : &x_; + y = y != nullptr ? y : &y_; + cairo_get_current_point(m_c, x, y); + } + return *this; + } + + context& snap(double* x, double* y) { + cairo_user_to_device(m_c, x, y); + *x = static_cast(*x + 0.5); + *y = static_cast(*y + 0.5); + return *this; + } + + protected: + cairo_t* m_c; + const logger& m_log; + vector> m_fonts; + std::deque> m_points; + int m_activegroups{0}; + + private: + const double degree = M_PI / 180.0; + }; +} // namespace cairo + +POLYBAR_NS_END diff --git a/include/cairo/font.hpp b/include/cairo/font.hpp new file mode 100644 index 0000000..67fe8f2 --- /dev/null +++ b/include/cairo/font.hpp @@ -0,0 +1,341 @@ +#pragma once + +#include + +#include "cairo/types.hpp" +#include "cairo/utils.hpp" +#include "common.hpp" +#include "components/logger.hpp" +#include "errors.hpp" +#include "settings.hpp" +#include "utils/math.hpp" +#include "utils/scope.hpp" +#include "utils/string.hpp" + +POLYBAR_NS + +namespace cairo { + /** + * @brief Global pointer to the Freetype library handler + */ + 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(utils::unicode_character& character) = 0; + virtual size_t match(utils::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(m_scaled); + auto face = static_cast(*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 { + bool scalable; + double fc_pixelsize = 0, fc_size = 0; + + property(FC_SCALABLE, &scalable); + + // 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; + + /* + * Font size in pixels if we use the size property. Since the size + * specifies the font size in points, this is converted to pixels + * 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 && 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 { + /* + * Non-scalable fonts do it the other way around, here the size + * property is only used if pixelsize is 0 and size is not + */ + 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(utils::unicode_character& character) override { + auto lock = make_unique(m_scaled); + auto face = static_cast(*lock); + return FT_Get_Char_Index(face, character.codepoint) ? 1 : 0; + } + + size_t match(utils::unicode_charlist& charlist) override { + auto lock = make_unique(m_scaled); + auto face = static_cast(*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 { + cairo_glyph_t* glyphs{nullptr}; + cairo_text_cluster_t* clusters{nullptr}; + cairo_text_cluster_flags_t cf{}; + int nglyphs = 0, 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 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(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(file)); + } else { + return ""; + } + } + + void property(string&& property, bool* dst) const { + FcBool b; + FcPatternGetBool(m_pattern, property.c_str(), 0, &b); + *dst = b; + } + + void property(string&& property, double* dst) const { + FcPatternGetDouble(m_pattern, property.c_str(), 0, dst); + } + + void property(string&& property, int* dst) const { + FcPatternGetInteger(m_pattern, property.c_str(), 0, dst); + } + + private: + cairo_scaled_font_t* m_scaled{nullptr}; + FcPattern* m_pattern{nullptr}; + }; + + /** + * 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"); + } + + static auto fc_cleanup = scope_util::make_exit_handler([] { + FT_Done_FreeType(g_ftlib); + FcFini(); + }); + + auto pattern = FcNameParse((FcChar8*)fontname.c_str()); + + if (!pattern) { + logger::make().err("Could not parse font \"%s\"", fontname); + throw application_error("Could not parse font \"" + fontname + "\""); + } + + FcDefaultSubstitute(pattern); + 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 + FcPatternPrint(match); +#endif + + return make_shared(cairo, match, offset, dpi_x, dpi_y); + } +} // namespace cairo + +POLYBAR_NS_END diff --git a/include/cairo/fwd.hpp b/include/cairo/fwd.hpp new file mode 100644 index 0000000..1730f9d --- /dev/null +++ b/include/cairo/fwd.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "common.hpp" + +POLYBAR_NS + +namespace cairo { + class context; + class surface; + class xcb_surface; + class font; + class font_fc; +} + +POLYBAR_NS_END diff --git a/include/cairo/surface.hpp b/include/cairo/surface.hpp new file mode 100644 index 0000000..0ec7f4e --- /dev/null +++ b/include/cairo/surface.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include + +#include "cairo/types.hpp" +#include "common.hpp" +#include "errors.hpp" +#include "utils/color.hpp" +#include "utils/string.hpp" + +POLYBAR_NS + +namespace cairo { + /** + * @brief Base surface + */ + class surface { + public: + explicit surface(cairo_surface_t* s) : m_s(s) {} + virtual ~surface() { + cairo_surface_destroy(m_s); + } + + operator cairo_surface_t*() const { + return m_s; + } + + void flush() { + cairo_surface_flush(m_s); + } + + void show(bool clear = true) { + if (clear) { + cairo_surface_show_page(m_s); + } else { + cairo_surface_copy_page(m_s); + } + } + + void dirty() { + cairo_surface_mark_dirty(m_s); + } + + void dirty(const rect& r) { + cairo_surface_mark_dirty_rectangle(m_s, r.x, r.y, r.w, r.h); + } + + void write_png(const string& dst) { + auto status = cairo_surface_write_to_png(m_s, dst.c_str()); + if (status != CAIRO_STATUS_SUCCESS) { + throw application_error(sstream() << "cairo_surface_write_to_png(): " << cairo_status_to_string(status)); + } + } + + protected: + cairo_surface_t* m_s; + }; + + /** + * @brief Surface for xcb + */ + class xcb_surface : public surface { + public: + explicit xcb_surface(xcb_connection_t* c, xcb_pixmap_t p, xcb_visualtype_t* v, int w, int h) + : surface(cairo_xcb_surface_create(c, p, v, w, h)) {} + + ~xcb_surface() override {} + + void set_drawable(xcb_drawable_t d, int w, int h) { + cairo_surface_flush(m_s); + cairo_xcb_surface_set_drawable(m_s, d, w, h); + } + }; +} + +POLYBAR_NS_END diff --git a/include/cairo/types.hpp b/include/cairo/types.hpp new file mode 100644 index 0000000..cf32811 --- /dev/null +++ b/include/cairo/types.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include + +#include "common.hpp" +#include "components/types.hpp" + +POLYBAR_NS + +enum class alignment; + +namespace cairo { + struct point { + double x; + double y; + }; + struct abspos { + double x; + double y; + bool clear{true}; + }; + struct relpos { + double x; + double y; + }; + struct rect { + double x; + double y; + double w; + double h; + }; + struct line { + double x1; + double y1; + double x2; + double y2; + double w; + }; + struct translate { + double x; + double y; + }; + struct linear_gradient { + double x1; + double y1; + double x2; + double y2; + vector steps; + }; + struct rounded_corners { + double x; + double y; + double w; + double h; + struct radius radius; + }; + struct circle_segment { + double x; + double y; + double w; + double angle_from; + double angle_to; + double radius; + }; + struct textblock { + alignment align; + string contents; + int font; + rgba bg{}; + cairo_operator_t bg_operator; + rect bg_rect; + double* x_advance; + double* y_advance; + }; +} // namespace cairo + +POLYBAR_NS_END diff --git a/include/cairo/utils.hpp b/include/cairo/utils.hpp new file mode 100644 index 0000000..5db3a14 --- /dev/null +++ b/include/cairo/utils.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include + +#include "common.hpp" + +POLYBAR_NS + +namespace cairo { + namespace utils { + /** + * @brief RAII wrapper used acquire cairo_device_t + */ + class device_lock { + public: + explicit device_lock(cairo_device_t* device); + ~device_lock(); + operator bool() const; + operator cairo_device_t*() const; + + private: + cairo_device_t* m_device{nullptr}; + }; + + /** + * @brief RAII wrapper used to access the underlying + * FT_Face of a scaled font face + */ + class ft_face_lock { + public: + explicit ft_face_lock(cairo_scaled_font_t* font); + ~ft_face_lock(); + operator FT_Face() const; + + private: + cairo_scaled_font_t* m_font; + FT_Face m_face; + }; + + /** + * @brief Unicode character containing converted codepoint + * and details on where its position in the source string + */ + struct unicode_character { + explicit unicode_character(); + unsigned long codepoint; + int offset; + int length; + }; + using unicode_charlist = std::list; + + /** + * @see + */ + 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 diff --git a/include/common.hpp b/include/common.hpp new file mode 100644 index 0000000..3e776f7 --- /dev/null +++ b/include/common.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "settings.hpp" + +#define POLYBAR_NS namespace polybar { +#define POLYBAR_NS_END } + +#ifndef PIPE_READ +#define PIPE_READ 0 +#endif +#ifndef PIPE_WRITE +#define PIPE_WRITE 1 +#endif + +POLYBAR_NS + +using std::array; +using std::forward; +using std::function; +using std::make_pair; +using std::make_shared; +using std::make_unique; +using std::move; +using std::pair; +using std::shared_ptr; +using std::size_t; +using std::string; +using std::to_string; +using std::unique_ptr; +using std::vector; + +using namespace std::string_literals; + +constexpr size_t operator"" _z(unsigned long long n) { + return n; +} + +/** + * Convert an enum to its underlying type. + */ +template +constexpr auto to_integral(E e) { + static_assert(std::is_enum::value, "only enums are supported"); + return static_cast>(e); +} + +POLYBAR_NS_END diff --git a/include/components/bar.hpp b/include/components/bar.hpp new file mode 100644 index 0000000..dc7a09e --- /dev/null +++ b/include/components/bar.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include + +#include "common.hpp" +#include "components/eventloop.hpp" +#include "components/types.hpp" +#include "errors.hpp" +#include "events/signal_fwd.hpp" +#include "events/signal_receiver.hpp" +#include "settings.hpp" +#include "tags/action_context.hpp" +#include "utils/math.hpp" +#include "x11/types.hpp" +#include "x11/window.hpp" + +POLYBAR_NS + +// fwd {{{ +class config; +class connection; +class logger; +class renderer; +class screen; +class tray_manager; + +namespace tags { + class dispatch; +} +// }}} + +class bar : public xpp::event::sink, + public signal_receiver { + public: + using make_type = unique_ptr; + static make_type make(eventloop::loop&, bool only_initialize_values = false); + + explicit bar(connection&, signal_emitter&, const config&, const logger&, eventloop::loop&, unique_ptr&&, + unique_ptr&&, unique_ptr&&, unique_ptr&&, + bool only_initialize_values); + ~bar(); + + const bar_settings& settings() const; + + void start(); + + void parse(string&& data, bool force = false); + + void hide(); + void show(); + void toggle(); + + protected: + void restack_window(); + void reconfigure_window(); + void reconfigure_geom(); + void reconfigure_pos(); + void reconfigure_struts(); + void reconfigure_wm_hints(); + void broadcast_visibility(); + + void map_window(); + + void trigger_click(mousebtn btn, int pos); + + void handle(const evt::client_message& evt) override; + void handle(const evt::destroy_notify& evt) override; + void handle(const evt::enter_notify& evt) override; + void handle(const evt::leave_notify& evt) override; + void handle(const evt::motion_notify& evt) override; + void handle(const evt::button_press& evt) override; + void handle(const evt::expose& evt) override; + void handle(const evt::property_notify& evt) override; + void handle(const evt::configure_notify& evt) override; + + bool on(const signals::ui::dim_window&) override; + +#if WITH_XCURSOR + /** + * Change cursor to the given cursor name. + * + * The cursor name must be valid (cursor_util::valid) + */ + void change_cursor(const string& name); +#endif + + private: + connection& m_connection; + signal_emitter& m_sig; + const config& m_conf; + const logger& m_log; + eventloop::loop& m_loop; + unique_ptr m_screen; + unique_ptr m_tray; + unique_ptr m_renderer; + unique_ptr m_dispatch; + unique_ptr m_action_ctxt; + + bar_settings m_opts{}; + + /** + * Name of currently active cursor + */ + string m_cursor{}; + + string m_lastinput{}; + bool m_dblclicks{false}; + + eventloop::TimerHandle& m_leftclick_timer{m_loop.handle()}; + eventloop::TimerHandle& m_middleclick_timer{m_loop.handle()}; + eventloop::TimerHandle& m_rightclick_timer{m_loop.handle()}; + eventloop::TimerHandle& m_dim_timer{m_loop.handle()}; + + bool m_visible{true}; +}; + +POLYBAR_NS_END diff --git a/include/components/builder.hpp b/include/components/builder.hpp new file mode 100644 index 0000000..b5f98e7 --- /dev/null +++ b/include/components/builder.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +#include "common.hpp" +#include "components/types.hpp" +#include "tags/types.hpp" +POLYBAR_NS + +using std::map; + +// fwd decl +using namespace drawtypes; +namespace modules { + struct module_interface; +} + +class builder { + public: + explicit builder(const bar_settings& bar); + + void reset(); + string flush(); + void node(const string& str); + void node(const string& str, int font_index); + void node(const label_t& label); + void node_repeat(const label_t& label, size_t n); + void offset(extent_val pixels = ZERO_PX_EXTENT); + void spacing(spacing_val size); + void font(int index); + void font_close(); + void background(rgba color); + void background_close(); + void foreground(rgba color); + void foreground_close(); + void overline(const rgba& color); + void overline_close(); + void underline(const rgba& color); + void underline_close(); + void control(tags::controltag tag); + void action(mousebtn index, string action); + void action(mousebtn btn, const modules::module_interface& module, string action, string data); + void action(mousebtn index, string action, const label_t& label); + void action(mousebtn btn, const modules::module_interface& module, string action, string data, const label_t& label); + void action_close(); + + static string get_spacing_format_string(spacing_val space); + + protected: + void append(const string& text); + + void overline_color_close(); + void underline_color_close(); + + void tag_open(tags::syntaxtag tag, const string& value); + void tag_open(tags::attribute attr); + void tag_close(tags::syntaxtag tag); + void tag_close(tags::attribute attr); + + private: + const bar_settings& m_bar; + string m_output; + + map m_tags{}; + std::unordered_set m_attrs{}; +}; + +POLYBAR_NS_END diff --git a/include/components/command_line.hpp b/include/components/command_line.hpp new file mode 100644 index 0000000..a572a0f --- /dev/null +++ b/include/components/command_line.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include + +#include "common.hpp" +#include "errors.hpp" + +POLYBAR_NS + +namespace command_line { + DEFINE_ERROR(argument_error); + DEFINE_ERROR(value_error); + + class option; + using choices = vector; + using options = vector