Compare commits
19 Commits
nextt
...
e9834a5e35
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9834a5e35 | ||
|
|
fb99c9e472 | ||
|
|
dc9d1fe248 | ||
|
|
05ef18d78f | ||
|
|
379f67f5c2 | ||
|
|
6d459badbc | ||
|
|
838f1f097c | ||
|
|
1c7466c07c | ||
|
|
44cfa0b0ef | ||
|
|
ce7758a07b | ||
|
|
bb2b4801f7 | ||
|
|
36e6b73cde | ||
|
|
90f57e9b1a | ||
|
|
157ecd2077 | ||
|
|
9f14c43989 | ||
|
|
cee1287562 | ||
|
|
317275abf6 | ||
|
|
986b3c1cb3 | ||
|
|
102a0bc5e0 |
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
|
||||
|
||||
2
.github/workflows/coding-style-pr.yml
vendored
2
.github/workflows/coding-style-pr.yml
vendored
@@ -8,6 +8,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch --depth=1 origin ${{ github.event.pull_request.base.sha }}
|
||||
- uses: yshui/git-clang-format-lint@v1.13
|
||||
- uses: yshui/git-clang-format-lint@v1.14
|
||||
with:
|
||||
base: ${{ github.event.pull_request.base.sha }}
|
||||
|
||||
2
.github/workflows/coding-style.yml
vendored
2
.github/workflows/coding-style.yml
vendored
@@ -9,6 +9,6 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: yshui/git-clang-format-lint@v1.13
|
||||
- uses: yshui/git-clang-format-lint@v1.14
|
||||
with:
|
||||
base: ${{ github.event.ref }}~1
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -103,6 +103,9 @@ OPTIONS
|
||||
*--corner-radius* 'VALUE'::
|
||||
Sets the radius of rounded window corners. When > 0, the compositor will round the corners of windows. Does not interact well with *--transparent-clipping*. (defaults to 0).
|
||||
|
||||
*--corner-radius-rules* 'RADIUS':'CONDITION'::
|
||||
Specify a list of corner radius rules. Overrides the corner radii of matching windows. This option takes precedence over the *--rounded-corners-exclude* option, and also overrides the default exclusion of fullscreen windows. The condition has the same format as *--opacity-rule*.
|
||||
|
||||
*--rounded-corners-exclude* 'CONDITION'::
|
||||
Exclude conditions for rounded corners.
|
||||
|
||||
@@ -217,8 +220,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.
|
||||
|
||||
@@ -111,8 +111,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
|
||||
|
||||
|
||||
#################################
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
WM_CLIENT_MACHINE, \
|
||||
_NET_ACTIVE_WINDOW, \
|
||||
_COMPTON_SHADOW, \
|
||||
_NET_WM_WINDOW_TYPE, \
|
||||
_NET_CURRENT_MON_CENTER
|
||||
_NET_WM_DESKTOP, \
|
||||
_NET_CURRENT_DESKTOP
|
||||
|
||||
#define ATOM_LIST2 \
|
||||
_NET_WM_WINDOW_TYPE_DESKTOP, \
|
||||
@@ -44,6 +44,7 @@
|
||||
_NET_WM_STATE, \
|
||||
_NET_WM_STATE_FULLSCREEN, \
|
||||
_NET_WM_BYPASS_COMPOSITOR, \
|
||||
_NET_WM_WINDOW_TYPE, \
|
||||
UTF8_STRING, \
|
||||
C_STRING
|
||||
// clang-format on
|
||||
|
||||
@@ -380,18 +380,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) {
|
||||
|
||||
@@ -197,7 +197,7 @@ struct backend_operations {
|
||||
/// mask is.
|
||||
bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx, void *mask,
|
||||
coord_t mask_dst, const region_t *reg_blur,
|
||||
const region_t *reg_visible) attr_nonnull(1, 3, 4, 6, 7);
|
||||
const region_t *reg_visible) attr_nonnull(1, 3, 6, 7);
|
||||
|
||||
/// Update part of the back buffer with the rendering buffer, then present the
|
||||
/// back buffer onto the target window (if not back buffered, update part of the
|
||||
|
||||
@@ -294,13 +294,14 @@ shadow_picture_err:
|
||||
void *default_backend_render_shadow(backend_t *backend_data, int width, int height,
|
||||
struct backend_shadow_context *sctx, struct color color) {
|
||||
const conv *kernel = (void *)sctx;
|
||||
xcb_pixmap_t shadow_pixel = solid_picture(backend_data->c, backend_data->root, true,
|
||||
1, color.red, color.green, color.blue),
|
||||
shadow = XCB_NONE;
|
||||
xcb_render_picture_t shadow_pixel = solid_picture(
|
||||
backend_data->c, backend_data->root, true, 1, color.red, color.green, color.blue);
|
||||
xcb_pixmap_t shadow = XCB_NONE;
|
||||
xcb_render_picture_t pict = XCB_NONE;
|
||||
|
||||
if (!build_shadow(backend_data->c, backend_data->root, color.alpha, width, height,
|
||||
kernel, shadow_pixel, &shadow, &pict)) {
|
||||
xcb_render_free_picture(backend_data->c, shadow_pixel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -308,6 +309,7 @@ void *default_backend_render_shadow(backend_t *backend_data, int width, int heig
|
||||
void *ret = backend_data->ops->bind_pixmap(
|
||||
backend_data, shadow, x_get_visual_info(backend_data->c, visual), true);
|
||||
xcb_render_free_picture(backend_data->c, pict);
|
||||
xcb_render_free_picture(backend_data->c, shadow_pixel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
15
src/common.h
15
src/common.h
@@ -206,9 +206,6 @@ typedef struct session {
|
||||
/// Width of root window.
|
||||
int root_width;
|
||||
// Damage of root window.
|
||||
// Damage root_damage;
|
||||
int selmon_center_x;
|
||||
int selmon_center_y;
|
||||
/// X Composite overlay window.
|
||||
xcb_window_t overlay;
|
||||
/// The target window for debug mode
|
||||
@@ -294,6 +291,8 @@ typedef struct session {
|
||||
int size_expose;
|
||||
/// Index of the next free slot in <code>expose_rects</code>.
|
||||
int n_expose;
|
||||
/// Current desktop of display
|
||||
uint32_t cur_desktop;
|
||||
|
||||
// === Window related ===
|
||||
/// A hash table of all windows.
|
||||
@@ -374,12 +373,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.
|
||||
|
||||
25
src/config.c
25
src/config.c
@@ -509,32 +509,37 @@ parse_geometry_end:
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a list of opacity rules.
|
||||
* Parse a list of window rules, prefixed with a number, separated by a ':'
|
||||
*/
|
||||
bool parse_rule_opacity(c2_lptr_t **res, const char *src) {
|
||||
// Find opacity value
|
||||
bool parse_numeric_window_rule(c2_lptr_t **res, const char *src, long min, long max) {
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find numeric value
|
||||
char *endptr = NULL;
|
||||
long val = strtol(src, &endptr, 0);
|
||||
if (!endptr || endptr == src) {
|
||||
log_error("No opacity specified: %s", src);
|
||||
log_error("No number specified: %s", src);
|
||||
return false;
|
||||
}
|
||||
if (val > 100 || val < 0) {
|
||||
log_error("Opacity %ld invalid: %s", val, src);
|
||||
|
||||
if (val < min || val > max) {
|
||||
log_error("Number not in range (%ld <= n <= %ld): %s", min, max, src);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip over spaces
|
||||
while (*endptr && isspace((unsigned char)*endptr))
|
||||
while (*endptr && isspace((unsigned char)*endptr)) {
|
||||
++endptr;
|
||||
}
|
||||
if (':' != *endptr) {
|
||||
log_error("Opacity terminator not found: %s", src);
|
||||
log_error("Number separator (':') not found: %s", src);
|
||||
return false;
|
||||
}
|
||||
++endptr;
|
||||
|
||||
// Parse pattern
|
||||
// I hope 1-100 is acceptable for (void *)
|
||||
return c2_parse(res, endptr, (void *)val);
|
||||
}
|
||||
|
||||
@@ -785,7 +790,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,
|
||||
|
||||
@@ -173,8 +173,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;
|
||||
|
||||
@@ -275,6 +275,8 @@ typedef struct options {
|
||||
int corner_radius;
|
||||
/// Rounded corners blacklist. A linked list of conditions.
|
||||
c2_lptr_t *rounded_corners_blacklist;
|
||||
/// Rounded corner rules. A linked list of conditions.
|
||||
c2_lptr_t *corner_radius_rules;
|
||||
|
||||
// === Focus related ===
|
||||
/// Whether to try to detect WM windows and mark them as focused.
|
||||
@@ -320,7 +322,7 @@ bool must_use parse_long(const char *, long *);
|
||||
bool must_use parse_int(const char *, int *);
|
||||
struct conv **must_use parse_blur_kern_lst(const char *, bool *hasneg, int *count);
|
||||
bool must_use parse_geometry(session_t *, const char *, region_t *);
|
||||
bool must_use parse_rule_opacity(c2_lptr_t **, const char *);
|
||||
bool must_use parse_numeric_window_rule(c2_lptr_t **, const char *, long, long);
|
||||
bool must_use parse_rule_window_shader(c2_lptr_t **, const char *, const char *);
|
||||
char *must_use locate_auxiliary_file(const char *scope, const char *path,
|
||||
const char *include_dir);
|
||||
|
||||
@@ -135,6 +135,32 @@ void parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, const char *n
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a window corner radius rule list in configuration file.
|
||||
*/
|
||||
static inline void
|
||||
parse_cfg_condlst_corner(options_t *opt, const config_t *pcfg, const char *name) {
|
||||
config_setting_t *setting = config_lookup(pcfg, name);
|
||||
if (setting) {
|
||||
// Parse an array of options
|
||||
if (config_setting_is_array(setting)) {
|
||||
int i = config_setting_length(setting);
|
||||
while (i--)
|
||||
if (!parse_numeric_window_rule(
|
||||
&opt->corner_radius_rules,
|
||||
config_setting_get_string_elem(setting, i), 0, INT_MAX))
|
||||
exit(1);
|
||||
}
|
||||
// Treat it as a single pattern if it's a string
|
||||
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||
if (!parse_numeric_window_rule(&opt->corner_radius_rules,
|
||||
config_setting_get_string(setting),
|
||||
0, INT_MAX))
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an opacity rule list in configuration file.
|
||||
*/
|
||||
@@ -146,15 +172,15 @@ parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
|
||||
if (config_setting_is_array(setting)) {
|
||||
int i = config_setting_length(setting);
|
||||
while (i--)
|
||||
if (!parse_rule_opacity(
|
||||
if (!parse_numeric_window_rule(
|
||||
&opt->opacity_rules,
|
||||
config_setting_get_string_elem(setting, i)))
|
||||
config_setting_get_string_elem(setting, i), 0, 100))
|
||||
exit(1);
|
||||
}
|
||||
// Treat it as a single pattern if it's a string
|
||||
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||
if (!parse_rule_opacity(&opt->opacity_rules,
|
||||
config_setting_get_string(setting)))
|
||||
if (!parse_numeric_window_rule(
|
||||
&opt->opacity_rules, config_setting_get_string(setting), 0, 100))
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -343,6 +369,9 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||
config_lookup_int(&cfg, "corner-radius", &opt->corner_radius);
|
||||
// --rounded-corners-exclude
|
||||
parse_cfg_condlst(&cfg, &opt->rounded_corners_blacklist, "rounded-corners-exclude");
|
||||
// --corner-radius-rules
|
||||
parse_cfg_condlst_corner(opt, &cfg, "corner-radius-rules");
|
||||
|
||||
// -e (frame_opacity)
|
||||
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
|
||||
// -c (shadow_enable)
|
||||
@@ -393,8 +422,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("**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");
|
||||
|
||||
33
src/event.c
33
src/event.c
@@ -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
|
||||
@@ -452,14 +452,27 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
|
||||
}
|
||||
|
||||
if (ps->root == ev->window) {
|
||||
if (ev->atom == ps->atoms->a_NET_CURRENT_MON_CENTER) {
|
||||
winprop_t prop = x_get_prop(ps->c, ps->root, ps->atoms->a_NET_CURRENT_MON_CENTER, 2L, XCB_ATOM_CARDINAL, 32);
|
||||
if (prop.nitems == 2) {
|
||||
ps->selmon_center_x = prop.p32[0];
|
||||
ps->selmon_center_y = prop.p32[1];
|
||||
}
|
||||
free_winprop(&prop);
|
||||
}
|
||||
|
||||
if (ev->atom == ps->atoms->a_NET_CURRENT_DESKTOP) {
|
||||
auto prop = x_get_prop(ps->c, ps->root, ps->atoms->a_NET_CURRENT_DESKTOP,
|
||||
1L, XCB_ATOM_CARDINAL, 32);
|
||||
|
||||
if (prop.nitems) {
|
||||
if (ps->cur_desktop != *prop.c32) {
|
||||
win_stack_foreach_managed_safe(w, &ps->window_stack) {
|
||||
if (w->a.override_redirect) {
|
||||
continue;
|
||||
}
|
||||
if (w->cur_desktop & *prop.c32) {
|
||||
w->dwm_mask = ANIM_NEXT_TAG;
|
||||
} else if (w->cur_desktop & ps->cur_desktop) {
|
||||
w->dwm_mask = ANIM_PREV_TAG;
|
||||
}
|
||||
}
|
||||
ps->cur_desktop = *prop.c32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ps->o.use_ewmh_active_win && ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
|
||||
// to update focus
|
||||
|
||||
@@ -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."},
|
||||
@@ -159,6 +161,7 @@ static const struct picom_option picom_options[] = {
|
||||
{"corner-radius" , required_argument, 333, NULL , "Sets the radius of rounded window corners. When > 0, the compositor will "
|
||||
"round the corners of windows. (defaults to 0)."},
|
||||
{"rounded-corners-exclude" , required_argument, 334, "COND" , "Exclude conditions for rounded corners."},
|
||||
{"corner-radius-rules" , required_argument, 340, "RADIUS:COND" , "Window rules for specific rounded corner radii."},
|
||||
{"clip-shadow-above" , required_argument, 335, NULL , "Specify a list of conditions of windows to not paint a shadow over, such "
|
||||
"as a dock window."},
|
||||
{"window-shader-fg" , required_argument, 336, "PATH" , "Specify GLSL fragment shader path for rendering window contents. Does not"
|
||||
@@ -172,6 +175,7 @@ static const struct picom_option picom_options[] = {
|
||||
{"dithered-present" , no_argument , 339, NULL , "Use higher precision during rendering, and apply dither when presenting the "
|
||||
"rendered screen. Reduces banding artifacts, but might cause performance "
|
||||
"degradation. Only works with OpenGL."},
|
||||
// 340 is corner-radius-rules
|
||||
{"legacy-backends" , no_argument , 733, NULL , "Use deprecated version of the backends."},
|
||||
{"monitor-repaint" , no_argument , 800, NULL , "Highlight the updated area of the screen. For debugging."},
|
||||
{"diagnostics" , no_argument , 801, NULL , "Print diagnostic information"},
|
||||
@@ -494,8 +498,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) {
|
||||
@@ -508,6 +512,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");
|
||||
@@ -515,7 +525,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);
|
||||
@@ -620,7 +630,7 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||
break;
|
||||
case 304:
|
||||
// --opacity-rule
|
||||
if (!parse_rule_opacity(&opt->opacity_rules, optarg))
|
||||
if (!parse_numeric_window_rule(&opt->opacity_rules, optarg, 0, 100))
|
||||
exit(1);
|
||||
break;
|
||||
case 305:
|
||||
@@ -634,7 +644,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);
|
||||
@@ -725,6 +734,11 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||
// --rounded-corners-exclude
|
||||
condlst_add(&opt->rounded_corners_blacklist, optarg);
|
||||
break;
|
||||
case 340:
|
||||
// --corner-radius-rules
|
||||
if (!parse_numeric_window_rule(&opt->corner_radius_rules, optarg, 0, INT_MAX))
|
||||
exit(1);
|
||||
break;
|
||||
case 335:
|
||||
// --clip-shadow-above
|
||||
condlst_add(&opt->shadow_clip_list, optarg);
|
||||
|
||||
106
src/picom.c
106
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;
|
||||
}
|
||||
@@ -749,13 +698,13 @@ paint_preprocess(session_t *ps, bool *fade_running, bool *animation_running) {
|
||||
w->animation_dest_center_y - w->animation_center_y;
|
||||
double neg_displacement_w = w->animation_dest_w - w->animation_w;
|
||||
double neg_displacement_h = w->animation_dest_h - w->animation_h;
|
||||
double animation_stiffness = ps->o.animation_stiffness;
|
||||
if (!(w->animation_is_tag & ANIM_IN_TAG)) {
|
||||
if (w->animation_is_tag & ANIM_SLOW)
|
||||
animation_stiffness = ps->o.animation_stiffness_tag_change;
|
||||
else if (w->animation_is_tag & ANIM_FAST)
|
||||
animation_stiffness = ps->o.animation_stiffness_tag_change * 1.5;
|
||||
}
|
||||
double animation_stiffness = ps->o.animation_stiffness;
|
||||
if (!(w->animation_is_tag & ANIM_IN_TAG)) {
|
||||
if (w->animation_is_tag & ANIM_SLOW)
|
||||
animation_stiffness = ps->o.animation_stiffness_tag_change;
|
||||
else if (w->animation_is_tag & ANIM_FAST)
|
||||
animation_stiffness = ps->o.animation_stiffness_tag_change * 1.5;
|
||||
}
|
||||
if (w->state == WSTATE_FADING && !(w->animation_is_tag & ANIM_FADE))
|
||||
w->opacity_target = win_calc_opacity_target(ps, w);
|
||||
double acceleration_x =
|
||||
@@ -893,7 +842,6 @@ paint_preprocess(session_t *ps, bool *fade_running, bool *animation_running) {
|
||||
// We can't check for 1 here as sometimes 1 = 0.999999999999999
|
||||
// in case of floating numbers
|
||||
if (w->animation_progress >= 0.999999999) {
|
||||
win_process_update_flags(ps, w);
|
||||
w->animation_progress = 1;
|
||||
w->animation_velocity_x = 0.0;
|
||||
w->animation_velocity_y = 0.0;
|
||||
@@ -1934,6 +1882,8 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
||||
.white_picture = XCB_NONE,
|
||||
.shadow_context = NULL,
|
||||
|
||||
.cur_desktop = 0,
|
||||
|
||||
#ifdef CONFIG_VSYNC_DRM
|
||||
.drm_fd = -1,
|
||||
#endif
|
||||
@@ -2020,7 +1970,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);
|
||||
@@ -2279,18 +2228,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);
|
||||
@@ -2385,12 +2326,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 = {
|
||||
@@ -2502,15 +2443,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
||||
|
||||
write_pid(ps);
|
||||
|
||||
// When picom starts, fetch monitor positions first. Because it won't fetch the data unless property changes.
|
||||
if (!ps->selmon_center_x && !ps->selmon_center_y) {
|
||||
winprop_t prop = x_get_prop(ps->c, ps->root, ps->atoms->a_NET_CURRENT_MON_CENTER, 2L, XCB_ATOM_CARDINAL, 32);
|
||||
if (prop.nitems == 2) {
|
||||
ps->selmon_center_x = prop.p32[0];
|
||||
ps->selmon_center_y = prop.p32[1];
|
||||
}
|
||||
free_winprop(&prop);
|
||||
}
|
||||
ev_init(&ps->animation_timer, animation_timer_callback);
|
||||
|
||||
if (fork && stderr_logger) {
|
||||
@@ -2634,7 +2566,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)) {
|
||||
|
||||
215
src/win.c
215
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"
|
||||
@@ -446,6 +445,10 @@ static void win_update_properties(session_t *ps, struct managed_win *w) {
|
||||
}
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->a_NET_WM_DESKTOP)) {
|
||||
win_update_prop_desktop(ps, w);
|
||||
}
|
||||
|
||||
if (win_fetch_and_unset_property_stale(w, ps->atoms->aWM_CLASS)) {
|
||||
if (win_update_class(ps, w)) {
|
||||
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
|
||||
@@ -472,6 +475,19 @@ static void win_update_properties(session_t *ps, struct managed_win *w) {
|
||||
|
||||
static void init_animation(session_t *ps, struct managed_win *w) {
|
||||
CLEAR_MASK(w->animation_is_tag)
|
||||
static int32_t randr_mon_center_x, randr_mon_center_y;
|
||||
if (w->randr_monitor == -1) {
|
||||
win_update_monitor(ps->randr_nmonitors, ps->randr_monitor_regs, w);
|
||||
if (w->randr_monitor != -1) {
|
||||
auto e = pixman_region32_extents(&ps->randr_monitor_regs[w->randr_monitor]);
|
||||
randr_mon_center_x = (e->x2 + e->x1) / 2, randr_mon_center_y = (e->y2 + e->y1) / 2;
|
||||
} else {
|
||||
randr_mon_center_x = ps->root_width / 2, randr_mon_center_y = ps->root_height / 2;
|
||||
}
|
||||
} else {
|
||||
auto e = pixman_region32_extents(&ps->randr_monitor_regs[w->randr_monitor]);
|
||||
randr_mon_center_x = (e->x2 + e->x1) / 2, randr_mon_center_y = (e->y2 + e->y1) / 2;
|
||||
}
|
||||
static double *anim_x, *anim_y, *anim_w, *anim_h;
|
||||
enum open_window_animation animation;
|
||||
if (ps->o.wintype_option[w->window_type].animation != OPEN_WINDOW_ANIMATION_INVALID
|
||||
@@ -486,6 +502,7 @@ static void init_animation(session_t *ps, struct managed_win *w) {
|
||||
animation = ps->o.animation_for_transient_window;
|
||||
}
|
||||
|
||||
|
||||
anim_x = &w->animation_center_x, anim_y = &w->animation_center_y;
|
||||
anim_w = &w->animation_w, anim_h = &w->animation_h;
|
||||
|
||||
@@ -532,9 +549,9 @@ static void init_animation(session_t *ps, struct managed_win *w) {
|
||||
sqrt(ps->root_width * ps->root_width + ps->root_height * ps->root_height);
|
||||
|
||||
// Set animation
|
||||
*anim_x = ps->selmon_center_x + radius * cos(angle);
|
||||
*anim_y = ps->selmon_center_y + radius * sin(angle);
|
||||
*anim_w = 0;
|
||||
*anim_x = randr_mon_center_x + radius * cos(angle);
|
||||
*anim_y = randr_mon_center_y + radius * sin(angle);
|
||||
*anim_w = 0;
|
||||
*anim_h = 0;
|
||||
break;
|
||||
case OPEN_WINDOW_ANIMATION_SLIDE_UP: // Slide up the image, without changing its location
|
||||
@@ -568,7 +585,7 @@ static void init_animation(session_t *ps, struct managed_win *w) {
|
||||
*anim_h = w->pending_g.height;
|
||||
break;
|
||||
case OPEN_WINDOW_ANIMATION_SLIDE_IN_CENTER:
|
||||
*anim_x = ps->selmon_center_x;
|
||||
*anim_x = randr_mon_center_x;
|
||||
*anim_y = w->g.y + w->pending_g.height * 0.5;
|
||||
*anim_w = w->pending_g.width;
|
||||
*anim_h = w->pending_g.height;
|
||||
@@ -580,7 +597,7 @@ static void init_animation(session_t *ps, struct managed_win *w) {
|
||||
w->animation_dest_h = w->pending_g.height;
|
||||
break;
|
||||
case OPEN_WINDOW_ANIMATION_SLIDE_OUT_CENTER:
|
||||
w->animation_dest_center_x = ps->selmon_center_x;
|
||||
w->animation_dest_center_x = randr_mon_center_x;
|
||||
w->animation_dest_center_y = w->pending_g.y;
|
||||
w->animation_dest_w = w->pending_g.width;
|
||||
w->animation_dest_h = w->pending_g.height;
|
||||
@@ -597,8 +614,8 @@ static void init_animation(session_t *ps, struct managed_win *w) {
|
||||
*anim_h = 0;
|
||||
break;
|
||||
case OPEN_WINDOW_ANIMATION_MINIMIZE:
|
||||
*anim_x = ps->selmon_center_x;
|
||||
*anim_y = ps->selmon_center_y;
|
||||
*anim_x = randr_mon_center_x;
|
||||
*anim_y = randr_mon_center_y;
|
||||
*anim_w = 0;
|
||||
*anim_h = 0;
|
||||
break;
|
||||
@@ -673,10 +690,10 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
|
||||
// Determine if a window should animate
|
||||
if (win_should_animate(ps, w)) {
|
||||
win_update_bounding_shape(ps, w);
|
||||
if (w->pending_g.y < 0 && w->g.y > 0 && abs(w->pending_g.y - w->g.y) >= w->pending_g.height)
|
||||
w->dwm_mask = ANIM_PREV_TAG;
|
||||
else if (w->pending_g.y > 0 && w->g.y < 0 && abs(w->pending_g.y - w->g.y) >= w->pending_g.height)
|
||||
w->dwm_mask = ANIM_NEXT_TAG;
|
||||
// if (w->pending_g.y < 0 && w->g.y > 0 && abs(w->pending_g.y - w->g.y) >= w->pending_g.height)
|
||||
// w->dwm_mask = ANIM_PREV_TAG;
|
||||
// else if (w->pending_g.y > 0 && w->g.y < 0 && abs(w->pending_g.y - w->g.y) >= w->pending_g.height)
|
||||
// w->dwm_mask = ANIM_NEXT_TAG;
|
||||
|
||||
if (!was_visible || w->dwm_mask) {
|
||||
|
||||
@@ -694,7 +711,6 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
|
||||
w->g.width = (uint16_t)round(w->animation_w);
|
||||
w->g.height = (uint16_t)round(w->animation_h);
|
||||
}
|
||||
|
||||
} else {
|
||||
w->animation_is_tag = ANIM_IN_TAG;
|
||||
w->animation_dest_center_x =
|
||||
@@ -705,37 +721,37 @@ void win_process_update_flags(session_t *ps, struct managed_win *w) {
|
||||
w->animation_dest_h = w->pending_g.height;
|
||||
}
|
||||
|
||||
CLEAR_MASK(w->dwm_mask)
|
||||
w->g.border_width = w->pending_g.border_width;
|
||||
double x_dist = w->animation_dest_center_x - w->animation_center_x;
|
||||
double y_dist = w->animation_dest_center_y - w->animation_center_y;
|
||||
double w_dist = w->animation_dest_w - w->animation_w;
|
||||
double h_dist = w->animation_dest_h - w->animation_h;
|
||||
w->animation_inv_og_distance =
|
||||
1.0 / sqrt(x_dist * x_dist + y_dist * y_dist +
|
||||
w_dist * w_dist + h_dist * h_dist);
|
||||
CLEAR_MASK(w->dwm_mask)
|
||||
w->g.border_width = w->pending_g.border_width;
|
||||
double x_dist = w->animation_dest_center_x - w->animation_center_x;
|
||||
double y_dist = w->animation_dest_center_y - w->animation_center_y;
|
||||
double w_dist = w->animation_dest_w - w->animation_w;
|
||||
double h_dist = w->animation_dest_h - w->animation_h;
|
||||
w->animation_inv_og_distance =
|
||||
1.0 / sqrt(x_dist * x_dist + y_dist * y_dist +
|
||||
w_dist * w_dist + h_dist * h_dist);
|
||||
|
||||
if (isinf(w->animation_inv_og_distance))
|
||||
w->animation_inv_og_distance = 0;
|
||||
if (isinf(w->animation_inv_og_distance))
|
||||
w->animation_inv_og_distance = 0;
|
||||
|
||||
// We only grab images if w->reg_ignore_valid is true as
|
||||
// there's an ev_shape_notify() event fired quickly on new windows
|
||||
// for e.g. in case of Firefox main menu and ev_shape_notify()
|
||||
// sets the win_set_flags(w, WIN_FLAGS_SIZE_STALE); which
|
||||
// brakes the new image captured and because this same event
|
||||
// also sets w->reg_ignore_valid = false; too we check for it
|
||||
if (w->reg_ignore_valid) {
|
||||
if (w->old_win_image) {
|
||||
ps->backend_data->ops->release_image(ps->backend_data,
|
||||
w->old_win_image);
|
||||
w->old_win_image = NULL;
|
||||
}
|
||||
// We only grab images if w->reg_ignore_valid is true as
|
||||
// there's an ev_shape_notify() event fired quickly on new windows
|
||||
// for e.g. in case of Firefox main menu and ev_shape_notify()
|
||||
// sets the win_set_flags(w, WIN_FLAGS_SIZE_STALE); which
|
||||
// brakes the new image captured and because this same event
|
||||
// also sets w->reg_ignore_valid = false; too we check for it
|
||||
if (w->reg_ignore_valid) {
|
||||
if (w->old_win_image) {
|
||||
ps->backend_data->ops->release_image(ps->backend_data,
|
||||
w->old_win_image);
|
||||
w->old_win_image = NULL;
|
||||
}
|
||||
|
||||
// We only grab
|
||||
if (w->win_image) {
|
||||
w->old_win_image = ps->backend_data->ops->clone_image(
|
||||
ps->backend_data, w->win_image, &w->bounding_shape);
|
||||
}
|
||||
// We only grab
|
||||
if (w->win_image) {
|
||||
w->old_win_image = ps->backend_data->ops->clone_image(
|
||||
ps->backend_data, w->win_image, &w->bounding_shape);
|
||||
}
|
||||
}
|
||||
|
||||
w->animation_progress = 0.0;
|
||||
@@ -755,7 +771,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)) {
|
||||
@@ -1157,6 +1173,17 @@ void win_update_prop_shadow_raw(session_t *ps, struct managed_win *w) {
|
||||
free_winprop(&prop);
|
||||
}
|
||||
|
||||
void win_update_prop_desktop(session_t *ps, struct managed_win *w) {
|
||||
winprop_t prop = x_get_prop(ps->c, w->base.id, ps->atoms->a_NET_WM_DESKTOP, 1,
|
||||
XCB_ATOM_CARDINAL, 32);
|
||||
if (!prop.nitems) {
|
||||
w->cur_desktop = w->cur_desktop;
|
||||
} else {
|
||||
w->cur_desktop = *prop.c32;
|
||||
}
|
||||
free_winprop(&prop);
|
||||
}
|
||||
|
||||
static void win_set_shadow(session_t *ps, struct managed_win *w, bool shadow_new) {
|
||||
if (w->shadow == shadow_new) {
|
||||
return;
|
||||
@@ -1400,13 +1427,24 @@ static void win_determine_rounded_corners(session_t *ps, struct managed_win *w)
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't round full screen windows & excluded windows
|
||||
if ((w && win_is_fullscreen(ps, w)) ||
|
||||
c2_match(ps, w, ps->o.rounded_corners_blacklist, NULL)) {
|
||||
void *radius_override = NULL;
|
||||
if (c2_match(ps, w, ps->o.corner_radius_rules, &radius_override)) {
|
||||
log_debug("Matched corner rule! %d", w->corner_radius);
|
||||
}
|
||||
|
||||
// Don't round full screen windows & excluded windows,
|
||||
// unless we find a corner override in corner_radius_rules
|
||||
if (!radius_override && ((w && win_is_fullscreen(ps, w)) ||
|
||||
c2_match(ps, w, ps->o.rounded_corners_blacklist, NULL))) {
|
||||
w->corner_radius = 0;
|
||||
log_debug("Not rounding corners for window %#010x", w->base.id);
|
||||
} else {
|
||||
w->corner_radius = ps->o.corner_radius;
|
||||
if (radius_override) {
|
||||
w->corner_radius = (int)(long)radius_override;
|
||||
} else {
|
||||
w->corner_radius = ps->o.corner_radius;
|
||||
}
|
||||
|
||||
log_debug("Rounding corners for window %#010x", w->base.id);
|
||||
// Initialize the border color to an invalid value
|
||||
w->border_col[0] = w->border_col[1] = w->border_col[2] =
|
||||
@@ -1467,7 +1505,7 @@ void win_on_factor_change(session_t *ps, struct managed_win *w) {
|
||||
// focused state of the window
|
||||
win_update_focused(ps, w);
|
||||
|
||||
if (w->animation_progress > 0.9999 || w->animation_progress < 0.0001) {
|
||||
if (w->animation_progress > 0.99999999 || (w->animation_progress == 0.0 && ps->animation_time != 0L)) {
|
||||
win_determine_shadow(ps, w);
|
||||
win_determine_clip_shadow_above(ps, w);
|
||||
}
|
||||
@@ -1818,7 +1856,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,
|
||||
@@ -1970,6 +2008,7 @@ struct win *fill_win(session_t *ps, struct win *w) {
|
||||
ps->atoms->a_NET_WM_NAME, ps->atoms->aWM_CLASS,
|
||||
ps->atoms->aWM_WINDOW_ROLE, ps->atoms->a_COMPTON_SHADOW,
|
||||
ps->atoms->aWM_CLIENT_LEADER, ps->atoms->aWM_TRANSIENT_FOR,
|
||||
ps->atoms->a_NET_WM_DESKTOP
|
||||
};
|
||||
win_set_properties_stale(new, init_stale_props, ARR_SIZE(init_stale_props));
|
||||
|
||||
@@ -2662,29 +2701,31 @@ void unmap_win_start(session_t *ps, struct managed_win *w) {
|
||||
w->opacity_target_old = fmax(w->opacity_target, w->opacity_target_old);
|
||||
w->opacity_target = win_calc_opacity_target(ps, w);
|
||||
|
||||
if (ps->o.animations && ps->o.animation_for_unmap_window != OPEN_WINDOW_ANIMATION_NONE && ps->o.wintype_option[w->window_type].animation) {
|
||||
w->dwm_mask = ANIM_UNMAP;
|
||||
init_animation(ps, w);
|
||||
if (ps->o.animations &&
|
||||
ps->o.animation_for_unmap_window != OPEN_WINDOW_ANIMATION_NONE &&
|
||||
ps->o.wintype_option[w->window_type].animation) {
|
||||
w->dwm_mask = ANIM_UNMAP;
|
||||
init_animation(ps, w);
|
||||
|
||||
double x_dist = w->animation_dest_center_x - w->animation_center_x;
|
||||
double y_dist = w->animation_dest_center_y - w->animation_center_y;
|
||||
double w_dist = w->animation_dest_w - w->animation_w;
|
||||
double h_dist = w->animation_dest_h - w->animation_h;
|
||||
w->animation_inv_og_distance =
|
||||
1.0 / sqrt(x_dist * x_dist + y_dist * y_dist +
|
||||
w_dist * w_dist + h_dist * h_dist);
|
||||
double x_dist = w->animation_dest_center_x - w->animation_center_x;
|
||||
double y_dist = w->animation_dest_center_y - w->animation_center_y;
|
||||
double w_dist = w->animation_dest_w - w->animation_w;
|
||||
double h_dist = w->animation_dest_h - w->animation_h;
|
||||
w->animation_inv_og_distance =
|
||||
1.0 / sqrt(x_dist * x_dist + y_dist * y_dist +
|
||||
w_dist * w_dist + h_dist * h_dist);
|
||||
|
||||
if (isinf(w->animation_inv_og_distance))
|
||||
w->animation_inv_og_distance = 0;
|
||||
if (isinf(w->animation_inv_og_distance))
|
||||
w->animation_inv_og_distance = 0;
|
||||
|
||||
w->animation_progress = 0.0;
|
||||
w->animation_progress = 0.0;
|
||||
|
||||
if (w->old_win_image) {
|
||||
ps->backend_data->ops->release_image(ps->backend_data,
|
||||
w->old_win_image);
|
||||
w->old_win_image = NULL;
|
||||
}
|
||||
}
|
||||
if (w->old_win_image) {
|
||||
ps->backend_data->ops->release_image(ps->backend_data,
|
||||
w->old_win_image);
|
||||
w->old_win_image = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DBUS
|
||||
// Send D-Bus signal
|
||||
@@ -2740,33 +2781,25 @@ 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) {
|
||||
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) {
|
||||
if (e->x1 <= mw->pending_g.x && e->x2 >= mw->pending_g.x + mw->widthb) {
|
||||
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);
|
||||
mw->randr_monitor = -1;
|
||||
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
|
||||
|
||||
27
src/win.h
27
src/win.h
@@ -125,6 +125,7 @@ struct managed_win {
|
||||
struct managed_win *prev_trans;
|
||||
/// Number of windows above this window
|
||||
int stacking_rank;
|
||||
uint32_t cur_desktop;
|
||||
// TODO(yshui) rethink reg_ignore
|
||||
|
||||
// Core members
|
||||
@@ -137,8 +138,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
|
||||
@@ -170,8 +171,8 @@ struct managed_win {
|
||||
/// opacity state, window geometry, window mapped/unmapped state,
|
||||
/// window mode of the windows above. DOES NOT INCLUDE the body of THIS WINDOW.
|
||||
/// NULL means reg_ignore has not been calculated for this window.
|
||||
/// 1 = tag prev , 2 = tag next, 4 = unmap
|
||||
uint32_t dwm_mask;
|
||||
/// 1 = tag prev , 2 = tag next, 4 = unmap
|
||||
uint32_t dwm_mask;
|
||||
rc_region_t *reg_ignore;
|
||||
/// Whether the reg_ignore of all windows beneath this window are valid
|
||||
bool reg_ignore_valid;
|
||||
@@ -202,11 +203,11 @@ struct managed_win {
|
||||
/// Inverse of the window distance at the start of animation, for
|
||||
/// tracking animation progress
|
||||
double animation_inv_og_distance;
|
||||
/// Animation info if it is a tag change & check if its changing window sizes
|
||||
/// 0: no tag change
|
||||
/// 1: normal tag change animation
|
||||
/// 2: tag change animation that effects window size
|
||||
uint16_t animation_is_tag;
|
||||
/// Animation info if it is a tag change & check if its changing window sizes
|
||||
/// 0: no tag change
|
||||
/// 1: normal tag change animation
|
||||
/// 2: tag change animation that effects window size
|
||||
uint16_t animation_is_tag;
|
||||
|
||||
// Client window related members
|
||||
/// ID of the top-level client window of the window.
|
||||
@@ -379,7 +380,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.
|
||||
*/
|
||||
@@ -561,3 +566,5 @@ static inline bool attr_pure attr_unused win_has_frame(const struct managed_win
|
||||
return w->g.border_width || w->frame_extents.top || w->frame_extents.left ||
|
||||
w->frame_extents.right || w->frame_extents.bottom;
|
||||
}
|
||||
|
||||
void win_update_prop_desktop(session_t *ps, struct managed_win *w);
|
||||
|
||||
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->o.animations) || !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
|
||||
|
||||
|
||||
#################################
|
||||
@@ -154,6 +155,11 @@ rounded-corners-exclude = [
|
||||
"window_type = 'desktop'"
|
||||
];
|
||||
|
||||
corner-radius-rules = [
|
||||
"10:window_type = 'dock'",
|
||||
"0x32:window_type = 'desktop'"
|
||||
];
|
||||
|
||||
|
||||
#################################
|
||||
# Background-Blurring #
|
||||
|
||||
Reference in New Issue
Block a user