Merge remote-tracking branch 'yshui/next' into next
This commit is contained in:
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-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-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
|
||||
if: ${{ matrix.language == 'cpp' }}
|
||||
|
||||
# Autobuild
|
||||
|
||||
@@ -23,6 +23,7 @@ Assuming you already have all the usual building tools installed (e.g. gcc, pyth
|
||||
* xproto
|
||||
* xcb
|
||||
* xcb-damage
|
||||
* xcb-dpms
|
||||
* xcb-xfixes
|
||||
* xcb-shape
|
||||
* xcb-renderutil
|
||||
@@ -44,7 +45,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-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-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
|
||||
```
|
||||
|
||||
On Fedora, the needed packages are
|
||||
|
||||
@@ -265,13 +265,6 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
|
||||
xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_SRC, inner->pict,
|
||||
XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
|
||||
|
||||
if (img->corner_radius != 0 && xrimg->rounded_rectangle != NULL) {
|
||||
// Clip tmp_pict with a rounded rectangle
|
||||
xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_IN_REVERSE,
|
||||
xrimg->rounded_rectangle->p, XCB_NONE,
|
||||
tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
|
||||
}
|
||||
|
||||
if (img->color_inverted) {
|
||||
if (inner->has_alpha) {
|
||||
auto tmp_pict2 = x_create_picture_with_visual(
|
||||
@@ -294,6 +287,7 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
|
||||
0, 0, 0, 0, 0, 0, tmpw, tmph);
|
||||
}
|
||||
}
|
||||
|
||||
if (img->dim != 0) {
|
||||
// Dim the actually content of window
|
||||
xcb_rectangle_t rect = {
|
||||
@@ -307,6 +301,13 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
|
||||
tmp_pict, dim_color, 1, &rect);
|
||||
}
|
||||
|
||||
if (img->corner_radius != 0 && xrimg->rounded_rectangle != NULL) {
|
||||
// Clip tmp_pict with a rounded rectangle
|
||||
xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_IN_REVERSE,
|
||||
xrimg->rounded_rectangle->p, XCB_NONE,
|
||||
tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
|
||||
}
|
||||
|
||||
xcb_render_composite(xd->base.c, XCB_RENDER_PICT_OP_OVER, tmp_pict,
|
||||
mask_pict, result, 0, 0, mask_dst_x, mask_dst_y,
|
||||
to_i16_checked(dst.x), to_i16_checked(dst.y), tmpew,
|
||||
@@ -508,6 +509,7 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool
|
||||
if (!r) {
|
||||
log_error("Invalid pixmap: %#010x", pixmap);
|
||||
x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code);
|
||||
free(e);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -553,7 +555,7 @@ release_rounded_corner_cache(backend_t *base, struct xrender_rounded_rectangle_c
|
||||
assert(cache->refcount > 0);
|
||||
cache->refcount--;
|
||||
if (cache->refcount == 0) {
|
||||
xcb_free_pixmap(base->c, cache->p);
|
||||
xcb_render_free_picture(base->c, cache->p);
|
||||
free(cache);
|
||||
}
|
||||
}
|
||||
@@ -575,9 +577,13 @@ static void deinit(backend_t *backend_data) {
|
||||
xcb_render_free_picture(xd->base.c, xd->alpha_pict[i]);
|
||||
}
|
||||
xcb_render_free_picture(xd->base.c, xd->target);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
xcb_render_free_picture(xd->base.c, xd->back[i]);
|
||||
xcb_free_pixmap(xd->base.c, xd->back_pixmap[i]);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (xd->back[i] != XCB_NONE) {
|
||||
xcb_render_free_picture(xd->base.c, xd->back[i]);
|
||||
}
|
||||
if (xd->back_pixmap[i] != XCB_NONE) {
|
||||
xcb_free_pixmap(xd->base.c, xd->back_pixmap[i]);
|
||||
}
|
||||
}
|
||||
if (xd->present_event) {
|
||||
xcb_unregister_for_special_event(xd->base.c, xd->present_event);
|
||||
|
||||
@@ -150,6 +150,8 @@ typedef struct session {
|
||||
// === Event handlers ===
|
||||
/// ev_io for X connection
|
||||
ev_io xiow;
|
||||
/// Timer for checking DPMS power level
|
||||
ev_timer dpms_check_timer;
|
||||
/// Timeout for delayed unredirection.
|
||||
ev_timer unredir_timer;
|
||||
/// Timer for fading
|
||||
@@ -240,6 +242,8 @@ typedef struct session {
|
||||
xcb_sync_fence_t sync_fence;
|
||||
/// Whether we are rendering the first frame after screen is redirected
|
||||
bool first_frame;
|
||||
/// Whether screen has been turned off
|
||||
bool screen_is_off;
|
||||
|
||||
// === Operation related ===
|
||||
/// Flags related to the root window
|
||||
@@ -348,6 +352,8 @@ typedef struct session {
|
||||
int composite_error;
|
||||
/// Major opcode for X Composite extension.
|
||||
int composite_opcode;
|
||||
/// Whether X DPMS extension exists
|
||||
bool dpms_exists;
|
||||
/// Whether X Shape extension exists.
|
||||
bool shape_exists;
|
||||
/// Event base number for X Shape extension.
|
||||
|
||||
@@ -16,7 +16,8 @@ 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'
|
||||
'xcb-shape', 'xcb-xinerama', 'xcb-xfixes', 'xcb-present', 'xcb-glx',
|
||||
'xcb-dpms', 'xcb'
|
||||
]
|
||||
|
||||
required_packages = [
|
||||
|
||||
51
src/picom.c
51
src/picom.c
@@ -21,6 +21,7 @@
|
||||
#include <unistd.h>
|
||||
#include <xcb/composite.h>
|
||||
#include <xcb/damage.h>
|
||||
#include <xcb/dpms.h>
|
||||
#include <xcb/glx.h>
|
||||
#include <xcb/present.h>
|
||||
#include <xcb/randr.h>
|
||||
@@ -169,6 +170,26 @@ void cxinerama_upd_scrs(session_t *ps) {
|
||||
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);
|
||||
}
|
||||
|
||||
void check_dpms_status(EV_P attr_unused, ev_timer *w, int revents attr_unused) {
|
||||
auto ps = session_ptr(w, dpms_check_timer);
|
||||
auto r = xcb_dpms_info_reply(ps->c, xcb_dpms_info(ps->c), NULL);
|
||||
if (!r) {
|
||||
log_fatal("Failed to query DPMS status.");
|
||||
abort();
|
||||
}
|
||||
auto now_screen_is_off = dpms_screen_is_off(r);
|
||||
if (ps->screen_is_off != now_screen_is_off) {
|
||||
ps->screen_is_off = now_screen_is_off;
|
||||
queue_redraw(ps);
|
||||
}
|
||||
free(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find matched window.
|
||||
*
|
||||
@@ -1092,6 +1113,19 @@ paint_preprocess(session_t *ps, bool *fade_running, bool *animation_running) {
|
||||
// If there's no window to paint, and the screen isn't redirected,
|
||||
// don't redirect it.
|
||||
unredir_possible = true;
|
||||
} else if (ps->screen_is_off) {
|
||||
// Screen is off, unredirect
|
||||
// We do this unconditionally disregarding "unredir_if_possible"
|
||||
// because it's important for correctness, because we need to
|
||||
// workaround problems X server has around screen off.
|
||||
//
|
||||
// Known problems:
|
||||
// 1. Sometimes OpenGL front buffer can lose content, and if we
|
||||
// are doing partial updates (i.e. use-damage = true), the
|
||||
// result will be wrong.
|
||||
// 2. For frame pacing, X server sends bogus
|
||||
// PresentCompleteNotify events when screen is off.
|
||||
unredir_possible = true;
|
||||
}
|
||||
if (unredir_possible) {
|
||||
if (ps->redirected) {
|
||||
@@ -1987,6 +2021,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
||||
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);
|
||||
xcb_prefetch_extension_data(ps->c, &xcb_dpms_id);
|
||||
|
||||
ext_info = xcb_get_extension_data(ps->c, &xcb_render_id);
|
||||
if (!ext_info || !ext_info->present) {
|
||||
@@ -2055,6 +2090,21 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
||||
ps->glx_event = ext_info->first_event;
|
||||
}
|
||||
|
||||
ext_info = xcb_get_extension_data(ps->c, &xcb_dpms_id);
|
||||
ps->dpms_exists = ext_info && ext_info->present;
|
||||
if (ps->dpms_exists) {
|
||||
auto r = xcb_dpms_info_reply(ps->c, xcb_dpms_info(ps->c), NULL);
|
||||
if (!r) {
|
||||
log_fatal("Failed to query DPMS info");
|
||||
goto err;
|
||||
}
|
||||
ps->screen_is_off = dpms_screen_is_off(r);
|
||||
// Check screen status every half second
|
||||
ev_timer_init(&ps->dpms_check_timer, check_dpms_status, 0, 0.5);
|
||||
ev_timer_start(ps->loop, &ps->dpms_check_timer);
|
||||
free(r);
|
||||
}
|
||||
|
||||
// Parse configuration file
|
||||
win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}};
|
||||
bool shadow_enabled = false, fading_enable = false, hasneg = false;
|
||||
@@ -2662,6 +2712,7 @@ static void session_destroy(session_t *ps) {
|
||||
ev_timer_stop(ps->loop, &ps->unredir_timer);
|
||||
ev_timer_stop(ps->loop, &ps->fade_timer);
|
||||
ev_timer_stop(ps->loop, &ps->animation_timer);
|
||||
ev_timer_stop(ps->loop, &ps->dpms_check_timer);
|
||||
ev_idle_stop(ps->loop, &ps->draw_idle);
|
||||
ev_prepare_stop(ps->loop, &ps->event_check);
|
||||
ev_signal_stop(ps->loop, &ps->usr1_signal);
|
||||
|
||||
Reference in New Issue
Block a user