mirror of
https://github.com/yshui/picom.git
synced 2024-11-25 14:06:08 -05:00
Merge pull request #995 from absolutelynothelix/begone-xinerama
This commit is contained in:
commit
317275abf6
22 changed files with 143 additions and 153 deletions
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
#################################
|
||||
|
|
|
@ -327,18 +327,18 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
®_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(
|
||||
®_shadow, ®_shadow,
|
||||
&ps->xinerama_scr_regs[w->xinerama_scr]);
|
||||
&ps->randr_monitor_regs[w->randr_monitor]);
|
||||
}
|
||||
|
||||
if (ps->o.transparent_clipping) {
|
||||
|
|
10
src/common.h
10
src/common.h
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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("\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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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");
|
||||
|
@ -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);
|
||||
|
|
76
src/picom.c
76
src/picom.c
|
@ -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,19 +2040,11 @@ 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 "
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
19
src/render.c
19
src/render.c
|
@ -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(®_tmp, ®_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(
|
||||
®_tmp, ®_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(®_tmp)) {
|
||||
|
|
44
src/win.c
44
src/win.c
|
@ -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
|
||||
|
|
10
src/win.h
10
src/win.h
|
@ -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
38
src/x.c
|
@ -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
10
src/x.h
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
#################################
|
||||
|
|
Loading…
Reference in a new issue