From 610483bd2319c596c6ac084d47a39082b9df0175 Mon Sep 17 00:00:00 2001 From: Trigg Date: Tue, 4 Jan 2022 06:24:59 +0000 Subject: [PATCH] steamcompmgr: Implement external overlay support --- src/steamcompmgr.cpp | 75 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 571a8e2..e3a9b2d 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -146,6 +146,7 @@ struct win { uint32_t inputFocusMode; uint32_t appID; bool isOverlay; + bool isExternalOverlay; bool isFullscreen; bool isSysTrayIcon; bool sizeHintsSpecified; @@ -189,6 +190,7 @@ static Window currentInputFocusWindow; uint32_t currentInputFocusMode; static Window currentKeyboardFocusWindow; static Window currentOverlayWindow; +static Window currentExternalOverlayWindow; static Window currentNotificationWindow; static Window currentOverrideWindow; static Window currentFadeWindow; @@ -236,6 +238,7 @@ extern bool g_bIntegerScale; static Atom steamAtom; static Atom gameAtom; static Atom overlayAtom; +static Atom externalOverlayAtom; static Atom gamesRunningAtom; static Atom screenZoomAtom; static Atom screenScaleAtom; @@ -293,6 +296,7 @@ bool g_bPendingFade = false; #define GAME_PROP "STEAM_GAME" #define STEAM_PROP "STEAM_BIGPICTURE" #define OVERLAY_PROP "STEAM_OVERLAY" +#define EXTERNAL_OVERLAY_PROP "GAMESCOPE_EXTERNAL_OVERLAY" #define GAMES_RUNNING_PROP "STEAM_GAMES_RUNNING" #define SCREEN_SCALE_PROP "STEAM_SCREEN_SCALE" #define SCREEN_MAGNIFICATION_PROP "STEAM_SCREEN_MAGNIFICATION" @@ -355,13 +359,15 @@ static LogScope xwm_log("xwm"); #ifdef WORKAROUND_ZPOS_BUG static const uint32_t g_zposBase = 0; static const uint32_t g_zposOverride = 0; -static const uint32_t g_zposOverlay = 1; -static const uint32_t g_zposCursor = 2; +static const uint32_t g_zposExternalOverlay = 1; +static const uint32_t g_zposOverlay = 2; +static const uint32_t g_zposCursor = 3; #else static const uint32_t g_zposBase = 0; static const uint32_t g_zposOverride = 1; -static const uint32_t g_zposOverlay = 2; -static const uint32_t g_zposCursor = 3; +static const uint32_t g_zposExternalOverlay = 2; +static const uint32_t g_zposOverlay = 3; +static const uint32_t g_zposCursor = 4; #endif // poor man's semaphore @@ -1270,7 +1276,7 @@ paint_window(Display *dpy, win *w, win *scaleW, struct Composite_t *pComposite, int curLayer = pComposite->nLayerCount; - pComposite->data.flOpacity[ curLayer ] = ( w->isOverlay ? w->opacity / (float)OPAQUE : 1.0f ) * flOpacityScale; + pComposite->data.flOpacity[ curLayer ] = ( (w->isOverlay || w->isExternalOverlay) ? w->opacity / (float)OPAQUE : 1.0f ) * flOpacityScale; pComposite->data.vScale[ curLayer ].x = 1.0 / currentScaleRatio; pComposite->data.vScale[ curLayer ].y = 1.0 / currentScaleRatio; @@ -1318,11 +1324,15 @@ paint_window(Display *dpy, win *w, win *scaleW, struct Composite_t *pComposite, { pPipeline->layerBindings[ curLayer ].zpos = g_zposOverlay; } + if ( w->isExternalOverlay ) + { + pPipeline->layerBindings[ curLayer ].zpos = g_zposExternalOverlay; + } pPipeline->layerBindings[ curLayer ].tex = lastCommit->vulkanTex; pPipeline->layerBindings[ curLayer ].fbid = lastCommit->fb_id; - pPipeline->layerBindings[ curLayer ].bFilter = w->isOverlay ? true : g_bFilterGameWindow; + pPipeline->layerBindings[ curLayer ].bFilter = (w->isOverlay || w->isExternalOverlay) ? true : g_bFilterGameWindow; if ( bBasePlane ) { @@ -1376,6 +1386,7 @@ paint_debug_info(Display *dpy) } win *overlay = find_win(dpy, currentOverlayWindow); + win *externalOverlay = find_win(dpy, currentExternalOverlayWindow); win *notification = find_win(dpy, currentNotificationWindow); if (overlay && gamesRunningCount && overlay->opacity) @@ -1384,6 +1395,12 @@ paint_debug_info(Display *dpy) paint_message(messageBuffer, Y, 1.0f, 0.0f, 1.0f); Y += textYMax; } + if (externalOverlay && externalOverlay->opacity) + { + sprintf(messageBuffer, "Compositing external overlay at opacity %f", externalOverlay->opacity / (float)OPAQUE); + paint_message(messageBuffer, Y, 1.0f, 0.0f, 1.0f); Y += textYMax; + } + if (notification && gamesRunningCount && notification->opacity) { sprintf(messageBuffer, "Compositing notification at opacity %f", notification->opacity / (float)OPAQUE); @@ -1422,6 +1439,7 @@ paint_all(Display *dpy, MouseCursor *cursor) gpuvis_trace_begin_ctx_printf( paintID, "paint_all" ); win *w; win *overlay; + win *externalOverlay; win *notification; win *override; win *input; @@ -1431,6 +1449,7 @@ paint_all(Display *dpy, MouseCursor *cursor) w = find_win(dpy, currentFocusWindow); overlay = find_win(dpy, currentOverlayWindow); + externalOverlay = find_win(dpy, currentExternalOverlayWindow); notification = find_win(dpy, currentNotificationWindow); override = find_win(dpy, currentOverrideWindow); input = find_win(dpy, currentInputFocusWindow); @@ -1533,7 +1552,18 @@ paint_all(Display *dpy, MouseCursor *cursor) if ( override && !w->isSteamStreamingClient ) { paint_window(dpy, override, w, &composite, &pipeline, false, cursor); - update_touch_scaling( &composite ); + update_touch_scaling( &composite ); + } + + if (externalOverlay) + { + if (externalOverlay->opacity) + { + paint_window(dpy, externalOverlay, externalOverlay, &composite, &pipeline, false, cursor); + + if ( externalOverlay->id == currentInputFocusWindow ) + update_touch_scaling( &composite ); + } } if (inGame && overlay) @@ -1895,7 +1925,7 @@ determine_and_apply_focus(Display *dpy, MouseCursor *cursor) } if ( w->a.map_state == IsViewable && w->a.c_class == InputOutput && w->isOverlay == false && - ( win_has_game_id( w ) || w->isSteam || w->isSteamStreamingClient ) && + w->isExternalOverlay == false && ( win_has_game_id( w ) || w->isSteam || w->isSteamStreamingClient ) && (w->opacity > TRANSLUCENT || w->isSteamStreamingClient == true ) ) { vecPossibleFocusWindows.push_back( w ); @@ -1914,6 +1944,14 @@ determine_and_apply_focus(Display *dpy, MouseCursor *cursor) } } + if (w->isExternalOverlay) + { + if(w->opacity >= maxOpacity) + { + currentExternalOverlayWindow = w->id; + } + } + if ( w->isOverlay && w->inputFocusMode ) { inputFocus = w; @@ -2412,6 +2450,7 @@ map_win(Display *dpy, Window id, unsigned long sequence) w->appID = w->id; } w->isOverlay = get_prop(dpy, w->id, overlayAtom, 0); + w->isExternalOverlay = get_prop(dpy, w->id, externalOverlayAtom, 0); get_size_hints(dpy, w); @@ -2623,6 +2662,7 @@ add_win(Display *dpy, Window id, Window prev, unsigned long sequence) } new_win->isOverlay = false; + new_win->isExternalOverlay = false; new_win->isSteam = false; new_win->isSteamStreamingClient = false; new_win->isSteamStreamingClientVideo = false; @@ -2830,6 +2870,8 @@ destroy_win(Display *dpy, Window id, bool gone, bool fade) currentInputFocusWindow = None; if (currentOverlayWindow == id && gone) currentOverlayWindow = None; + if (currentExternalOverlayWindow == id && gone) + currentExternalOverlayWindow = None; if (currentNotificationWindow == id && gone) currentNotificationWindow = None; if (currentOverrideWindow == id && gone) @@ -2850,7 +2892,7 @@ damage_win(Display *dpy, XDamageNotifyEvent *de) if (!w) return; - if (w->isOverlay && !w->opacity) + if ((w->isOverlay || w->isExternalOverlay) && !w->opacity) return; // First damage event we get, compute focus; we only want to focus damaged @@ -3052,6 +3094,10 @@ handle_property_notify(Display *dpy, XPropertyEvent *ev) { hasRepaint = true; } + if ( w->id == currentExternalOverlayWindow ) + { + hasRepaint = true; + } } unsigned int maxOpacity = 0; @@ -3066,6 +3112,10 @@ handle_property_notify(Display *dpy, XPropertyEvent *ev) maxOpacity = w->opacity; } } + if (w->isExternalOverlay) + { + currentExternalOverlayWindow = w->id; + } } } } @@ -3411,7 +3461,11 @@ void handle_done_commits( void ) hasRepaint = true; } } - + // If this is an external overlay, repaint + if ( w->id == currentExternalOverlayWindow && w->opacity != TRANSLUCENT ) + { + hasRepaint = true; + } // If this is the main plane, repaint if ( w->id == currentFocusWindow && !w->isSteamStreamingClient ) { @@ -4050,6 +4104,7 @@ steamcompmgr_main(int argc, char **argv) steamTouchClickModeAtom = XInternAtom(dpy, "STEAM_TOUCH_CLICK_MODE", false); gameAtom = XInternAtom(dpy, GAME_PROP, false); overlayAtom = XInternAtom(dpy, OVERLAY_PROP, false); + externalOverlayAtom = XInternAtom(dpy, EXTERNAL_OVERLAY_PROP, false); opacityAtom = XInternAtom(dpy, OPACITY_PROP, false); gamesRunningAtom = XInternAtom(dpy, GAMES_RUNNING_PROP, false); screenScaleAtom = XInternAtom(dpy, SCREEN_SCALE_PROP, false);