fix(render): Deal with incomplete wallpapers
If the root pixmap does not fully cover the bar window, some pseudo-transparent areas were filled with unitialized data, causing pixelation or other rendering artifacts. Now, ovserved background slices are first filled with black to make sure this does not happen and they print an error if not the full pixmap can be filled. Fixes #3041
This commit is contained in:
parent
35638027a8
commit
c0d3d7a3e7
@ -40,6 +40,7 @@ CheckOptions:
|
|||||||
readability-identifier-naming.MemberCase: lower_case
|
readability-identifier-naming.MemberCase: lower_case
|
||||||
readability-identifier-naming.ProtectedMemberPrefix: 'm_'
|
readability-identifier-naming.ProtectedMemberPrefix: 'm_'
|
||||||
readability-identifier-naming.PrivateMemberPrefix: 'm_'
|
readability-identifier-naming.PrivateMemberPrefix: 'm_'
|
||||||
|
readability-simplify-boolean-expr.SimplifyDeMorgan: false
|
||||||
|
|
||||||
HeaderFilterRegex: ''
|
HeaderFilterRegex: ''
|
||||||
WarningsAsErrors: ''
|
WarningsAsErrors: ''
|
||||||
|
@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `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/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))
|
- `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))
|
- `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
|
||||||
|
@ -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() {
|
||||||
|
Loading…
Reference in New Issue
Block a user