Skip to content

Commit 89c2c85

Browse files
committed
core: don't flush X connection before go to sleep
See the added comments for details. Fixes #1145 Fixes #1166 Fixes #1040? (cherry picked from commit 75d0b7b) Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
1 parent 41f9a58 commit 89c2c85

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

src/event.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@
4848
/// When top half finished, we enter the render stage, where no server state should be
4949
/// queried. All rendering should be done with our internal knowledge of the server state.
5050
///
51+
/// P.S. There is another reason to avoid sending any request to the server as much as
52+
/// possible. To make sure requests are sent, flushes are needed. And `xcb_flush`/`XFlush`
53+
/// functions may read more events from the server into their queues. This is
54+
/// undesirable, see the comments on `handle_queued_x_events` in picom.c for more details.
5155

52-
// TODO(yshui) the things described above
56+
// TODO(yshui) the things described above. This is mostly done, maybe some of
57+
// the functions here is still making unnecessary queries, we need
58+
// to do some auditing to be sure.
5359

5460
/**
5561
* Get a window's name from window ID.
@@ -590,7 +596,7 @@ static inline void repair_win(session_t *ps, struct managed_win *w) {
590596
// to make sure the X server receives the DamageSubtract request, hence the
591597
// `xcb_request_check` here.
592598
// Otherwise, we fetch the damage regions. That means we will receive a reply
593-
// from the X server, which implies it has received our request.
599+
// from the X server, which implies it has received our DamageSubtract request.
594600
if (!w->ever_damaged) {
595601
auto e = xcb_request_check(
596602
ps->c.c, xcb_damage_subtract(ps->c.c, w->damage, XCB_NONE, XCB_NONE));

src/picom.c

+24-8
Original file line numberDiff line numberDiff line change
@@ -1609,9 +1609,32 @@ static void unredirect(session_t *ps) {
16091609
log_debug("Screen unredirected.");
16101610
}
16111611

1612-
// Handle queued events before we go to sleep
1612+
/// Handle queued events before we go to sleep.
1613+
///
1614+
/// This function is called by ev_prepare watcher, which is called just before
1615+
/// the event loop goes to sleep. X damage events are incremental, which means
1616+
/// if we don't handle the ones X server already sent us, we won't get new ones.
1617+
/// And if we don't get new ones, we won't render, i.e. we would freeze. libxcb
1618+
/// keeps an internal queue of events, so we have to be 100% sure no events are
1619+
/// left in that queue before we go to sleep.
16131620
static void handle_queued_x_events(EV_P attr_unused, ev_prepare *w, int revents attr_unused) {
16141621
session_t *ps = session_ptr(w, event_check);
1622+
// Flush because if we go into sleep when there is still requests in the
1623+
// outgoing buffer, they will not be sent for an indefinite amount of
1624+
// time. Use XFlush here too, we might still use some Xlib functions
1625+
// because OpenGL.
1626+
//
1627+
// Also note, after we have flushed here, we won't flush again in this
1628+
// function before going into sleep. This is because `xcb_flush`/`XFlush`
1629+
// may _read_ more events from the server (yes, this is ridiculous, I
1630+
// know). And we can't have that, see the comments above this function.
1631+
//
1632+
// This means if functions called ev_handle need to send some events,
1633+
// they need to carefully make sure those events are flushed, one way or
1634+
// another.
1635+
XFlush(ps->c.dpy);
1636+
xcb_flush(ps->c.c);
1637+
16151638
if (ps->vblank_scheduler) {
16161639
vblank_handle_x_events(ps->vblank_scheduler);
16171640
}
@@ -1621,13 +1644,6 @@ static void handle_queued_x_events(EV_P attr_unused, ev_prepare *w, int revents
16211644
ev_handle(ps, ev);
16221645
free(ev);
16231646
};
1624-
// Flush because if we go into sleep when there is still
1625-
// requests in the outgoing buffer, they will not be sent
1626-
// for an indefinite amount of time.
1627-
// Use XFlush here too, we might still use some Xlib functions
1628-
// because OpenGL.
1629-
XFlush(ps->c.dpy);
1630-
xcb_flush(ps->c.c);
16311647
int err = xcb_connection_has_error(ps->c.c);
16321648
if (err) {
16331649
log_fatal("X11 server connection broke (error %d)", err);

0 commit comments

Comments
 (0)