Fix blank client frames and frame-callback stall
Blit client buffers from their top-left origin instead of honoring set_window_geometry offsets: clients like foot set a geometry that extends above the buffer (CSD shadow, geom_y < 0), which made the source row pointer start before the buffer and produced a blank frame. Buffers are now copied 1:1 from origin, capped to canvas. Also dispatch wl_callback.done on the first configure commit so frame-throttled clients (foot) don't stall waiting for it.
This commit is contained in:
parent
1206ab41db
commit
3ae1a7320a
1 changed files with 21 additions and 11 deletions
|
|
@ -257,15 +257,13 @@ static void copy_buffer_to_display(struct tabby_surface *surface) {
|
|||
size_t out_size = (size_t)out->height * (size_t)out->stride;
|
||||
memset(out->data, 0x22, out_size);
|
||||
|
||||
int src_x = (surface->geom_width > 0) ? surface->geom_x : 0;
|
||||
int src_y = (surface->geom_height > 0) ? surface->geom_y : 0;
|
||||
int src_w = (surface->geom_width > 0) ? surface->geom_width : surface->pixel_width;
|
||||
int src_h = (surface->geom_height > 0) ? surface->geom_height : surface->pixel_height;
|
||||
|
||||
if (src_x + src_w > surface->pixel_width) src_w = surface->pixel_width - src_x;
|
||||
if (src_y + src_h > surface->pixel_height) src_h = surface->pixel_height - src_y;
|
||||
if (src_w < 0) src_w = 0;
|
||||
if (src_h < 0) src_h = 0;
|
||||
/* Blit the client's buffer at its top-left origin (0,0), capped to the
|
||||
canvas size. We intentionally ignore the surface's window geometry for
|
||||
positioning: some clients set a geometry that extends above/beside the
|
||||
buffer (e.g. foot's CSD shadow, geom_y < 0), which would make the source
|
||||
row pointer start before the buffer and produce a blank frame. */
|
||||
int src_w = surface->pixel_width;
|
||||
int src_h = surface->pixel_height;
|
||||
|
||||
int cw = (src_w < out->width) ? src_w : out->width;
|
||||
int ch = (src_h < out->height) ? src_h : out->height;
|
||||
|
|
@ -273,11 +271,10 @@ static void copy_buffer_to_display(struct tabby_surface *surface) {
|
|||
if (cw <= 0 || ch <= 0) return;
|
||||
if (surface->pixel_stride <= 0 || out->stride <= 0) return;
|
||||
if (surface->pixels == NULL || out->data == NULL) return;
|
||||
if (src_y + ch > surface->pixel_height) return;
|
||||
|
||||
for (int y = 0; y < ch; y++) {
|
||||
void *dst = out->data + y * out->stride;
|
||||
void *src = surface->pixels + (src_y + y) * surface->pixel_stride + src_x * 4;
|
||||
void *src = surface->pixels + y * surface->pixel_stride;
|
||||
if ((unsigned char*)dst < (unsigned char*)out->data ||
|
||||
(unsigned char*)dst + cw*4 > (unsigned char*)out->data + out->height*out->stride) break;
|
||||
if ((unsigned char*)src < (unsigned char*)surface->pixels ||
|
||||
|
|
@ -308,6 +305,19 @@ static void surface_commit(struct wl_client *client, struct wl_resource *resourc
|
|||
|
||||
if (surface->tab_label && surface->title)
|
||||
gtk_label_set_text(GTK_LABEL(surface->tab_label), surface->title);
|
||||
|
||||
/* Dispatch the pending frame callback. Several clients (notably
|
||||
foot) request wl_surface.frame on the first commit and will not
|
||||
render their real buffer until wl_callback.done is sent, so it
|
||||
must fire even on this early configure path. */
|
||||
if (surface->frame_callback) {
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
uint32_t ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
||||
wl_callback_send_done(surface->frame_callback, ms);
|
||||
wl_resource_destroy(surface->frame_callback);
|
||||
surface->frame_callback = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue