core: drop xinerama

there are two x extensions for working with monitors (especially
multiple): xinerama and randr. xinerama is old, feature-poor and in
general isn't used anymore compared to the randr: new, feature-rich and
widely-used. for some reason we were using both of them, so let's drop
xinerama to keep things simple, clean and small. and to be modern.

the drop was done in three steps:
* first step was to replace all the xinerama-based code with the
  randr-based one and to replace or remove all the xinerama mentions;
* second step was to replace the xinerama's terminology with the
  randr's one. xinerama was referring only to the word "screen", while
  randr refers to multiple words and i think the word "monitor" is the
  most suitable for us and, hopefully, clear both to a contributor and
  to an end user;
* third step was to refactor the new randr-based code if needed and to
  address related todo's (mostly about moving related functions
  elsewhere).

all the steps were done well except addressing a leftover todo about
moving the win_update_monitor function to the x.c which wasn't done.

the xinerama-shadow-crop option was renamed to crop-shadow-to-monitor,
but it's previous name is still accepted, has effect and the
deprecation message is printed to preserve backwards-compatibility.
This commit is contained in:
Maxim Solovyov 2023-01-13 14:27:45 +03:00
parent 102a0bc5e0
commit 986b3c1cb3
No known key found for this signature in database
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
#################################