From 2c7399e3590cccd23b834f4b76193d918be56bb4 Mon Sep 17 00:00:00 2001 From: Ashesh Ambasta Date: Wed, 27 May 2026 16:23:56 +0200 Subject: 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. --- src/Xmobar/X11/XRender.hsc | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'src/Xmobar') 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 -- cgit v1.2.3