60542da091
"Set" the wallpaper during startup only sometimes
Since commit 4f5e0e7
, i3 would take a screenshot and set that as the
background pixmap of the root window during startup. This is the easy
part of setting a proper X11 wallpaper.
The code in question was added because something either set the
background pixmap of the root window to NONE or the X11 server was
started with "-background none". This is apparently done by default by
e.g. gdm to avoid some flickering while the X11 server starts up.
This commit makes this code conditional: Only when no wallpaper is
detected is a screenshot taken.
Since I could not find any way to query the background of a window, a
more direct approach is taken to detect this situation: First, we find
some part of the root window that is not currently covered. Then we open
a white window there, close it again and grab a screenshot. If a
wallpaper is set, the X11 server will draw this wallpaper after the
window is closed and something else will be visible in the screenshot.
However, the wallpaper could have a white pixel at the tested position.
Thus, this procedure is repeated with a black window.
Only when this procedure produces two different pixel values is a
screenshot taken and set as the wallpaper.
Fixes: https://github.com/i3/i3/issues/4371
Fixes: https://github.com/i3/i3/issues/2869
Signed-off-by: Uli Schlachter <psychon@znc.in>
28 lines
1.0 KiB
C
28 lines
1.0 KiB
C
/*
|
|
* vim:ts=4:sw=4:expandtab
|
|
*
|
|
* i3 - an improved dynamic tiling window manager
|
|
* © 2009 Michael Stapelberg and contributors (see also: LICENSE)
|
|
*
|
|
*/
|
|
#include "libi3.h"
|
|
|
|
void set_screenshot_as_wallpaper(xcb_connection_t *conn, xcb_screen_t *screen) {
|
|
uint16_t width = screen->width_in_pixels;
|
|
uint16_t height = screen->height_in_pixels;
|
|
xcb_pixmap_t pixmap = xcb_generate_id(conn);
|
|
xcb_gcontext_t gc = xcb_generate_id(conn);
|
|
|
|
xcb_create_pixmap(conn, screen->root_depth, pixmap, screen->root, width, height);
|
|
|
|
xcb_create_gc(conn, gc, screen->root,
|
|
XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
|
|
(uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
|
|
|
|
xcb_copy_area(conn, screen->root, pixmap, gc, 0, 0, 0, 0, width, height);
|
|
xcb_change_window_attributes(conn, screen->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap});
|
|
xcb_free_gc(conn, gc);
|
|
xcb_free_pixmap(conn, pixmap);
|
|
xcb_flush(conn);
|
|
}
|