Merge pull request #995 from absolutelynothelix/begone-xinerama

This commit is contained in:
Yuxuan Shui 2023-01-29 15:36:04 +00:00 committed by GitHub
commit 317275abf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 143 additions and 153 deletions

View File

@ -36,7 +36,7 @@ jobs:
languages: ${{ matrix.language }}
# Install dependencies
- run: sudo apt update && sudo apt install libxext-dev libxcb1-dev libxcb-dpms0-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-xinerama0-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl1-mesa-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson ninja-build
- run: sudo apt update && sudo apt install libxext-dev libxcb1-dev libxcb-dpms0-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl1-mesa-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson ninja-build
if: ${{ matrix.language == 'cpp' }}
# Autobuild

View File

@ -32,7 +32,6 @@ Assuming you already have all the usual building tools installed (e.g. gcc, pyth
* xcb-composite
* xcb-image
* xcb-present
* xcb-xinerama
* xcb-glx
* pixman
* libdbus (optional, disable with the `-Ddbus=false` meson configure flag)
@ -45,7 +44,7 @@ Assuming you already have all the usual building tools installed (e.g. gcc, pyth
On Debian based distributions (e.g. Ubuntu), the needed packages are
```
libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-dpms0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-xinerama0-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl-dev libegl-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson
libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-dpms0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl-dev libegl-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson
```
On Fedora, the needed packages are

View File

@ -217,8 +217,8 @@ May also be one of the predefined kernels: `3x3box` (default), `5x5box`, `7x7box
*--shadow-exclude-reg* 'GEOMETRY'::
Specify a X geometry that describes the region in which shadow should not be painted in, such as a dock window region. Use `--shadow-exclude-reg x10+0-0`, for example, if the 10 pixels on the bottom of the screen should not have shadows painted on.
*--xinerama-shadow-crop*::
Crop shadow of a window fully on a particular Xinerama screen to the screen.
*--crop-shadow-to-monitor*::
Crop shadow of a window fully on a particular monitor to that monitor. This is currently implemented using the X RandR extension.
*--backend* 'BACKEND'::
Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. `xrender` is the default one.

View File

@ -61,8 +61,9 @@ shadow-exclude = [
#
# shadow-exclude-reg = ""
# Crop shadow of a window fully on a particular Xinerama screen to the screen.
# xinerama-shadow-crop = false
# Crop shadow of a window fully on a particular monitor to that monitor. This is
# currently implemented using the X RandR extension.
# crop-shadow-to-monitor = false
#################################

View File

@ -327,18 +327,18 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
&reg_shadow_clip);
}
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0 &&
w->xinerama_scr < ps->xinerama_nscrs) {
// There can be a window where number of screens is
// updated, but the screen number attached to the windows
if (ps->o.crop_shadow_to_monitor && w->randr_monitor >= 0 &&
w->randr_monitor < ps->randr_nmonitors) {
// There can be a window where number of monitors is
// updated, but the monitor number attached to the window
// have not.
//
// Window screen number will be updated eventually, so
// Window monitor number will be updated eventually, so
// here we just check to make sure we don't access out of
// bounds.
pixman_region32_intersect(
&reg_shadow, &reg_shadow,
&ps->xinerama_scr_regs[w->xinerama_scr]);
&ps->randr_monitor_regs[w->randr_monitor]);
}
if (ps->o.transparent_clipping) {

View File

@ -368,12 +368,10 @@ typedef struct session {
int glx_event;
/// Error base number for X GLX extension.
int glx_error;
/// Whether X Xinerama extension exists.
bool xinerama_exists;
/// Xinerama screen regions.
region_t *xinerama_scr_regs;
/// Number of Xinerama screens.
int xinerama_nscrs;
/// Number of X RandR monitors.
int randr_nmonitors;
/// X RandR monitor regions.
region_t *randr_monitor_regs;
/// Whether X Sync extension exists.
bool xsync_exists;
/// Event base number for X Sync extension.

View File

@ -747,7 +747,7 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
.shadow_opacity = .75,
.shadow_blacklist = NULL,
.shadow_ignore_shaped = false,
.xinerama_shadow_crop = false,
.crop_shadow_to_monitor = false,
.shadow_clip_list = NULL,
.corner_radius = 0,

View File

@ -153,8 +153,8 @@ typedef struct options {
c2_lptr_t *shadow_blacklist;
/// Whether bounding-shaped window should be ignored.
bool shadow_ignore_shaped;
/// Whether to crop shadow to the very Xinerama screen.
bool xinerama_shadow_crop;
/// Whether to crop shadow to the very X RandR monitor.
bool crop_shadow_to_monitor;
/// Don't draw shadow over these windows. A linked list of conditions.
c2_lptr_t *shadow_clip_list;

View File

@ -384,8 +384,12 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", &opt->shadow_ignore_shaped);
// --detect-rounded-corners
lcfg_lookup_bool(&cfg, "detect-rounded-corners", &opt->detect_rounded_corners);
// --xinerama-shadow-crop
lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", &opt->xinerama_shadow_crop);
// --crop-shadow-to-monitor
if (lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", &opt->crop_shadow_to_monitor)) {
log_warn("xinerama-shadow-crop is deprecated. Use crop-shadow-to-monitor "
"instead.");
}
lcfg_lookup_bool(&cfg, "crop-shadow-to-monitor", &opt->crop_shadow_to_monitor);
// --detect-client-opacity
lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity);
// --refresh-rate

View File

@ -1202,7 +1202,7 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
cdbus_m_opts_get_do(shadow_offset_x, cdbus_reply_int32);
cdbus_m_opts_get_do(shadow_offset_y, cdbus_reply_int32);
cdbus_m_opts_get_do(shadow_opacity, cdbus_reply_double);
cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool);
cdbus_m_opts_get_do(crop_shadow_to_monitor, cdbus_reply_bool);
cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32);
cdbus_m_opts_get_do(fade_in_step, cdbus_reply_double);

View File

@ -2,21 +2,21 @@
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
#include <stdio.h>
#include <xcb/xcb.h>
#include <xcb/composite.h>
#include <xcb/xcb.h>
#include "backend/driver.h"
#include "diagnostic.h"
#include "config.h"
#include "picom.h"
#include "common.h"
#include "config.h"
#include "diagnostic.h"
#include "picom.h"
void print_diagnostics(session_t *ps, const char *config_file, bool compositor_running) {
printf("**Version:** " PICOM_VERSION "\n");
//printf("**CFLAGS:** %s\n", "??");
// printf("**CFLAGS:** %s\n", "??");
printf("\n### Extensions:\n\n");
printf("* Shape: %s\n", ps->shape_exists ? "Yes" : "No");
printf("* XRandR: %s\n", ps->randr_exists ? "Yes" : "No");
printf("* RandR: %s\n", ps->randr_exists ? "Yes" : "No");
printf("* Present: %s\n", ps->present_exists ? "Present" : "Not Present");
printf("\n### Misc:\n\n");
printf("* Use Overlay: %s\n", ps->overlay != XCB_NONE ? "Yes" : "No");

View File

@ -237,8 +237,8 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
win_set_flags(mw, WIN_FLAGS_SIZE_STALE);
}
// Recalculate which screen this window is on
win_update_screen(ps->xinerama_nscrs, ps->xinerama_scr_regs, mw);
// Recalculate which monitor this window is on
win_update_monitor(ps->randr_nmonitors, ps->randr_monitor_regs, mw);
}
// override_redirect flag cannot be changed after window creation, as far

View File

@ -16,8 +16,7 @@ cflags = []
required_xcb_packages = [
'xcb-render', 'xcb-damage', 'xcb-randr', 'xcb-sync', 'xcb-composite',
'xcb-shape', 'xcb-xinerama', 'xcb-xfixes', 'xcb-present', 'xcb-glx',
'xcb-dpms', 'xcb'
'xcb-shape', 'xcb-xfixes', 'xcb-present', 'xcb-glx', 'xcb-dpms', 'xcb'
]
required_packages = [

View File

@ -72,6 +72,9 @@ static const struct picom_option picom_options[] = {
"managers not passing _NET_WM_WINDOW_OPACITY of client windows to frame"},
{"refresh-rate" , required_argument, 269, NULL , NULL},
{"vsync" , optional_argument, 270, NULL , "Enable VSync"},
{"crop-shadow-to-monitor" , no_argument , 271, NULL , "Crop shadow of a window fully on a particular monitor to that monitor. "
"This is currently implemented using the X RandR extension"},
{"xinerama-shadow-crop" , no_argument , 272, NULL , NULL},
{"sw-opti" , no_argument , 274, NULL , NULL},
{"vsync-aggressive" , no_argument , 275, NULL , NULL},
{"use-ewmh-active-win" , no_argument , 276, NULL , "Use _NET_WM_ACTIVE_WINDOW on the root window to determine which window is "
@ -119,7 +122,6 @@ static const struct picom_option picom_options[] = {
{"opacity-rule" , required_argument, 304, "OPACITY:COND", "Specify a list of opacity rules, see man page for more details"},
{"shadow-exclude-reg" , required_argument, 305, NULL , NULL},
{"paint-exclude" , required_argument, 306, NULL , NULL},
{"xinerama-shadow-crop" , no_argument , 307, NULL , "Crop shadow of a window fully on a particular Xinerama screen to the screen."},
{"unredir-if-possible-exclude" , required_argument, 308, "COND" , "Conditions of windows that shouldn't be considered full-screen for "
"unredirecting screen."},
{"unredir-if-possible-delay" , required_argument, 309, NULL, "Delay before unredirecting the window, in milliseconds. Defaults to 0."},
@ -485,8 +487,8 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
P_CASEBOOL(267, detect_rounded_corners);
P_CASEBOOL(268, detect_client_opacity);
case 269:
log_warn("--refresh-rate has been deprecated, please remove it from"
"your command line options");
log_warn("--refresh-rate has been deprecated, please remove it "
"from your command line options");
break;
case 270:
if (optarg) {
@ -499,6 +501,12 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
opt->vsync = true;
}
break;
P_CASEBOOL(271, crop_shadow_to_monitor);
case 272:
opt->crop_shadow_to_monitor = true;
log_warn("--xinerama-shadow-crop is deprecated. Use "
"--crop-shadow-to-monitor instead.");
break;
case 274:
log_warn("--sw-opti has been deprecated, please remove it from the "
"command line options");
@ -506,7 +514,7 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
case 275:
// --vsync-aggressive
log_error("--vsync-aggressive has been removed, please remove it"
" from the command line options");
" from the command line options");
failed = true;
break;
P_CASEBOOL(276, use_ewmh_active_win);
@ -625,7 +633,6 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
// --paint-exclude
condlst_add(&opt->paint_blacklist, optarg);
break;
P_CASEBOOL(307, xinerama_shadow_crop);
case 308:
// --unredir-if-possible-exclude
condlst_add(&opt->unredir_if_possible_blacklist, optarg);

View File

@ -28,7 +28,6 @@
#include <xcb/render.h>
#include <xcb/sync.h>
#include <xcb/xfixes.h>
#include <xcb/xinerama.h>
#include <ev.h>
#include <test.h>
@ -111,21 +110,6 @@ void quit(session_t *ps) {
ev_break(ps->loop, EVBREAK_ALL);
}
/**
* Free Xinerama screen info.
*
* XXX consider moving to x.c
*/
static inline void free_xinerama_info(session_t *ps) {
if (ps->xinerama_scr_regs) {
for (int i = 0; i < ps->xinerama_nscrs; ++i)
pixman_region32_fini(&ps->xinerama_scr_regs[i]);
free(ps->xinerama_scr_regs);
ps->xinerama_scr_regs = NULL;
}
ps->xinerama_nscrs = 0;
}
/**
* Get current system clock in milliseconds.
*/
@ -135,41 +119,6 @@ static inline int64_t get_time_ms(void) {
return (int64_t)tp.tv_sec * 1000 + (int64_t)tp.tv_nsec / 1000000;
}
// XXX Move to x.c
void cxinerama_upd_scrs(session_t *ps) {
// XXX Consider deprecating Xinerama, switch to RandR when necessary
free_xinerama_info(ps);
if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists)
return;
xcb_xinerama_is_active_reply_t *active =
xcb_xinerama_is_active_reply(ps->c, xcb_xinerama_is_active(ps->c), NULL);
if (!active || !active->state) {
free(active);
return;
}
free(active);
auto xinerama_scrs =
xcb_xinerama_query_screens_reply(ps->c, xcb_xinerama_query_screens(ps->c), NULL);
if (!xinerama_scrs) {
return;
}
xcb_xinerama_screen_info_t *scrs =
xcb_xinerama_query_screens_screen_info(xinerama_scrs);
ps->xinerama_nscrs = xcb_xinerama_query_screens_screen_info_length(xinerama_scrs);
ps->xinerama_scr_regs = ccalloc(ps->xinerama_nscrs, region_t);
for (int i = 0; i < ps->xinerama_nscrs; ++i) {
const xcb_xinerama_screen_info_t *const s = &scrs[i];
pixman_region32_init_rect(&ps->xinerama_scr_regs[i], s->x_org, s->y_org,
s->width, s->height);
}
free(xinerama_scrs);
}
static inline bool dpms_screen_is_off(xcb_dpms_info_reply_t *info) {
// state is a bool indicating whether dpms is enabled
return info->state && (info->power_level != XCB_DPMS_DPMS_MODE_ON);
@ -691,8 +640,8 @@ static void configure_root(session_t *ps) {
static void handle_root_flags(session_t *ps) {
if ((ps->root_flags & ROOT_FLAGS_SCREEN_CHANGE) != 0) {
if (ps->o.xinerama_shadow_crop) {
cxinerama_upd_scrs(ps);
if (ps->o.crop_shadow_to_monitor) {
x_update_randr_monitors(ps);
}
ps->root_flags &= ~(uint64_t)ROOT_FLAGS_SCREEN_CHANGE;
}
@ -1834,7 +1783,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
xcb_prefetch_extension_data(ps->c, &xcb_shape_id);
xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id);
xcb_prefetch_extension_data(ps->c, &xcb_randr_id);
xcb_prefetch_extension_data(ps->c, &xcb_xinerama_id);
xcb_prefetch_extension_data(ps->c, &xcb_present_id);
xcb_prefetch_extension_data(ps->c, &xcb_sync_id);
xcb_prefetch_extension_data(ps->c, &xcb_glx_id);
@ -2092,18 +2040,10 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
}
// Query X RandR
if (ps->o.xinerama_shadow_crop) {
if (!ps->randr_exists) {
log_fatal("No XRandR extension. xinerama-shadow-crop cannot be "
"enabled.");
goto err;
}
}
// Query X Xinerama extension
if (ps->o.xinerama_shadow_crop) {
ext_info = xcb_get_extension_data(ps->c, &xcb_xinerama_id);
ps->xinerama_exists = ext_info && ext_info->present;
if (ps->o.crop_shadow_to_monitor && !ps->randr_exists) {
log_fatal("No X RandR extension. crop-shadow-to-monitor cannot be "
"enabled.");
goto err;
}
rebuild_screen_reg(ps);
@ -2198,12 +2138,12 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
}
// Monitor screen changes if vsync_sw is enabled and we are using
// an auto-detected refresh rate, or when Xinerama features are enabled
if (ps->randr_exists && ps->o.xinerama_shadow_crop) {
// an auto-detected refresh rate, or when X RandR features are enabled
if (ps->randr_exists && ps->o.crop_shadow_to_monitor) {
xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
}
cxinerama_upd_scrs(ps);
x_update_randr_monitors(ps);
{
xcb_render_create_picture_value_list_t pa = {
@ -2436,7 +2376,7 @@ static void session_destroy(session_t *ps) {
}
free(ps->o.blur_kerns);
free(ps->o.glx_fshader_win_str);
free_xinerama_info(ps);
x_free_randr_info(ps);
// Release custom window shaders
free(ps->o.window_shader_fg);

View File

@ -42,8 +42,6 @@ void circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce);
void root_damaged(session_t *ps);
void cxinerama_upd_scrs(session_t *ps);
void queue_redraw(session_t *ps);
void discard_pending(session_t *ps, uint32_t sequence);

View File

@ -1098,18 +1098,19 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
if (!ps->o.wintype_option[w->window_type].full_shadow)
pixman_region32_subtract(&reg_tmp, &reg_tmp, &bshape_no_corners);
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0 &&
w->xinerama_scr < ps->xinerama_nscrs)
// There can be a window where number of screens
// is updated, but the screen number attached to
// the windows have not.
if (ps->o.crop_shadow_to_monitor && w->randr_monitor >= 0 &&
w->randr_monitor < ps->randr_nmonitors) {
// There can be a window where number of monitors is
// updated, but the monitor number attached to the window
// have not.
//
// Window screen number will be updated
// eventually, so here we just check to make sure
// we don't access out of bounds.
// Window monitor number will be updated eventually, so
// here we just check to make sure we don't access out of
// bounds.
pixman_region32_intersect(
&reg_tmp, &reg_tmp,
&ps->xinerama_scr_regs[w->xinerama_scr]);
&ps->randr_monitor_regs[w->randr_monitor]);
}
// Detect if the region is empty before painting
if (pixman_region32_not_empty(&reg_tmp)) {

View File

@ -14,7 +14,6 @@
#include <xcb/render.h>
#include <xcb/xcb.h>
#include <xcb/xcb_renderutil.h>
#include <xcb/xinerama.h>
#include "atom.h"
#include "backend/backend.h"
@ -517,7 +516,7 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
win_clear_flags(w, WIN_FLAGS_POSITION_STALE);
}
win_update_screen(ps->xinerama_nscrs, ps->xinerama_scr_regs, w);
win_update_monitor(ps->randr_nmonitors, ps->randr_monitor_regs, w);
}
if (win_check_flags_all(w, WIN_FLAGS_PROPERTY_STALE)) {
@ -1550,7 +1549,7 @@ struct win *fill_win(session_t *ps, struct win *w) {
.shadow = false,
.clip_shadow_above = false,
.fg_shader = NULL,
.xinerama_scr = -1,
.randr_monitor = -1,
.mode = WMODE_TRANS,
.ever_damaged = false,
.client_win = XCB_NONE,
@ -2434,33 +2433,24 @@ bool win_skip_fading(session_t *ps, struct managed_win *w) {
return win_check_fade_finished(ps, w);
}
/**
* Get the Xinerama screen a window is on.
*
* Return an index >= 0, or -1 if not found.
*
* TODO(yshui) move to x.c
* TODO(yshui) use xrandr
*/
void win_update_screen(int nscreens, region_t *screens, struct managed_win *w) {
w->xinerama_scr = -1;
for (int i = 0; i < nscreens; i++) {
auto e = pixman_region32_extents(&screens[i]);
if (e->x1 <= w->g.x && e->y1 <= w->g.y && e->x2 >= w->g.x + w->widthb &&
e->y2 >= w->g.y + w->heightb) {
w->xinerama_scr = i;
log_debug("Window %#010x (%s), %dx%d+%dx%d, is on screen "
"%d "
"(%dx%d+%dx%d)",
w->base.id, w->name, w->g.x, w->g.y, w->widthb, w->heightb,
i, e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1);
// TODO(absolutelynothelix): rename to x_update_win_(randr_?)monitor and move to
// the x.c.
void win_update_monitor(int nmons, region_t *mons, struct managed_win *mw) {
mw->randr_monitor = -1;
for (int i = 0; i < nmons; i++) {
auto e = pixman_region32_extents(&mons[i]);
if (e->x1 <= mw->g.x && e->y1 <= mw->g.y &&
e->x2 >= mw->g.x + mw->widthb && e->y2 >= mw->g.y + mw->heightb) {
mw->randr_monitor = i;
log_debug("Window %#010x (%s), %dx%d+%dx%d, is entirely on the "
"monitor %d (%dx%d+%dx%d)",
mw->base.id, mw->name, mw->g.x, mw->g.y, mw->widthb,
mw->heightb, i, e->x1, e->y1, e->x2 - e->x1, e->y2 - e->y1);
return;
}
}
log_debug("Window %#010x (%s), %dx%d+%dx%d, is not contained by any "
"screen",
w->base.id, w->name, w->g.x, w->g.y, w->g.width, w->g.height);
log_debug("Window %#010x (%s), %dx%d+%dx%d, is not entirely on any monitor",
mw->base.id, mw->name, mw->g.x, mw->g.y, mw->widthb, mw->heightb);
}
/// Map an already registered window

View File

@ -123,8 +123,8 @@ struct managed_win {
struct win_geometry g;
/// Updated geometry received in events
struct win_geometry pending_g;
/// Xinerama screen this window is on.
int xinerama_scr;
/// X RandR monitor this window is on.
int randr_monitor;
/// Window visual pict format
const xcb_render_pictforminfo_t *pictfmt;
/// Client window visual pict format
@ -345,7 +345,11 @@ void win_recheck_client(session_t *ps, struct managed_win *w);
*/
double attr_pure win_calc_opacity_target(session_t *ps, const struct managed_win *w);
bool attr_pure win_should_dim(session_t *ps, const struct managed_win *w);
void win_update_screen(int nscreens, region_t *screens, struct managed_win *w);
// TODO(absolutelynothelix): rename to x_update_win_(randr_?)monitor and move to
// the x.h.
void win_update_monitor(int nmons, region_t *mons, struct managed_win *mw);
/**
* Retrieve the bounding shape of a window.
*/

38
src/x.c
View File

@ -9,6 +9,7 @@
#include <xcb/composite.h>
#include <xcb/damage.h>
#include <xcb/glx.h>
#include <xcb/randr.h>
#include <xcb/render.h>
#include <xcb/sync.h>
#include <xcb/xcb.h>
@ -787,3 +788,40 @@ xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) {
return NULL;
}
void x_update_randr_monitors(session_t *ps) {
x_free_randr_info(ps);
if (!ps->o.crop_shadow_to_monitor || !ps->randr_exists) {
return;
}
xcb_randr_get_monitors_reply_t *r = xcb_randr_get_monitors_reply(
ps->c, xcb_randr_get_monitors(ps->c, ps->root, true), NULL);
if (!r) {
return;
}
ps->randr_nmonitors = xcb_randr_get_monitors_monitors_length(r);
ps->randr_monitor_regs = ccalloc(ps->randr_nmonitors, region_t);
xcb_randr_monitor_info_iterator_t monitor_info_it =
xcb_randr_get_monitors_monitors_iterator(r);
for (int i = 0; monitor_info_it.rem; xcb_randr_monitor_info_next(&monitor_info_it)) {
xcb_randr_monitor_info_t *mi = monitor_info_it.data;
pixman_region32_init_rect(&ps->randr_monitor_regs[i++], mi->x, mi->y,
mi->width, mi->height);
}
free(r);
}
void x_free_randr_info(session_t *ps) {
if (ps->randr_monitor_regs) {
for (int i = 0; i < ps->randr_nmonitors; i++) {
pixman_region32_fini(&ps->randr_monitor_regs[i]);
}
free(ps->randr_monitor_regs);
ps->randr_monitor_regs = NULL;
}
ps->randr_nmonitors = 0;
}

10
src/x.h
View File

@ -302,4 +302,14 @@ x_get_pictfmt_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen);
/**
* X RandR-related functions.
*
* The x_update_randr_monitors function populates ps->randr_nmonitors and
* ps->randr_monitor_regs with the data X RandR provided and the
* x_free_randr_info function frees them.
*/
void x_update_randr_monitors(session_t *ps);
void x_free_randr_info(session_t *ps);
uint32_t attr_deprecated xcb_generate_id(xcb_connection_t *c);

View File

@ -64,8 +64,9 @@ shadow-exclude = [
#
# shadow-exclude-reg = ""
# Crop shadow of a window fully on a particular Xinerama screen to the screen.
# xinerama-shadow-crop = false
# Crop shadow of a window fully on a particular monitor to that monitor. This is
# currently implemented using the X RandR extension.
# crop-shadow-to-monitor = false
#################################