summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAshesh Ambasta <ashesh.ambasta@gmail.com>2026-05-27 16:23:56 +0200
committerAshesh Ambasta <ashesh.ambasta@gmail.com>2026-05-29 10:31:36 +0200
commit2c7399e3590cccd23b834f4b76193d918be56bb4 (patch)
tree908d8aa990cfda0929274102cf9477257c52b3bf
parent6cf589469e7d93c20522b3c0ae616255766759e1 (diff)
downloadxmobar-2c7399e3590cccd23b834f4b76193d918be56bb4.tar.gz
xmobar-2c7399e3590cccd23b834f4b76193d918be56bb4.tar.bz2
Skip root pixmap access when alpha == 255
When alpha is 255 (fully opaque), the pseudo-transparency blend factor is zero (0xFFFF - 257 * 255 = 0), making the root pixmap composite a visual no-op. However, drawBackground unconditionally calls XRenderCreatePicture on the _XROOTPMAP_ID pixmap. Wallpaper setters like feh free the old root pixmap via XKillClient each time they cycle to a new image. If xmobar attempts XRenderCreatePicture on the freed pixmap, the X server returns BadDrawable and the default error handler terminates xmobar. Guard the entire root pixmap code path with `when (alpha < 255)` so that fully opaque bars never touch _XROOTPMAP_ID.
-rw-r--r--changelog.md1
-rw-r--r--src/Xmobar/X11/XRender.hsc38
2 files changed, 23 insertions, 16 deletions
diff --git a/changelog.md b/changelog.md
index aeb07e3..bc56e1d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,6 @@
## Version 0.51 (unrelease)
+- Fix BadDrawable crash when wallpaper setters free the root pixmap while alpha is 255
- base dependency relaxed to 4.21
## Version 0.50 (June, 2025)
diff --git a/src/Xmobar/X11/XRender.hsc b/src/Xmobar/X11/XRender.hsc
index 5ad0391..4e4d448 100644
--- a/src/Xmobar/X11/XRender.hsc
+++ b/src/Xmobar/X11/XRender.hsc
@@ -91,22 +91,28 @@ drawBackground d p bgc alpha (Rectangle x y wid ht) = do
withRenderFill d
(XRenderColor 0 0 0 (257 * alpha))
(render pictOpSrc bgfill pic)
- -- Handle transparency
- internAtom d "_XROOTPMAP_ID" False >>= \xid ->
- let xroot = defaultRootWindow d in
- alloca $ \x1 ->
- alloca $ \x2 ->
- alloca $ \x3 ->
- alloca $ \x4 ->
- alloca $ \pprop -> do
- xGetWindowProperty d xroot xid 0 1 False 20 x1 x2 x3 x4 pprop
- prop <- peek pprop
- when (prop /= nullPtr) $ do
- rootbg <- peek (castPtr prop) :: IO Pixmap
- xFree prop
- withRenderPicture d rootbg $ \bgpic ->
- withRenderFill d (XRenderColor 0 0 0 (0xFFFF - 257 * alpha))
- (render pictOpAdd bgpic pic)
+ -- Handle pseudo-transparency by compositing the root pixmap.
+ -- Skip entirely when alpha == 255 (fully opaque) since the blend
+ -- factor would be zero, making this a no-op. More importantly,
+ -- the root pixmap (_XROOTPMAP_ID) can be freed at any time by
+ -- wallpaper setters like feh (via XKillClient), causing a
+ -- BadDrawable crash in XRenderCreatePicture if we touch it.
+ when (alpha < 255) $
+ internAtom d "_XROOTPMAP_ID" False >>= \xid ->
+ let xroot = defaultRootWindow d in
+ alloca $ \x1 ->
+ alloca $ \x2 ->
+ alloca $ \x3 ->
+ alloca $ \x4 ->
+ alloca $ \pprop -> do
+ xGetWindowProperty d xroot xid 0 1 False 20 x1 x2 x3 x4 pprop
+ prop <- peek pprop
+ when (prop /= nullPtr) $ do
+ rootbg <- peek (castPtr prop) :: IO Pixmap
+ xFree prop
+ withRenderPicture d rootbg $ \bgpic ->
+ withRenderFill d (XRenderColor 0 0 0 (0xFFFF - 257 * alpha))
+ (render pictOpAdd bgpic pic)
-- | Parses color into XRender color (allocation not necessary!)
parseRenderColor :: Display -> String -> IO XRenderColor