Shape the window when there is no compositor

On Xfce with compositing off, X11 has no alpha to blend against, so the
transparent background came out as a black box around the cat.

When a window comes up without an alpha channel, TNCat now cuts the window down
to the pixels the drawing covers, using the X11 shape extension, and refreshes
that 15 times a second so it follows the animation. A sitting cat in a 120 x 106
window comes out as 96 rectangles over 29 percent of the window, so most of the
box is gone. Edges are harder than with a compositor, one bit per pixel, and the
log says so and names the Xfce setting that gives smooth ones instead.

The image-to-rectangles step is platform independent and folds every device row
into its window row, which both halves the rectangle count on a scaled display
and keeps a pixel that is opaque in only one of them.

xcb and xcb-shape are picked up through pkg-config on Unix and the build still
works without them. Opaque mode now paints a neutral card rather than the coat
colour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
JulianandClaude Opus 5 committed 2026-09-11 09:49:51 +02:00
1 parent 0aceb3665d
commit d685bf492a
9 files changed
+284 -11

No files matched your search

+19
View File
@@ -17,6 +17,7 @@ qt_add_executable(tncat
src/catcontroller.h src/catcontroller.cpp
src/appsettings.h src/appsettings.cpp
src/platforminfo.h src/platforminfo.cpp
src/windowshape.h src/windowshape.cpp
)
target_include_directories(tncat PRIVATE src)
@@ -38,6 +39,24 @@ qt_add_qml_module(tncat
target_link_libraries(tncat PRIVATE
Qt6::Core Qt6::Gui Qt6::Quick Qt6::QuickShapes)
# Without a compositor, X11 renders a transparent background as black. The
# shape extension is the way out: it cuts the window down to the cat itself.
# Both libraries ship with X11 and Qt's own xcb plugin already uses them.
if(UNIX AND NOT APPLE)
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
pkg_check_modules(TNCAT_XCB IMPORTED_TARGET xcb xcb-shape)
endif()
if(TARGET PkgConfig::TNCAT_XCB)
target_link_libraries(tncat PRIVATE PkgConfig::TNCAT_XCB)
target_compile_definitions(tncat PRIVATE TNCAT_HAVE_XCB_SHAPE)
else()
message(STATUS "TNCat: xcb-shape not found. Without a compositor the cat "
"will sit in a black box; install libxcb-shape0-dev or "
"xcb-util-dev and reconfigure.")
endif()
endif()
set_target_properties(tncat PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/Info.plist.in