Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package picom for openSUSE:Factory checked 
in at 2024-11-17 16:41:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/picom (Old)
 and      /work/SRC/openSUSE:Factory/.picom.new.2017 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "picom"

Sun Nov 17 16:41:37 2024 rev:13 rq:1224526 version:12.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/picom/picom.changes      2024-10-17 
18:40:00.939968584 +0200
+++ /work/SRC/openSUSE:Factory/.picom.new.2017/picom.changes    2024-11-17 
16:41:43.164530239 +0100
@@ -1,0 +2,17 @@
+Fri Nov 15 11:03:35 UTC 2024 - Michael Pujos <[email protected]>
+
+- Update to version 12.5:
+  * Bug fixes
+    - Fix assertion failure when running with some window managers (e.g. 
qtile) and no window is focused (#1384)
+- Update to version 12.4:
+  * Improvements
+    - Better workaround for a NVIDIA quirk, fix high CPU usage when
+      screen is off (#1265)
+    - Avoid using xrender convolution in all cases, should improve
+      shadow performance for most users (#1349)
+  * Bug fixes
+    - Fix leak of saved window images
+  * Build fixes
+    - Fix build on arm32 (#1355)
+
+-------------------------------------------------------------------

Old:
----
  picom-12.3.tar.gz

New:
----
  picom-12.5.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ picom.spec ++++++
--- /var/tmp/diff_new_pack.OPHpbG/_old  2024-11-17 16:41:43.684551839 +0100
+++ /var/tmp/diff_new_pack.OPHpbG/_new  2024-11-17 16:41:43.688552005 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           picom
-Version:        12.3
+Version:        12.5
 Release:        0
 Summary:        Stand-alone compositor for X11
 License:        MIT AND MPL-2.0

++++++ picom-12.3.tar.gz -> picom-12.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/CHANGELOG.md new/picom-12.5/CHANGELOG.md
--- old/picom-12.3/CHANGELOG.md 2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/CHANGELOG.md 2024-11-13 07:48:38.000000000 +0100
@@ -1,3 +1,24 @@
+# 12.5 (2024-Nov-13)
+
+## Bug fixes
+
+* Fix assertion failure when running with some window managers (e.g. qtile) 
and no window is focused (#1384)
+
+# 12.4 (2024-Nov-09)
+
+## Improvements
+
+* Better workaround for a NVIDIA qurik, fix high CPU usage when screen is off 
(#1265)
+* Avoid using xrender convolution in all cases, should improve shadow 
performance for most users. (#1349)
+
+# Bug fixes
+
+* Fix leak of saved window images.
+
+## Build fixes
+
+* Fix build on arm32 (#1355)
+
 # 12.3 (2024-Oct-14)
 
 ## Improvements
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/meson.build new/picom-12.5/meson.build
--- old/picom-12.3/meson.build  2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/meson.build  2024-11-13 07:48:38.000000000 +0100
@@ -1,4 +1,4 @@
-project('picom', 'c', version: '12.3',
+project('picom', 'c', version: '12.5',
         default_options: ['c_std=c11', 'warning_level=1'])
 
 cc = meson.get_compiler('c')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/backend/backend_common.c 
new/picom-12.5/src/backend/backend_common.c
--- old/picom-12.3/src/backend/backend_common.c 2024-10-14 17:25:35.000000000 
+0200
+++ new/picom-12.5/src/backend/backend_common.c 2024-11-13 07:48:38.000000000 
+0100
@@ -197,7 +197,7 @@
  */
 bool build_shadow(struct x_connection *c, double opacity, const int width,
                   const int height, const conv *kernel, xcb_render_picture_t 
shadow_pixel,
-                  xcb_pixmap_t *pixmap, xcb_render_picture_t *pict) {
+                  xcb_pixmap_t *pixmap) {
        xcb_image_t *shadow_image = NULL;
        xcb_pixmap_t shadow_pixmap = XCB_NONE, shadow_pixmap_argb = XCB_NONE;
        xcb_render_picture_t shadow_picture = XCB_NONE, shadow_picture_argb = 
XCB_NONE;
@@ -262,12 +262,12 @@
                             shadow_image->height);
 
        *pixmap = shadow_pixmap_argb;
-       *pict = shadow_picture_argb;
 
        xcb_free_gc(c->c, gc);
        xcb_image_destroy(shadow_image);
        xcb_free_pixmap(c->c, shadow_pixmap);
        x_free_picture(c, shadow_picture);
+       x_free_picture(c, shadow_picture_argb);
 
        return true;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/backend/backend_common.h 
new/picom-12.5/src/backend/backend_common.h
--- old/picom-12.3/src/backend/backend_common.h 2024-10-14 17:25:35.000000000 
+0200
+++ new/picom-12.5/src/backend/backend_common.h 2024-11-13 07:48:38.000000000 
+0100
@@ -28,8 +28,7 @@
 xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double 
opacity,
                          int width, int height);
 bool build_shadow(struct x_connection *, double opacity, int width, int height,
-                  const conv *kernel, xcb_render_picture_t shadow_pixel,
-                  xcb_pixmap_t *pixmap, xcb_render_picture_t *pict);
+                  const conv *kernel, xcb_render_picture_t shadow_pixel, 
xcb_pixmap_t *pixmap);
 
 xcb_render_picture_t
 solid_picture(struct x_connection *, bool argb, double a, double r, double g, 
double b);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/backend/xrender/xrender.c 
new/picom-12.5/src/backend/xrender/xrender.c
--- old/picom-12.3/src/backend/xrender/xrender.c        2024-10-14 
17:25:35.000000000 +0200
+++ new/picom-12.5/src/backend/xrender/xrender.c        2024-11-13 
07:48:38.000000000 +0100
@@ -956,12 +956,7 @@
        xd->curr_back = 0;
        xd->back_image.pict = xd->vsync ? xd->back[xd->curr_back] : xd->target;
 
-       auto drivers = detect_driver(xd->base.c->c, &xd->base, xd->target_win);
-       if (drivers & (DRIVER_MODESETTING | DRIVER_NVIDIA | DRIVER_NOUVEAU |
-                      DRIVER_AMDGPU | DRIVER_RADEON | DRIVER_FGLRX)) {
-               // I believe xf86-video-intel have accelerated convolution?
-               xd->quirks |= BACKEND_QUIRK_SLOW_BLUR;
-       }
+       xd->quirks |= BACKEND_QUIRK_SLOW_BLUR;
 
        return &xd->base;
 err:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/config.h new/picom-12.5/src/config.h
--- old/picom-12.3/src/config.h 2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/config.h 2024-11-13 07:48:38.000000000 +0100
@@ -199,9 +199,6 @@
        struct win_script animations[ANIMATION_TRIGGER_COUNT];
 };
 
-// Make sure `window_options` has no implicit padding.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic error "-Wpadded"
 /// Like `window_maybe_options`, but all fields are guaranteed to be set.
 struct window_options {
        double opacity;
@@ -220,13 +217,18 @@
 
        struct win_script animations[ANIMATION_TRIGGER_COUNT];
 };
-#pragma GCC diagnostic pop
 
 static inline bool
 win_options_no_damage(const struct window_options *a, const struct 
window_options *b) {
        // Animation changing does not immediately change how window is 
rendered, so
-       // they don't cause damage.
-       return memcmp(a, b, offsetof(struct window_options, animations)) == 0;
+       // they don't cause damage; all other options do.
+       return a->opacity == b->opacity && a->dim == b->dim &&
+              a->corner_radius == b->corner_radius && a->unredir == b->unredir 
&&
+              a->transparent_clipping == b->transparent_clipping &&
+              a->shadow == b->shadow && a->invert_color == b->invert_color &&
+              a->blur_background == b->blur_background && a->fade == b->fade &&
+              a->clip_shadow_above == b->clip_shadow_above && a->paint == 
b->paint &&
+              a->full_shadow == b->full_shadow && a->shader == b->shader;
 }
 
 /// Structure representing all options.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/log.h new/picom-12.5/src/log.h
--- old/picom-12.3/src/log.h    2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/log.h    2024-11-13 07:48:38.000000000 +0100
@@ -33,12 +33,13 @@
                }                                                               
               \
        } while (0)
 
-#define LOG(level, x, ...)                                                     
                \
-       do {                                                                    
               \
-               if (LOG_LEVEL_##level >= log_get_level_tls()) {                 
               \
-                       log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, 
##__VA_ARGS__); \
-               }                                                               
               \
+#define LOG_(level, x, ...)                                                    
          \
+       do {                                                                    
         \
+               if (level >= log_get_level_tls()) {                             
         \
+                       log_printf(tls_logger, level, __func__, x, 
##__VA_ARGS__);       \
+               }                                                               
         \
        } while (0)
+#define LOG(level, x, ...) LOG_(LOG_LEVEL_##level, x, ##__VA_ARGS__)
 #define log_trace(x, ...) LOG_UNLIKELY(TRACE, x, ##__VA_ARGS__)
 #define log_verbose(x, ...) LOG_UNLIKELY(VERBOSE, x, ##__VA_ARGS__)
 #define log_debug(x, ...) LOG_UNLIKELY(DEBUG, x, ##__VA_ARGS__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/picom.c new/picom-12.5/src/picom.c
--- old/picom-12.3/src/picom.c  2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/picom.c  2024-11-13 07:48:38.000000000 +0100
@@ -1450,18 +1450,10 @@
 static void handle_x_events(struct session *ps) {
        uint32_t latest_completed = ps->c.latest_completed_request;
        while (true) {
-               // Flush because if we go into sleep when there is still 
requests
-               // in the outgoing buffer, they will not be sent for an 
indefinite
-               // amount of time. Use XFlush here too, we might still use some
-               // Xlib functions because OpenGL.
-               //
-               // Also note, `xcb_flush`/`XFlush` may _read_ more events from 
the server
-               // (yes, this is ridiculous, I know). But since we are polling 
for events
-               // in a loop, this should be fine - if we read events here, 
they will be
-               // handled below; and if some requests is sent later in this 
loop, we will
-               // set `needs_flush` and loop once more and get here to flush 
them.
-               XFlush(ps->c.dpy);
-               xcb_flush(ps->c.c);
+               if (!x_prepare_for_sleep(&ps->c)) {
+                       log_fatal("X connection broke.");
+                       exit(1);
+               }
 
                // If we send any new requests, we should loop again to flush 
them. There
                // is no direct way to do this from xcb. So if we called 
`ev_handle`, or
@@ -1694,9 +1686,7 @@
                        w->running_animation_instance = NULL;
                        w->in_openclose = false;
                        if (w->saved_win_image != NULL) {
-                               
ps->backend_data->ops.release_image(ps->backend_data,
-                                                                   
w->saved_win_image);
-                               w->saved_win_image = NULL;
+                               win_release_saved_win_image(ps->backend_data, 
w);
                        }
                        if (w->state == WSTATE_UNMAPPED) {
                                unmap_win_finish(ps, w);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/renderer/renderer.c 
new/picom-12.5/src/renderer/renderer.c
--- old/picom-12.3/src/renderer/renderer.c      2024-10-14 17:25:35.000000000 
+0200
+++ new/picom-12.5/src/renderer/renderer.c      2024-11-13 07:48:38.000000000 
+0100
@@ -351,10 +351,8 @@
 renderer_bind_shadow(struct renderer *r, struct backend_base *backend, struct 
win *w) {
        if (backend->ops.quirks(backend) & BACKEND_QUIRK_SLOW_BLUR) {
                xcb_pixmap_t shadow = XCB_NONE;
-               xcb_render_picture_t pict = XCB_NONE;
-
                if (!build_shadow(backend->c, r->shadow_color.alpha, w->widthb, 
w->heightb,
-                                 (void *)r->shadow_kernel, r->shadow_pixel, 
&shadow, &pict)) {
+                                 (void *)r->shadow_kernel, r->shadow_pixel, 
&shadow)) {
                        return false;
                }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/vblank.c new/picom-12.5/src/vblank.c
--- old/picom-12.3/src/vblank.c 2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/vblank.c 2024-11-13 07:48:38.000000000 +0100
@@ -87,6 +87,21 @@
        pthread_t sync_thread;
        bool running, error, vblank_requested;
        unsigned int last_msc;
+       /// Number of synthesized vblank event. Currently these are being 
inserted when
+       /// the driver reports duplicate msc to us.
+       ///
+       /// This is because the NVIDIA driver has been observed to recover from 
a
+       /// duplicated msc loop by us rendering a new frame. So we insert a 
fake vblank
+       /// event so the render loop can progress, but doing so makes our msc 
desync from
+       /// the driver's msc. An hypothetical sequence of events go like this:
+       ///
+       ///   - driver -> msc 1, we report msc 1
+       ///   - driver -> msc 1 (duplicate msc! if we don't render a new frame, 
we'll
+       ///     be stuck here forever)
+       ///   - we report msc 2
+       ///   - new frame rendered, driver recover
+       ///   - driver -> msc 2, but we already reported msc 2, so we have to 
report msc 3
+       unsigned int vblank_inserted;
 
        /// Protects `running`, and `vblank_requested`
        pthread_mutex_t vblank_requested_mtx;
@@ -199,6 +214,8 @@
        pthread_cond_signal(&args->start_cnd);
        pthread_mutex_unlock(&args->start_mtx);
 
+       unsigned int last_msc = 0;
+
        pthread_mutex_lock(&self->vblank_requested_mtx);
        while (self->running) {
                if (!self->vblank_requested) {
@@ -208,10 +225,9 @@
                }
                pthread_mutex_unlock(&self->vblank_requested_mtx);
 
-               unsigned int last_msc;
                glXWaitVideoSyncSGI(1, 0, &last_msc);
 
-               struct timespec now;
+               struct timespec now = {};
                clock_gettime(CLOCK_MONOTONIC, &now);
                atomic_store(&self->current_msc, last_msc);
                atomic_store(&self->current_ust,
@@ -323,28 +339,33 @@
 static void
 sgi_video_sync_scheduler_callback(EV_P attr_unused, ev_async *w, int 
attr_unused revents) {
        auto sched = container_of(w, struct sgi_video_sync_vblank_scheduler, 
notify);
-       auto msc = atomic_load(&sched->current_msc);
-       if (sched->last_msc == msc) {
+       auto msc = atomic_load(&sched->current_msc) + sched->vblank_inserted;
+       auto ust = atomic_load(&sched->current_ust);
+       if (sched->last_msc >= msc) {
                // NVIDIA spams us with duplicate vblank events after a 
suspend/resume
-               // cycle. Recreating the X connection and GLX context seems to 
fix this.
-               // Oh NVIDIA.
-               log_warn("Duplicate vblank event found with msc %d. Possible 
NVIDIA bug?", msc);
-               log_warn("Resetting the vblank scheduler");
-               sgi_video_sync_scheduler_deinit(&sched->base);
-               sched->base.vblank_event_requested = false;
-               if (!sgi_video_sync_scheduler_init(&sched->base)) {
-                       log_error("Failed to reset the vblank scheduler");
-               } else {
-                       sgi_video_sync_scheduler_schedule(&sched->base);
-               }
-               return;
+               // cycle, or when the monitor turns off.
+               // Fake a vblank event in this case. See comments on 
`vblank_inserted`
+               // for more details.
+               enum log_level level =
+                   sched->vblank_inserted == 0 ? LOG_LEVEL_WARN : 
LOG_LEVEL_DEBUG;
+               LOG_(level,
+                    "Duplicate vblank event found with msc %d. Possible NVIDIA 
bug? "
+                    "Number of duplicates so far: %d",
+                    msc, sched->vblank_inserted);
+               sched->last_msc++;
+               sched->vblank_inserted++;
+
+               struct timespec now;
+               clock_gettime(CLOCK_MONOTONIC, &now);
+               ust = (uint64_t)(now.tv_sec * 1000000 + now.tv_nsec / 1000);
+       } else {
+               sched->last_msc = msc;
        }
        auto event = (struct vblank_event){
-           .msc = msc,
-           .ust = atomic_load(&sched->current_ust),
+           .msc = sched->last_msc,
+           .ust = ust,
        };
        sched->base.vblank_event_requested = false;
-       sched->last_msc = msc;
        log_verbose("Received vblank event for msc %" PRIu64, event.msc);
        vblank_scheduler_invoke_callbacks(&sched->base, &event);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/wm/win.c new/picom-12.5/src/wm/win.c
--- old/picom-12.3/src/wm/win.c 2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/wm/win.c 2024-11-13 07:48:38.000000000 +0100
@@ -235,10 +235,14 @@
        }
 }
 
-static inline void win_release_saved_win_image(backend_t *base, struct win *w) 
{
+void win_release_saved_win_image(backend_t *base, struct win *w) {
        if (w->saved_win_image) {
-               base->ops.release_image(base, w->saved_win_image);
+               xcb_pixmap_t pixmap = XCB_NONE;
+               pixmap = base->ops.release_image(base, w->saved_win_image);
                w->saved_win_image = NULL;
+               if (pixmap != XCB_NONE) {
+                       xcb_free_pixmap(base->c->c, pixmap);
+               }
        }
 }
 
@@ -1937,9 +1941,7 @@
        if (win_check_flags_any(w, WIN_FLAGS_PIXMAP_STALE)) {
                // Grab the old pixmap, animations might need it
                if (w->saved_win_image) {
-                       ps->backend_data->ops.release_image(ps->backend_data,
-                                                           w->saved_win_image);
-                       w->saved_win_image = NULL;
+                       win_release_saved_win_image(ps->backend_data, w);
                }
                if (ps->drivers & DRIVER_NVIDIA) {
                        if (w->win_image != NULL) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/wm/win.h new/picom-12.5/src/wm/win.h
--- old/picom-12.3/src/wm/win.h 2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/wm/win.h 2024-11-13 07:48:38.000000000 +0100
@@ -419,6 +419,7 @@
 /// because of fading and such.
 void win_destroy_start(session_t *ps, struct win *w);
 void win_map_start(struct session *ps, struct win *w);
+void win_release_saved_win_image(backend_t *base, struct win *w);
 /// Release images bound with a window, set the *_NONE flags on the window. 
Only to be
 /// used when de-initializing the backend outside of win.c
 void win_release_images(struct backend_base *backend, struct win *w);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/wm/wm.c new/picom-12.5/src/wm/wm.c
--- old/picom-12.3/src/wm/wm.c  2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/wm/wm.c  2024-11-13 07:48:38.000000000 +0100
@@ -187,7 +187,9 @@
 
 struct wm_ref *wm_find_by_client(const struct wm *wm, xcb_window_t client) {
        auto node = wm_tree_find(&wm->tree, client);
-       if (node == NULL) {
+       if (node == NULL || node->parent == NULL) {
+               // If `client` is the root window, we return NULL too, 
technically
+               // the root window doesn't have a client window.
                return NULL;
        }
        auto toplevel = wm_tree_find_toplevel_for(&wm->tree, node);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/x.c new/picom-12.5/src/x.c
--- old/picom-12.3/src/x.c      2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/x.c      2024-11-13 07:48:38.000000000 +0100
@@ -166,12 +166,6 @@
 /// This function logs X errors, or aborts the program based on severity of 
the error.
 static void x_handle_error(struct x_connection *c, xcb_generic_error_t *ev) {
        x_discard_pending_errors(c, ev->full_sequence);
-       if (c->event_sync_sent && ev->full_sequence == c->event_sync) {
-               // This is the error for our event sync request we have been
-               // expecting.
-               c->event_sync_sent = false;
-               return;
-       }
        struct pending_x_error *first_error_action = NULL;
        if (!list_is_empty(&c->pending_x_errors)) {
                first_error_action =
@@ -206,6 +200,48 @@
                                        ev->error_code));
 }
 
+struct x_generic_async_request {
+       struct x_async_request_base base;
+       enum x_error_action error_action;
+       const char *func;
+       const char *file;
+       int line;
+};
+
+static void x_generic_async_callback(struct x_connection * /*c*/,
+                                     struct x_async_request_base *req_base,
+                                     const xcb_raw_generic_event_t 
*reply_or_error) {
+       auto req = (struct x_generic_async_request *)req_base;
+       auto error_action = req->error_action;
+       auto func = req->func == NULL ? "(unknown)" : req->func;
+       auto file = req->file == NULL ? "(unknown)" : req->file;
+       auto line = req->line;
+       free(req);
+
+       if (reply_or_error == NULL || reply_or_error->response_type != 0) {
+               return;
+       }
+
+       auto error = (xcb_generic_error_t *)reply_or_error;
+       if (error_action != PENDING_REPLY_ACTION_IGNORE) {
+               log_error("X error for request in %s at %s:%d: %s", func, file, 
line,
+                         x_error_code_to_string(error->full_sequence, 
error->major_code,
+                                                error->minor_code, 
error->error_code));
+       } else {
+               log_debug("Expected X error for request in %s at %s:%d: %s", 
func, file, line,
+                         x_error_code_to_string(error->full_sequence, 
error->major_code,
+                                                error->minor_code, 
error->error_code));
+       }
+       switch (error_action) {
+       case PENDING_REPLY_ACTION_ABORT:
+               log_fatal("An unrecoverable X error occurred, "
+                         "aborting...");
+               abort();
+       case PENDING_REPLY_ACTION_DEBUG_ABORT: assert(false); break;
+       case PENDING_REPLY_ACTION_IGNORE: break;
+       }
+}
+
 /**
  * Xlib error handler function.
  */
@@ -238,7 +274,6 @@
 
        c->screen = DefaultScreen(dpy);
        c->screen_info = xcb_aux_get_screen(c->c, c->screen);
-       c->event_sync_sent = false;
 
        // Do a round trip to fetch the current sequence number
        auto cookie = xcb_get_input_focus(c->c);
@@ -1063,15 +1098,36 @@
        return x_ingest_event(c, e);
 }
 
+bool x_prepare_for_sleep(struct x_connection *c) {
+       if (!list_is_empty(&c->pending_x_requests)) {
+               auto last = list_entry(c->pending_x_requests.prev,
+                                      struct x_async_request_base, siblings);
+               if (c->event_sync != last->sequence) {
+                       // Send an async request that is guaranteed to error, 
see comments
+                       // on `event_sync` for why.
+                       auto req = ccalloc(1, struct x_generic_async_request);
+                       req->func = __func__;
+                       req->file = __FILE__;
+                       req->line = __LINE__;
+                       req->error_action = PENDING_REPLY_ACTION_IGNORE;
+                       req->base.sequence = xcb_free_pixmap(c->c, 
XCB_NONE).sequence;
+                       req->base.callback = x_generic_async_callback;
+                       req->base.no_reply = true;
+                       c->event_sync = req->base.sequence;
+                       x_await_request(c, &req->base);
+                       log_trace("Sending event sync request to catch response 
to "
+                                 "pending request, last sequence: %u, event 
sync: %u",
+                                 last->sequence, c->event_sync);
+               }
+       }
+       XFlush(c->dpy);
+       xcb_flush(c->c);
+       return true;
+}
+
 xcb_generic_event_t *x_poll_for_event(struct x_connection *c, bool queued) {
        xcb_raw_generic_event_t *ret = NULL;
        while (true) {
-               if (!list_is_empty(&c->pending_x_requests) && 
!c->event_sync_sent) {
-                       // Send a request that is guaranteed to error, see 
comments on
-                       // `event_sync` for why.
-                       c->event_sync = xcb_free_pixmap(c->c, 
XCB_NONE).sequence;
-                       c->event_sync_sent = true;
-               }
                ret = x_poll_for_event_impl(c, queued);
 
                if (ret == NULL || ret->response_type != 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-12.3/src/x.h new/picom-12.5/src/x.h
--- old/picom-12.3/src/x.h      2024-10-14 17:25:35.000000000 +0200
+++ new/picom-12.5/src/x.h      2024-11-13 07:48:38.000000000 +0100
@@ -112,7 +112,6 @@
        /// events. The only problem, if no events are coming, we will be stuck
        /// indefinitely, so we have to make our own events.
        uint32_t event_sync;
-       bool event_sync_sent;
 };
 
 /// Monitor info
@@ -474,6 +473,16 @@
        list_insert_before(&c->pending_x_requests, &req->siblings);
 }
 
+/// Flush all X buffers to ensure we don't sleep with outgoing messages not 
sent.
+///
+/// If there are requests pending replies, an event sync request will
+/// be sent if necessary. See comments on `event_sync` for more information. 
MUST be
+/// called before sleep to ensure we can handle replies/events in a timely 
manner. This
+/// function MIGHT read data from X into xcb buffer (because `xcb_flush` might 
read,
+/// ridiculous, I know), so `x_poll_for_event(queued = true)` MUST be called 
after this to
+/// drain the buffer.
+bool x_prepare_for_sleep(struct x_connection *c);
+
 /// Poll for the next X event. This is like `xcb_poll_for_event`, but also 
includes
 /// machinery for handling async replies. Calling `xcb_poll_for_event` 
directly will
 /// cause replies to async requests to be lost, so that should never be called.

Reply via email to