mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-02-09 00:20:33 +01:00
xwayland: Add _XWAYLAND_SUSPENDED
If a compositor stops sending frame callbacks to a mapped window (this can happen with some compositors if they don't unmap minimized windows or windows on other virtual desktops), the app may break. For example, it is a pretty common thing with video games. They may freeze and remain frozen even after getting brought back to foreground. This change adds the _XWAYLAND_SUSPENDED property so the compositor can provide a hint to Xwayland that the window won't receive frame callbacks any time soon and that it is better to send present complete notify events at approximately 60Hz instead of 1Hz. Signed-off-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
This commit is contained in:
parent
ac42c39145
commit
8d3ef700c7
5 changed files with 66 additions and 9 deletions
|
|
@ -189,7 +189,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;
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
@ -865,6 +862,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;
|
||||
|
|
@ -1176,6 +1174,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue