mirror of
https://github.com/polybar/polybar.git
synced 2024-11-11 13:50:56 -05:00
Merge remote-tracking branch 'origin/hotfix/3.7.2'
This commit is contained in:
commit
1ba083cdb2
15 changed files with 97 additions and 43 deletions
24
.clang-tidy
24
.clang-tidy
|
@ -32,20 +32,16 @@ Checks: '
|
||||||
'
|
'
|
||||||
|
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: modernize-loop-convert.NamingStyle
|
cppcoreguidelines-avoid-do-while.IgnoreMacros: true
|
||||||
value: lower_case
|
modernize-loop-convert.NamingStyle: lower_case
|
||||||
- key: readability-identifier-naming.ClassCase
|
readability-identifier-naming.ClassCase: lower_case
|
||||||
value: lower_case
|
readability-identifier-naming.ClassConstantCase: UPPER_CASE
|
||||||
- key: readability-identifier-naming.ClassConstantCase
|
readability-identifier-naming.ClassMethodCase: lower_case
|
||||||
value: UPPER_CASE
|
readability-identifier-naming.MemberCase: lower_case
|
||||||
- key: readability-identifier-naming.ClassMethodCase
|
readability-identifier-naming.ProtectedMemberPrefix: 'm_'
|
||||||
value: lower_case
|
readability-identifier-naming.PrivateMemberPrefix: 'm_'
|
||||||
- key: readability-identifier-naming.MemberCase
|
readability-simplify-boolean-expr.SimplifyDeMorgan: false
|
||||||
value: lower_case
|
|
||||||
- key: readability-identifier-naming.ProtectedMemberPrefix
|
|
||||||
value: 'm_'
|
|
||||||
- key: readability-identifier-naming.PrivateMemberPrefix
|
|
||||||
value: 'm_'
|
|
||||||
HeaderFilterRegex: ''
|
HeaderFilterRegex: ''
|
||||||
WarningsAsErrors: ''
|
WarningsAsErrors: ''
|
||||||
AnalyzeTemporaryDtors: false
|
AnalyzeTemporaryDtors: false
|
||||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -12,6 +12,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Added
|
### Added
|
||||||
- An option `unmute-on-scroll` for `internal/pulseaudio` and `internal/alsa` to unmute audio when the user scrolls on the widget.
|
- An option `unmute-on-scroll` for `internal/pulseaudio` and `internal/alsa` to unmute audio when the user scrolls on the widget.
|
||||||
|
|
||||||
|
## [3.7.2] - 2024-08-17
|
||||||
|
### Fixed
|
||||||
|
- `custom/script`: When a script with `tail = true` received multiple lines quickly, only the first would get displayed ([`#3117`](https://github.com/polybar/polybar/issues/3117), [`#3119`](https://github.com/polybar/polybar/pull/3119)) by [@Isak05](https://github.com/Isak05)
|
||||||
|
- Token min-length calculations would behave differently when non-ASCII characters appear in the token ([`#3074`](https://github.com/polybar/polybar/issues/3074), [`#3087`](https://github.com/polybar/polybar/pull/3087)) by [@nklloyd](https://github.com/nklloyd)
|
||||||
|
- i3: Fix duplicated rendering for non-full-width bars ([`#3091`](https://github.com/polybar/polybar/pull/3091), [`#3060`](https://github.com/polybar/polybar/issues/3060))
|
||||||
|
- `internal/backlight`: Module could display the literal `%percentage%` token if the backlight reports a value of 0 at startup ([`#3081`](https://github.com/polybar/polybar/pull/3081)) by [@unclechu](https://github.com/unclechu)
|
||||||
|
- `internal/tray`: Fix crash during restarting, when tray icons were not removed proberly ([`#3111`](https://github.com/polybar/polybar/issues/3111), [`#3112`](https://github.com/polybar/polybar/pull/3112))
|
||||||
|
- `custom/ipc`: Module would display the literal `%output%` token before the initial hook finished executing ([`#3131`](https://github.com/polybar/polybar/issues/3131), [`#3140`](https://github.com/polybar/polybar/pull/3140))
|
||||||
|
- renderer: Pseudo-transparency rendering artifacts when wallpaper does not fill entire screen ([`#3096`](https://github.com/polybar/polybar/pull/3096), [`#3041`](https://github.com/polybar/polybar/issues/3041))
|
||||||
|
|
||||||
## [3.7.1] - 2023-11-27
|
## [3.7.1] - 2023-11-27
|
||||||
### Build
|
### Build
|
||||||
- Fixed missing header when using `libc++` in clang 15 and below
|
- Fixed missing header when using `libc++` in clang 15 and below
|
||||||
|
@ -260,7 +270,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Fixed
|
### Fixed
|
||||||
- Empty color values are no longer treated as invalid and no longer produce an error.
|
- Empty color values are no longer treated as invalid and no longer produce an error.
|
||||||
|
|
||||||
[Unreleased]: https://github.com/polybar/polybar/compare/3.7.1...HEAD
|
[Unreleased]: https://github.com/polybar/polybar/compare/3.7.2...HEAD
|
||||||
|
[3.7.2]: https://github.com/polybar/polybar/releases/tag/3.7.2
|
||||||
[3.7.1]: https://github.com/polybar/polybar/releases/tag/3.7.1
|
[3.7.1]: https://github.com/polybar/polybar/releases/tag/3.7.1
|
||||||
[3.7.0]: https://github.com/polybar/polybar/releases/tag/3.7.0
|
[3.7.0]: https://github.com/polybar/polybar/releases/tag/3.7.0
|
||||||
[3.6.3]: https://github.com/polybar/polybar/releases/tag/3.6.3
|
[3.6.3]: https://github.com/polybar/polybar/releases/tag/3.6.3
|
||||||
|
|
|
@ -64,6 +64,14 @@ enable-ipc = true
|
||||||
|
|
||||||
; override-redirect = true
|
; override-redirect = true
|
||||||
|
|
||||||
|
; This module is not active by default (to enable it, add it to one of the
|
||||||
|
; modules-* list above).
|
||||||
|
; Please note that only a single tray can exist at any time. If you launch
|
||||||
|
; multiple bars with this module, only a single one will show it, the others
|
||||||
|
; will produce a warning. Which bar gets the module is timing dependent and can
|
||||||
|
; be quite random.
|
||||||
|
; For more information, see the documentation page for this module:
|
||||||
|
; https://polybar.readthedocs.io/en/stable/user/modules/tray.html
|
||||||
[module/systray]
|
[module/systray]
|
||||||
type = internal/tray
|
type = internal/tray
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,16 @@ the Dropbox application).
|
||||||
Polybar is only responsible for embedding the windows in the bar and
|
Polybar is only responsible for embedding the windows in the bar and
|
||||||
positioning them correctly.
|
positioning them correctly.
|
||||||
|
|
||||||
.. note::
|
.. attention::
|
||||||
|
|
||||||
Only a single instance of this module can be active at the same time (across
|
Only a single instance of this module can be active at the same time (across
|
||||||
all polybar instances).
|
all polybar instances in the same graphical session).
|
||||||
|
|
||||||
The way the `system tray protocol <systray-spec_>`_ works, at most one tray
|
The way the `system tray protocol <systray-spec_>`_ works, at most one tray
|
||||||
can exist at any time.
|
can exist at any time.
|
||||||
Polybar will produce a warning if additional tray instances are created.
|
Polybar will produce a warning if additional tray instances are created.
|
||||||
|
This also applies when another tray application (e.g. ``stalonetray``) is
|
||||||
|
active.
|
||||||
|
|
||||||
For transparent background colors, the tray will use pseudo-transparency, true
|
For transparent background colors, the tray will use pseudo-transparency, true
|
||||||
transparency is not possible for the tray icons.
|
transparency is not possible for the tray icons.
|
||||||
|
|
|
@ -67,7 +67,12 @@ namespace modules {
|
||||||
brightness_handle m_val;
|
brightness_handle m_val;
|
||||||
brightness_handle m_max;
|
brightness_handle m_max;
|
||||||
|
|
||||||
int m_percentage = 0;
|
/**
|
||||||
|
* Initial value set to a negative number so that any value read from the backlight file triggers an update during
|
||||||
|
* the first read.
|
||||||
|
* Otherwise, tokens may not be replaced
|
||||||
|
*/
|
||||||
|
int m_percentage = -1;
|
||||||
|
|
||||||
chrono::duration<double> m_interval{};
|
chrono::duration<double> m_interval{};
|
||||||
chrono::steady_clock::time_point m_lastpoll;
|
chrono::steady_clock::time_point m_lastpoll;
|
||||||
|
|
|
@ -119,7 +119,7 @@ namespace modules {
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
string module<Impl>::contents() {
|
string module<Impl>::contents() {
|
||||||
if (m_changed) {
|
if (m_changed.exchange(false)) {
|
||||||
m_log.info("%s: Rebuilding cache", name());
|
m_log.info("%s: Rebuilding cache", name());
|
||||||
m_cache = CAST_MOD(Impl)->get_output();
|
m_cache = CAST_MOD(Impl)->get_output();
|
||||||
// Make sure builder is really empty
|
// Make sure builder is really empty
|
||||||
|
@ -129,7 +129,6 @@ namespace modules {
|
||||||
m_builder->control(tags::controltag::R);
|
m_builder->control(tags::controltag::R);
|
||||||
m_cache += m_builder->flush();
|
m_cache += m_builder->flush();
|
||||||
}
|
}
|
||||||
m_changed = false;
|
|
||||||
}
|
}
|
||||||
return m_cache;
|
return m_cache;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ class command<output_policy::REDIRECTED> : private command<output_policy::IGNORE
|
||||||
|
|
||||||
void tail(std::function<void(string)> cb);
|
void tail(std::function<void(string)> cb);
|
||||||
string readline();
|
string readline();
|
||||||
|
bool wait_for_data(int timeout_ms);
|
||||||
|
|
||||||
int get_stdout(int c);
|
int get_stdout(int c);
|
||||||
int get_stdin(int c);
|
int get_stdin(int c);
|
||||||
|
|
|
@ -155,7 +155,7 @@ script_runner::interval script_runner::run_tail() {
|
||||||
assert(fd != -1);
|
assert(fd != -1);
|
||||||
|
|
||||||
while (!m_stopping && cmd.is_running() && !io_util::poll(fd, POLLHUP, 0)) {
|
while (!m_stopping && cmd.is_running() && !io_util::poll(fd, POLLHUP, 0)) {
|
||||||
if (io_util::poll_read(fd, 250)) {
|
if (cmd.wait_for_data(250)) {
|
||||||
auto changed = set_output(cmd.readline());
|
auto changed = set_output(cmd.readline());
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
|
|
@ -86,14 +86,6 @@ renderer::renderer(connection& conn, signal_emitter& sig, const config& conf, co
|
||||||
{
|
{
|
||||||
m_pixmap = m_connection.generate_id();
|
m_pixmap = m_connection.generate_id();
|
||||||
m_connection.create_pixmap(m_depth, m_pixmap, m_window, m_bar.size.w, m_bar.size.h);
|
m_connection.create_pixmap(m_depth, m_pixmap, m_window, m_bar.size.w, m_bar.size.h);
|
||||||
|
|
||||||
uint32_t configure_mask = 0;
|
|
||||||
std::array<uint32_t, 32> configure_values{};
|
|
||||||
xcb_params_cw_t configure_params{};
|
|
||||||
|
|
||||||
XCB_AUX_ADD_PARAM(&configure_mask, &configure_params, back_pixmap, m_pixmap);
|
|
||||||
connection::pack_values(configure_mask, &configure_params, configure_values);
|
|
||||||
m_connection.change_window_attributes_checked(m_window, configure_mask, configure_values.data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("renderer: Allocate graphic contexts");
|
m_log.trace("renderer: Allocate graphic contexts");
|
||||||
|
@ -372,8 +364,8 @@ void renderer::flush() {
|
||||||
highlight_clickable_areas();
|
highlight_clickable_areas();
|
||||||
|
|
||||||
m_surface->flush();
|
m_surface->flush();
|
||||||
// Clear entire window so that the new pixmap is shown
|
// Copy pixmap onto the window
|
||||||
m_connection.clear_area(0, m_window, 0, 0, m_bar.size.w, m_bar.size.h);
|
m_connection.copy_area(m_pixmap, m_window, m_gcontext, 0, 0, 0, 0, m_bar.size.w, m_bar.size.h);
|
||||||
m_connection.flush();
|
m_connection.flush();
|
||||||
|
|
||||||
if (!m_snapshot_dst.empty()) {
|
if (!m_snapshot_dst.empty()) {
|
||||||
|
|
|
@ -82,14 +82,15 @@ namespace drawtypes {
|
||||||
|
|
||||||
for (auto&& tok : m_tokens) {
|
for (auto&& tok : m_tokens) {
|
||||||
string repl{replacement};
|
string repl{replacement};
|
||||||
|
size_t len = string_util::char_len(repl);
|
||||||
if (token == tok.token) {
|
if (token == tok.token) {
|
||||||
if (tok.max != 0_z && string_util::char_len(repl) > tok.max) {
|
if (tok.max != 0_z && len > tok.max) {
|
||||||
repl = string_util::utf8_truncate(std::move(repl), tok.max) + tok.suffix;
|
repl = string_util::utf8_truncate(std::move(repl), tok.max) + tok.suffix;
|
||||||
} else if (tok.min != 0_z && repl.length() < tok.min) {
|
} else if (tok.min != 0_z && len < tok.min) {
|
||||||
if (tok.rpadding) {
|
if (tok.rpadding) {
|
||||||
repl.append(tok.min - repl.length(), ' ');
|
repl.append(tok.min - len, ' ');
|
||||||
} else {
|
} else {
|
||||||
repl.insert(0_z, tok.min - repl.length(), tok.zpad ? '0' : ' ');
|
repl.insert(0_z, tok.min - len, tok.zpad ? '0' : ' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ namespace modules {
|
||||||
this->module::start();
|
this->module::start();
|
||||||
m_mainthread = thread([&] {
|
m_mainthread = thread([&] {
|
||||||
m_log.trace("%s: Thread id = %i", this->name(), concurrency_util::thread_id(this_thread::get_id()));
|
m_log.trace("%s: Thread id = %i", this->name(), concurrency_util::thread_id(this_thread::get_id()));
|
||||||
|
// Initial update to start with an empty output until the initial hook finishes
|
||||||
|
update_output();
|
||||||
update();
|
update();
|
||||||
broadcast();
|
broadcast();
|
||||||
});
|
});
|
||||||
|
|
|
@ -201,6 +201,14 @@ string command<output_policy::REDIRECTED>::readline() {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until there is data in the output stream or until timeout_ms milliseconds
|
||||||
|
*/
|
||||||
|
bool command<output_policy::REDIRECTED>::wait_for_data(int timeout_ms) {
|
||||||
|
return (m_stdout_reader && m_stdout_reader->rdbuf()->in_avail() > 0) ||
|
||||||
|
io_util::poll_read(get_stdout(PIPE_READ), timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get command output channel
|
* Get command output channel
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -220,13 +220,34 @@ void bg_slice::copy(xcb_pixmap_t root_pixmap, int depth, xcb_rectangle_t geom, x
|
||||||
ensure_resources(depth, visual);
|
ensure_resources(depth, visual);
|
||||||
assert(m_pixmap);
|
assert(m_pixmap);
|
||||||
|
|
||||||
// fill the slice
|
auto pixmap_end_x = int16_t(geom.x + geom.width);
|
||||||
|
auto pixmap_end_y = int16_t(geom.y + geom.height);
|
||||||
|
|
||||||
auto translated = m_connection.translate_coordinates(m_window, m_connection.screen()->root, m_rect.x, m_rect.y);
|
auto translated = m_connection.translate_coordinates(m_window, m_connection.screen()->root, m_rect.x, m_rect.y);
|
||||||
// Coordinates of the slice in the root pixmap
|
|
||||||
auto src_x = math_util::cap(translated->dst_x, geom.x, int16_t(geom.x + geom.width));
|
/*
|
||||||
auto src_y = math_util::cap(translated->dst_y, geom.y, int16_t(geom.y + geom.height));
|
* If the slice is not fully contained in the root pixmap, we will be missing at least some background pixels. For
|
||||||
|
* those areas, nothing is copied over and a simple black background is shown.
|
||||||
|
* This can happen when connecting new monitors without updating the root pixmap.
|
||||||
|
*/
|
||||||
|
if (!(translated->dst_x >= geom.x && translated->dst_x + m_rect.width <= pixmap_end_x &&
|
||||||
|
translated->dst_y >= geom.y && translated->dst_y + m_rect.height <= pixmap_end_y)) {
|
||||||
|
m_log.err(
|
||||||
|
"background_manager: Root pixmap does not fully cover transparent areas. "
|
||||||
|
"Pseudo-transparency may not fully work and instead just show a black background. "
|
||||||
|
"Make sure you have a wallpaper set on all of your screens");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coordinates of the slice in the root pixmap. The rectangle is capped so that it is contained in the root pixmap to
|
||||||
|
* avoid copying areas not covered by the pixmap.
|
||||||
|
*/
|
||||||
|
auto src_x = math_util::cap(translated->dst_x, geom.x, pixmap_end_x);
|
||||||
|
auto src_y = math_util::cap(translated->dst_y, geom.y, pixmap_end_x);
|
||||||
auto w = math_util::cap(m_rect.width, uint16_t(0), uint16_t(geom.width - (src_x - geom.x)));
|
auto w = math_util::cap(m_rect.width, uint16_t(0), uint16_t(geom.width - (src_x - geom.x)));
|
||||||
auto h = math_util::cap(m_rect.height, uint16_t(0), uint16_t(geom.height - (src_y - geom.y)));
|
auto h = math_util::cap(m_rect.height, uint16_t(0), uint16_t(geom.height - (src_y - geom.y)));
|
||||||
|
|
||||||
|
// fill the slice
|
||||||
m_log.trace(
|
m_log.trace(
|
||||||
"background_manager: Copying from root pixmap (0x%x:%d) %dx%d+%d+%d", root_pixmap, depth, w, h, src_x, src_y);
|
"background_manager: Copying from root pixmap (0x%x:%d) %dx%d+%d+%d", root_pixmap, depth, w, h, src_x, src_y);
|
||||||
m_connection.copy_area_checked(root_pixmap, m_pixmap, m_gcontext, src_x, src_y, 0, 0, w, h);
|
m_connection.copy_area_checked(root_pixmap, m_pixmap, m_gcontext, src_x, src_y, 0, 0, w, h);
|
||||||
|
@ -257,12 +278,18 @@ void bg_slice::allocate_resources(xcb_visualtype_t* visual) {
|
||||||
XCB_AUX_ADD_PARAM(&mask, ¶ms, foreground, black_pixel);
|
XCB_AUX_ADD_PARAM(&mask, ¶ms, foreground, black_pixel);
|
||||||
XCB_AUX_ADD_PARAM(&mask, ¶ms, background, black_pixel);
|
XCB_AUX_ADD_PARAM(&mask, ¶ms, background, black_pixel);
|
||||||
XCB_AUX_ADD_PARAM(&mask, ¶ms, graphics_exposures, 0);
|
XCB_AUX_ADD_PARAM(&mask, ¶ms, graphics_exposures, 0);
|
||||||
m_connection.pack_values(mask, ¶ms, value_list);
|
connection::pack_values(mask, ¶ms, value_list);
|
||||||
m_gcontext = m_connection.generate_id();
|
m_gcontext = m_connection.generate_id();
|
||||||
m_connection.create_gc(m_gcontext, m_pixmap, mask, value_list.data());
|
m_connection.create_gc(m_gcontext, m_pixmap, mask, value_list.data());
|
||||||
|
|
||||||
m_log.trace("background_manager: Allocating cairo surface");
|
m_log.trace("background_manager: Allocating cairo surface");
|
||||||
m_surface = make_unique<cairo::xcb_surface>(m_connection, m_pixmap, visual, m_rect.width, m_rect.height);
|
m_surface = make_unique<cairo::xcb_surface>(m_connection, m_pixmap, visual, m_rect.width, m_rect.height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill pixmap with black in case it is not fully filled by the root pixmap. Otherwise we may render uninitialized
|
||||||
|
* memory
|
||||||
|
*/
|
||||||
|
m_connection.poly_fill_rectangle(m_pixmap, m_gcontext, 1, &m_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bg_slice::free_resources() {
|
void bg_slice::free_resources() {
|
||||||
|
|
|
@ -502,7 +502,8 @@ void manager::remove_client(const client& c) {
|
||||||
void manager::remove_client(xcb_window_t win) {
|
void manager::remove_client(xcb_window_t win) {
|
||||||
auto old_size = m_clients.size();
|
auto old_size = m_clients.size();
|
||||||
m_clients.erase(
|
m_clients.erase(
|
||||||
std::remove_if(m_clients.begin(), m_clients.end(), [win](const auto& client) { return client->match(win); }));
|
std::remove_if(m_clients.begin(), m_clients.end(), [win](const auto& client) { return client->match(win); }),
|
||||||
|
m_clients.end());
|
||||||
|
|
||||||
if (old_size != m_clients.size()) {
|
if (old_size != m_clients.size()) {
|
||||||
reconfigure();
|
reconfigure();
|
||||||
|
@ -518,7 +519,8 @@ void manager::remove_client(xcb_window_t win) {
|
||||||
*/
|
*/
|
||||||
void manager::clean_clients() {
|
void manager::clean_clients() {
|
||||||
m_clients.erase(
|
m_clients.erase(
|
||||||
std::remove_if(m_clients.begin(), m_clients.end(), [](const auto& client) { return client.get() == nullptr; }));
|
std::remove_if(m_clients.begin(), m_clients.end(), [](const auto& client) { return client.get() == nullptr; }),
|
||||||
|
m_clients.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool manager::change_visibility(bool visible) {
|
bool manager::change_visibility(bool visible) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Polybar version information
|
# Polybar version information
|
||||||
# Update this on every release
|
# Update this on every release
|
||||||
# This is used to create the version string if a git repo is not available
|
# This is used to create the version string if a git repo is not available
|
||||||
3.7.1
|
3.7.2
|
||||||
|
|
Loading…
Reference in a new issue