steamcompmgr: Implement external overlay support
This commit is contained in:
parent
9a26fa583a
commit
610483bd23
1 changed files with 65 additions and 10 deletions
|
@ -146,6 +146,7 @@ struct win {
|
||||||
uint32_t inputFocusMode;
|
uint32_t inputFocusMode;
|
||||||
uint32_t appID;
|
uint32_t appID;
|
||||||
bool isOverlay;
|
bool isOverlay;
|
||||||
|
bool isExternalOverlay;
|
||||||
bool isFullscreen;
|
bool isFullscreen;
|
||||||
bool isSysTrayIcon;
|
bool isSysTrayIcon;
|
||||||
bool sizeHintsSpecified;
|
bool sizeHintsSpecified;
|
||||||
|
@ -189,6 +190,7 @@ static Window currentInputFocusWindow;
|
||||||
uint32_t currentInputFocusMode;
|
uint32_t currentInputFocusMode;
|
||||||
static Window currentKeyboardFocusWindow;
|
static Window currentKeyboardFocusWindow;
|
||||||
static Window currentOverlayWindow;
|
static Window currentOverlayWindow;
|
||||||
|
static Window currentExternalOverlayWindow;
|
||||||
static Window currentNotificationWindow;
|
static Window currentNotificationWindow;
|
||||||
static Window currentOverrideWindow;
|
static Window currentOverrideWindow;
|
||||||
static Window currentFadeWindow;
|
static Window currentFadeWindow;
|
||||||
|
@ -236,6 +238,7 @@ extern bool g_bIntegerScale;
|
||||||
static Atom steamAtom;
|
static Atom steamAtom;
|
||||||
static Atom gameAtom;
|
static Atom gameAtom;
|
||||||
static Atom overlayAtom;
|
static Atom overlayAtom;
|
||||||
|
static Atom externalOverlayAtom;
|
||||||
static Atom gamesRunningAtom;
|
static Atom gamesRunningAtom;
|
||||||
static Atom screenZoomAtom;
|
static Atom screenZoomAtom;
|
||||||
static Atom screenScaleAtom;
|
static Atom screenScaleAtom;
|
||||||
|
@ -293,6 +296,7 @@ bool g_bPendingFade = false;
|
||||||
#define GAME_PROP "STEAM_GAME"
|
#define GAME_PROP "STEAM_GAME"
|
||||||
#define STEAM_PROP "STEAM_BIGPICTURE"
|
#define STEAM_PROP "STEAM_BIGPICTURE"
|
||||||
#define OVERLAY_PROP "STEAM_OVERLAY"
|
#define OVERLAY_PROP "STEAM_OVERLAY"
|
||||||
|
#define EXTERNAL_OVERLAY_PROP "GAMESCOPE_EXTERNAL_OVERLAY"
|
||||||
#define GAMES_RUNNING_PROP "STEAM_GAMES_RUNNING"
|
#define GAMES_RUNNING_PROP "STEAM_GAMES_RUNNING"
|
||||||
#define SCREEN_SCALE_PROP "STEAM_SCREEN_SCALE"
|
#define SCREEN_SCALE_PROP "STEAM_SCREEN_SCALE"
|
||||||
#define SCREEN_MAGNIFICATION_PROP "STEAM_SCREEN_MAGNIFICATION"
|
#define SCREEN_MAGNIFICATION_PROP "STEAM_SCREEN_MAGNIFICATION"
|
||||||
|
@ -355,13 +359,15 @@ static LogScope xwm_log("xwm");
|
||||||
#ifdef WORKAROUND_ZPOS_BUG
|
#ifdef WORKAROUND_ZPOS_BUG
|
||||||
static const uint32_t g_zposBase = 0;
|
static const uint32_t g_zposBase = 0;
|
||||||
static const uint32_t g_zposOverride = 0;
|
static const uint32_t g_zposOverride = 0;
|
||||||
static const uint32_t g_zposOverlay = 1;
|
static const uint32_t g_zposExternalOverlay = 1;
|
||||||
static const uint32_t g_zposCursor = 2;
|
static const uint32_t g_zposOverlay = 2;
|
||||||
|
static const uint32_t g_zposCursor = 3;
|
||||||
#else
|
#else
|
||||||
static const uint32_t g_zposBase = 0;
|
static const uint32_t g_zposBase = 0;
|
||||||
static const uint32_t g_zposOverride = 1;
|
static const uint32_t g_zposOverride = 1;
|
||||||
static const uint32_t g_zposOverlay = 2;
|
static const uint32_t g_zposExternalOverlay = 2;
|
||||||
static const uint32_t g_zposCursor = 3;
|
static const uint32_t g_zposOverlay = 3;
|
||||||
|
static const uint32_t g_zposCursor = 4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// poor man's semaphore
|
// poor man's semaphore
|
||||||
|
@ -1270,7 +1276,7 @@ paint_window(Display *dpy, win *w, win *scaleW, struct Composite_t *pComposite,
|
||||||
|
|
||||||
int curLayer = pComposite->nLayerCount;
|
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 ].x = 1.0 / currentScaleRatio;
|
||||||
pComposite->data.vScale[ curLayer ].y = 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;
|
pPipeline->layerBindings[ curLayer ].zpos = g_zposOverlay;
|
||||||
}
|
}
|
||||||
|
if ( w->isExternalOverlay )
|
||||||
|
{
|
||||||
|
pPipeline->layerBindings[ curLayer ].zpos = g_zposExternalOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
pPipeline->layerBindings[ curLayer ].tex = lastCommit->vulkanTex;
|
pPipeline->layerBindings[ curLayer ].tex = lastCommit->vulkanTex;
|
||||||
pPipeline->layerBindings[ curLayer ].fbid = lastCommit->fb_id;
|
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 )
|
if ( bBasePlane )
|
||||||
{
|
{
|
||||||
|
@ -1376,6 +1386,7 @@ paint_debug_info(Display *dpy)
|
||||||
}
|
}
|
||||||
|
|
||||||
win *overlay = find_win(dpy, currentOverlayWindow);
|
win *overlay = find_win(dpy, currentOverlayWindow);
|
||||||
|
win *externalOverlay = find_win(dpy, currentExternalOverlayWindow);
|
||||||
win *notification = find_win(dpy, currentNotificationWindow);
|
win *notification = find_win(dpy, currentNotificationWindow);
|
||||||
|
|
||||||
if (overlay && gamesRunningCount && overlay->opacity)
|
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;
|
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)
|
if (notification && gamesRunningCount && notification->opacity)
|
||||||
{
|
{
|
||||||
sprintf(messageBuffer, "Compositing notification at opacity %f", notification->opacity / (float)OPAQUE);
|
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" );
|
gpuvis_trace_begin_ctx_printf( paintID, "paint_all" );
|
||||||
win *w;
|
win *w;
|
||||||
win *overlay;
|
win *overlay;
|
||||||
|
win *externalOverlay;
|
||||||
win *notification;
|
win *notification;
|
||||||
win *override;
|
win *override;
|
||||||
win *input;
|
win *input;
|
||||||
|
@ -1431,6 +1449,7 @@ paint_all(Display *dpy, MouseCursor *cursor)
|
||||||
|
|
||||||
w = find_win(dpy, currentFocusWindow);
|
w = find_win(dpy, currentFocusWindow);
|
||||||
overlay = find_win(dpy, currentOverlayWindow);
|
overlay = find_win(dpy, currentOverlayWindow);
|
||||||
|
externalOverlay = find_win(dpy, currentExternalOverlayWindow);
|
||||||
notification = find_win(dpy, currentNotificationWindow);
|
notification = find_win(dpy, currentNotificationWindow);
|
||||||
override = find_win(dpy, currentOverrideWindow);
|
override = find_win(dpy, currentOverrideWindow);
|
||||||
input = find_win(dpy, currentInputFocusWindow);
|
input = find_win(dpy, currentInputFocusWindow);
|
||||||
|
@ -1533,7 +1552,18 @@ paint_all(Display *dpy, MouseCursor *cursor)
|
||||||
if ( override && !w->isSteamStreamingClient )
|
if ( override && !w->isSteamStreamingClient )
|
||||||
{
|
{
|
||||||
paint_window(dpy, override, w, &composite, &pipeline, false, cursor);
|
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)
|
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 &&
|
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 ) )
|
(w->opacity > TRANSLUCENT || w->isSteamStreamingClient == true ) )
|
||||||
{
|
{
|
||||||
vecPossibleFocusWindows.push_back( w );
|
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 )
|
if ( w->isOverlay && w->inputFocusMode )
|
||||||
{
|
{
|
||||||
inputFocus = w;
|
inputFocus = w;
|
||||||
|
@ -2412,6 +2450,7 @@ map_win(Display *dpy, Window id, unsigned long sequence)
|
||||||
w->appID = w->id;
|
w->appID = w->id;
|
||||||
}
|
}
|
||||||
w->isOverlay = get_prop(dpy, w->id, overlayAtom, 0);
|
w->isOverlay = get_prop(dpy, w->id, overlayAtom, 0);
|
||||||
|
w->isExternalOverlay = get_prop(dpy, w->id, externalOverlayAtom, 0);
|
||||||
|
|
||||||
get_size_hints(dpy, w);
|
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->isOverlay = false;
|
||||||
|
new_win->isExternalOverlay = false;
|
||||||
new_win->isSteam = false;
|
new_win->isSteam = false;
|
||||||
new_win->isSteamStreamingClient = false;
|
new_win->isSteamStreamingClient = false;
|
||||||
new_win->isSteamStreamingClientVideo = false;
|
new_win->isSteamStreamingClientVideo = false;
|
||||||
|
@ -2830,6 +2870,8 @@ destroy_win(Display *dpy, Window id, bool gone, bool fade)
|
||||||
currentInputFocusWindow = None;
|
currentInputFocusWindow = None;
|
||||||
if (currentOverlayWindow == id && gone)
|
if (currentOverlayWindow == id && gone)
|
||||||
currentOverlayWindow = None;
|
currentOverlayWindow = None;
|
||||||
|
if (currentExternalOverlayWindow == id && gone)
|
||||||
|
currentExternalOverlayWindow = None;
|
||||||
if (currentNotificationWindow == id && gone)
|
if (currentNotificationWindow == id && gone)
|
||||||
currentNotificationWindow = None;
|
currentNotificationWindow = None;
|
||||||
if (currentOverrideWindow == id && gone)
|
if (currentOverrideWindow == id && gone)
|
||||||
|
@ -2850,7 +2892,7 @@ damage_win(Display *dpy, XDamageNotifyEvent *de)
|
||||||
if (!w)
|
if (!w)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (w->isOverlay && !w->opacity)
|
if ((w->isOverlay || w->isExternalOverlay) && !w->opacity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// First damage event we get, compute focus; we only want to focus damaged
|
// 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;
|
hasRepaint = true;
|
||||||
}
|
}
|
||||||
|
if ( w->id == currentExternalOverlayWindow )
|
||||||
|
{
|
||||||
|
hasRepaint = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int maxOpacity = 0;
|
unsigned int maxOpacity = 0;
|
||||||
|
@ -3066,6 +3112,10 @@ handle_property_notify(Display *dpy, XPropertyEvent *ev)
|
||||||
maxOpacity = w->opacity;
|
maxOpacity = w->opacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (w->isExternalOverlay)
|
||||||
|
{
|
||||||
|
currentExternalOverlayWindow = w->id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3411,7 +3461,11 @@ void handle_done_commits( void )
|
||||||
hasRepaint = true;
|
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 this is the main plane, repaint
|
||||||
if ( w->id == currentFocusWindow && !w->isSteamStreamingClient )
|
if ( w->id == currentFocusWindow && !w->isSteamStreamingClient )
|
||||||
{
|
{
|
||||||
|
@ -4050,6 +4104,7 @@ steamcompmgr_main(int argc, char **argv)
|
||||||
steamTouchClickModeAtom = XInternAtom(dpy, "STEAM_TOUCH_CLICK_MODE", false);
|
steamTouchClickModeAtom = XInternAtom(dpy, "STEAM_TOUCH_CLICK_MODE", false);
|
||||||
gameAtom = XInternAtom(dpy, GAME_PROP, false);
|
gameAtom = XInternAtom(dpy, GAME_PROP, false);
|
||||||
overlayAtom = XInternAtom(dpy, OVERLAY_PROP, false);
|
overlayAtom = XInternAtom(dpy, OVERLAY_PROP, false);
|
||||||
|
externalOverlayAtom = XInternAtom(dpy, EXTERNAL_OVERLAY_PROP, false);
|
||||||
opacityAtom = XInternAtom(dpy, OPACITY_PROP, false);
|
opacityAtom = XInternAtom(dpy, OPACITY_PROP, false);
|
||||||
gamesRunningAtom = XInternAtom(dpy, GAMES_RUNNING_PROP, false);
|
gamesRunningAtom = XInternAtom(dpy, GAMES_RUNNING_PROP, false);
|
||||||
screenScaleAtom = XInternAtom(dpy, SCREEN_SCALE_PROP, false);
|
screenScaleAtom = XInternAtom(dpy, SCREEN_SCALE_PROP, false);
|
||||||
|
|
Loading…
Reference in a new issue