Merge branch 'work/zzag/xwayland-frame-heartbeat' into 'master'

Draft: xwayland: Add _XWAYLAND_SUSPENDED

See merge request xorg/xserver!2124
This commit is contained in:
Vlad Zahorodnii 2026-01-29 08:43:52 +00:00
commit bfa7ff4bad
5 changed files with 66 additions and 9 deletions

View file

@ -188,7 +188,8 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
CARD32 timeout;
if (xwl_window && xwl_window->frame_callback &&
!xorg_list_is_empty(&xwl_present_window->frame_callback_list))
!xorg_list_is_empty(&xwl_present_window->frame_callback_list) &&
!xwl_window->suspended)
timeout = TIMER_LEN_FLIP;
else
timeout = TIMER_LEN_COPY;

View file

@ -171,7 +171,6 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
{
ScreenPtr screen = closure;
PropertyStateRec *rec = calldata;
struct xwl_screen *xwl_screen;
struct xwl_window *xwl_window;
if (rec->win->drawable.pScreen != screen)
@ -181,10 +180,7 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
if (!xwl_window)
return;
xwl_screen = xwl_screen_get(screen);
if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
xwl_window_update_property(xwl_window, rec);
xwl_window_update_property(xwl_window, rec);
}
#ifdef XACE
@ -204,7 +200,8 @@ xwl_access_property_callback(CallbackListPtr *pcbl, void *closure,
ScreenPtr pScreen = closure;
struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
if (prop->propertyName == xwl_screen->allow_commits_prop) {
if (prop->propertyName == xwl_screen->allow_commits_prop ||
prop->propertyName == xwl_screen->suspended_prop) {
/* Only the WM and the Xserver itself */
if (client != serverClient &&
client->index != xwl_screen->wm_client_id &&
@ -871,6 +868,7 @@ Bool
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
{
static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
static const char suspended[] = "_XWAYLAND_SUSPENDED";
struct xwl_screen *xwl_screen;
Pixel red_mask, blue_mask, green_mask;
int ret, bpc, green_bpc, i;
@ -1181,6 +1179,12 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
return FALSE;
xwl_screen->suspended_prop = MakeAtom(suspended,
strlen(suspended),
TRUE);
if (xwl_screen->suspended_prop == BAD_RESOURCE)
return FALSE;
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
AddCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, pScreen);
#ifdef XACE

View file

@ -141,6 +141,7 @@ struct xwl_screen {
struct glamor_context *glamor_ctx;
Atom allow_commits_prop;
Atom suspended_prop;
/* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
const char *glvnd_vendor;

View file

@ -172,17 +172,67 @@ xwl_window_set_allow_commits_from_property(struct xwl_window *xwl_window,
xwl_window_set_allow_commits(xwl_window, !!propdata[0], "from property");
}
static void
xwl_window_set_suspended(struct xwl_window *xwl_window, Bool suspended,
const char *debug_msg)
{
xwl_window->suspended = suspended;
DebugF("XWAYLAND: win %d suspended = %u (%s)\n",
xwl_window->toplevel->drawable.id, suspended, debug_msg);
}
static void
xwl_window_reset_suspended(struct xwl_window *xwl_window, const char *debug_msg)
{
xwl_window_set_suspended(xwl_window, FALSE, debug_msg);
}
static void
xwl_window_set_suspended_from_property(struct xwl_window *xwl_window, PropertyPtr prop)
{
static Bool warned = FALSE;
CARD32 *propdata;
if (prop->propertyName != xwl_window->xwl_screen->suspended_prop)
FatalError("Xwayland internal error: prop mismatch in %s.\n", __func__);
if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) {
/* Not properly set, so fall back to the default value */
xwl_window_reset_suspended(xwl_window, "WM fault");
if (!warned) {
LogMessageVerb(X_WARNING, 0, "Window manager is misusing property %s.\n",
NameForAtom(prop->propertyName));
warned = TRUE;
}
return;
}
propdata = prop->data;
xwl_window_set_suspended(xwl_window, !!propdata[0], "from property");
}
void
xwl_window_update_property(struct xwl_window *xwl_window,
PropertyStateRec *propstate)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
switch (propstate->state) {
case PropertyNewValue:
xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop);
if (propstate->prop->propertyName == xwl_screen->allow_commits_prop) {
xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop);
} else if (propstate->prop->propertyName == xwl_screen->suspended_prop) {
xwl_window_set_suspended_from_property(xwl_window, propstate->prop);
}
break;
case PropertyDelete:
xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted");
if (propstate->prop->propertyName == xwl_screen->allow_commits_prop) {
xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted");
} else if (propstate->prop->propertyName == xwl_screen->suspended_prop) {
xwl_window_reset_suspended(xwl_window, "property deleted");
}
break;
default:

View file

@ -90,6 +90,7 @@ struct xwl_window {
struct xorg_list link_damage;
struct xorg_list link_window;
struct wl_callback *frame_callback;
Bool suspended;
Bool allow_commits;
struct xorg_list window_buffers_available;
struct xorg_list window_buffers_unavailable;