diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 63a7266..c7ed945 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -166,6 +166,20 @@ Window x11_win(win *w) { return w->id; } +struct global_focus_t +{ + win *currentFocusWindow; + win *currentInputFocusWindow; + uint32_t currentInputFocusMode; + win *currentOverlayWindow; + win *currentExternalOverlayWindow; + win *currentNotificationWindow; + win *currentOverrideWindow; + win *currentFadeWindow; + MouseCursor *cursor; +} global_focus; + + uint32_t currentOutputWidth, currentOutputHeight; bool hasFocusWindow; @@ -1121,7 +1135,7 @@ namespace PaintWindowFlag using PaintWindowFlags = uint32_t; static void -paint_window(xwayland_ctx_t *ctx, win *w, win *scaleW, struct Composite_t *pComposite, +paint_window(win *w, win *scaleW, struct Composite_t *pComposite, struct VulkanPipeline_t *pPipeline, MouseCursor *cursor, PaintWindowFlags flags = 0, float flOpacityScale = 1.0f) { uint32_t sourceWidth, sourceHeight; @@ -1168,7 +1182,7 @@ paint_window(xwayland_ctx_t *ctx, win *w, win *scaleW, struct Composite_t *pComp // Base plane will stay as tex=0 if we don't have contents yet, which will // make us fall back to compositing and use the Vulkan null texture - win *mainOverlayWindow = ctx->currentOverlayWindow; + win *mainOverlayWindow = global_focus.currentOverlayWindow; const bool notificationMode = flags & PaintWindowFlag::NotificationMode; if (notificationMode && !mainOverlayWindow) @@ -1314,8 +1328,11 @@ static void update_touch_scaling( struct Composite_t *pComposite ) } static void -paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) +paint_all() { + gamescope_xwayland_server_t *root_server = wlserver_get_xwayland_server(0); + xwayland_ctx_t *root_ctx = root_server->ctx.get(); + static long long int paintID = 0; paintID++; @@ -1330,12 +1347,12 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) unsigned int currentTime = get_time_in_milliseconds(); bool fadingOut = ( currentTime - fadeOutStartTime < g_FadeOutDuration || g_bPendingFade ) && g_HeldCommits[HELD_COMMIT_FADE]; - w = ctx->currentFocusWindow; - overlay = ctx->currentOverlayWindow; - externalOverlay = ctx->currentExternalOverlayWindow; - notification = ctx->currentNotificationWindow; - override = ctx->currentOverrideWindow; - input = ctx->currentInputFocusWindow; + w = global_focus.currentFocusWindow; + overlay = global_focus.currentOverlayWindow; + externalOverlay = global_focus.currentExternalOverlayWindow; + notification = global_focus.currentNotificationWindow; + override = global_focus.currentOverrideWindow; + input = global_focus.currentInputFocusWindow; if ( !w ) { @@ -1379,14 +1396,18 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) win *videow = NULL; bool bHasVideoUnderlay = false; - for ( videow = ctx->list; videow; videow = videow->next ) + gamescope_xwayland_server_t *server = NULL; + for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) { - if ( videow->isSteamStreamingClientVideo == true ) + for ( videow = server->ctx->list; videow; videow = videow->next ) { - // TODO: also check matching AppID so we can have several pairs - paint_window(ctx, videow, videow, &composite, &pipeline, cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::DrawBorders); - bHasVideoUnderlay = true; - break; + if ( videow->isSteamStreamingClientVideo == true ) + { + // TODO: also check matching AppID so we can have several pairs + paint_window(videow, videow, &composite, &pipeline, global_focus.cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::DrawBorders); + bHasVideoUnderlay = true; + break; + } } } @@ -1395,7 +1416,7 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) uint32_t flags = PaintWindowFlag::DrawBorders; if ( !bHasVideoUnderlay ) flags |= PaintWindowFlag::BasePlane; - paint_window(ctx, w, w, &composite, &pipeline, cursor, flags); + paint_window(w, w, &composite, &pipeline, global_focus.cursor, flags); update_touch_scaling( &composite ); // paint UI unless it's fully hidden, which it communicates to us through opacity=0 @@ -1412,7 +1433,7 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) : ((currentTime - fadeOutStartTime) / (float)g_FadeOutDuration); paint_cached_base_layer(g_HeldCommits[HELD_COMMIT_FADE], g_CachedPlanes[HELD_COMMIT_FADE], &composite, &pipeline, 1.0f - opacityScale); - paint_window(ctx, w, w, &composite, &pipeline, cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::FadeTarget | PaintWindowFlag::DrawBorders, opacityScale); + paint_window(w, w, &composite, &pipeline, global_focus.cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::FadeTarget | PaintWindowFlag::DrawBorders, opacityScale); } else { @@ -1422,11 +1443,11 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) g_HeldCommits[HELD_COMMIT_FADE] = nullptr; g_bPendingFade = false; fadeOutStartTime = 0; - ctx->currentFadeWindow = None; + global_focus.currentFadeWindow = None; } } // Just draw focused window as normal, be it Steam or the game - paint_window(ctx, w, w, &composite, &pipeline, cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::DrawBorders); + paint_window(w, w, &composite, &pipeline, global_focus.cursor, PaintWindowFlag::BasePlane | PaintWindowFlag::DrawBorders); } update_touch_scaling( &composite ); } @@ -1437,7 +1458,7 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) // as we will have too many layers. Better to be safe than sorry. if ( override && !w->isSteamStreamingClient ) { - paint_window(ctx, override, w, &composite, &pipeline, cursor); + paint_window(override, w, &composite, &pipeline, global_focus.cursor); update_touch_scaling( &composite ); } @@ -1445,9 +1466,9 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) { if (externalOverlay->opacity) { - paint_window(ctx, externalOverlay, externalOverlay, &composite, &pipeline, cursor, PaintWindowFlag::NoScale); + paint_window(externalOverlay, externalOverlay, &composite, &pipeline, global_focus.cursor, PaintWindowFlag::NoScale); - if ( externalOverlay == ctx->currentInputFocusWindow ) + if ( externalOverlay == global_focus.currentInputFocusWindow ) update_touch_scaling( &composite ); } } @@ -1456,9 +1477,9 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) { if (overlay->opacity) { - paint_window(ctx, overlay, overlay, &composite, &pipeline, cursor, PaintWindowFlag::DrawBorders); + paint_window(overlay, overlay, &composite, &pipeline, global_focus.cursor, PaintWindowFlag::DrawBorders); - if ( overlay == ctx->currentInputFocusWindow ) + if ( overlay == global_focus.currentInputFocusWindow ) update_touch_scaling( &composite ); } } @@ -1467,7 +1488,7 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) { if (notification->opacity) { - paint_window(ctx, notification, notification, &composite, &pipeline, cursor, PaintWindowFlag::NotificationMode); + paint_window(notification, notification, &composite, &pipeline, global_focus.cursor, PaintWindowFlag::NotificationMode); } } @@ -1476,7 +1497,7 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) // Draw cursor if we need to if (input) { - cursor->paint(override == input ? w : input, &composite, &pipeline); + global_focus.cursor->paint(override == input ? w : input, &composite, &pipeline); } if ( !bValidContents || ( BIsNested() == false && g_DRM.paused == true ) ) @@ -1626,7 +1647,7 @@ paint_all(xwayland_ctx_t *ctx, MouseCursor *cursor) xwm_log.errorf( "Failed to save screenshot to %s", pTimeBuffer ); } - XDeleteProperty( ctx->dpy, ctx->root, ctx->atoms.gamescopeScreenShotAtom ); + XDeleteProperty( root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeScreenShotAtom ); }); screenshotThread.detach(); @@ -1780,7 +1801,7 @@ static bool is_good_override_candidate( win *override, win* focus ) } static void -determine_and_apply_focus(xwayland_ctx_t *ctx) +determine_and_apply_focus(xwayland_ctx_t *ctx, std::vector& vecGlobalPossibleFocusWindows) { win *w, *focus = NULL, *override_focus = NULL; win *inputFocus = NULL; @@ -1788,10 +1809,6 @@ determine_and_apply_focus(xwayland_ctx_t *ctx) gameFocused = false; win *prevFocusWindow = ctx->currentFocusWindow; - win *prevOverlayWindow = ctx->currentOverlayWindow; - win *prevExternalOverlayWindow = ctx->currentExternalOverlayWindow; - win *prevNotificationWindow = ctx->currentNotificationWindow; - win *prevOverrideWindow = ctx->currentOverrideWindow; ctx->currentFocusWindow = nullptr; ctx->currentOverlayWindow = nullptr; ctx->currentExternalOverlayWindow = nullptr; @@ -1844,51 +1861,9 @@ determine_and_apply_focus(xwayland_ctx_t *ctx) } } - if ( prevExternalOverlayWindow != ctx->currentExternalOverlayWindow || - prevOverlayWindow != ctx->currentOverlayWindow || - prevNotificationWindow != ctx->currentNotificationWindow ) - { - hasRepaint = true; - } + vecGlobalPossibleFocusWindows.insert(vecGlobalPossibleFocusWindows.end(), vecPossibleFocusWindows.begin(), vecPossibleFocusWindows.end()); - std::vector< unsigned long > focusable_appids; - std::vector< unsigned long > focusable_windows; - - for ( win *focusable_window : vecPossibleFocusWindows ) - { - unsigned int unAppID = focusable_window->appID; - if ( unAppID != 0 ) - { - unsigned long j; - for( j = 0; j < focusable_appids.size(); j++ ) - { - if ( focusable_appids[ j ] == unAppID ) - { - break; - } - } - if ( j == focusable_appids.size() ) - { - focusable_appids.push_back( unAppID ); - } - } - - // list of [window, appid, pid] triplets - focusable_windows.push_back( focusable_window->id ); - focusable_windows.push_back( focusable_window->appID ); - focusable_windows.push_back( focusable_window->pid ); - } - - XChangeProperty( ctx->dpy, ctx->root, ctx->atoms.gamescopeFocusableAppsAtom, XA_CARDINAL, 32, PropModeReplace, - (unsigned char *)focusable_appids.data(), focusable_appids.size() ); - - XChangeProperty( ctx->dpy, ctx->root, ctx->atoms.gamescopeFocusableWindowsAtom, XA_CARDINAL, 32, PropModeReplace, - (unsigned char *)focusable_windows.data(), focusable_windows.size() ); - - std::stable_sort( vecPossibleFocusWindows.begin(), vecPossibleFocusWindows.end(), - is_focus_priority_greater ); - - if ( ctx->focusControlWindow != None || vecFocuscontrolAppIDs.size() > 0 ) + if ( ctx->focusControlWindow != None ) { if ( ctx->focusControlWindow != None ) { @@ -1901,22 +1876,11 @@ determine_and_apply_focus(xwayland_ctx_t *ctx) } } } - - for ( auto focusable_appid : vecFocuscontrolAppIDs ) - { - for ( win *focusable_window : vecPossibleFocusWindows ) - { - if ( focusable_window->appID == focusable_appid ) - { - focus = focusable_window; - goto found; - } - } - } found: gameFocused = true; } - else if ( vecPossibleFocusWindows.size() > 0 ) + + if ( !focus && vecPossibleFocusWindows.size() > 0 ) { focus = vecPossibleFocusWindows[ 0 ]; gameFocused = focus->appID != 0; @@ -1974,17 +1938,7 @@ found: if ( !override_focus && focus ) { - if ( vecFocuscontrolAppIDs.size() > 0 ) - { - for ( win *override : vecPossibleFocusWindows ) - { - if ( is_good_override_candidate(override, focus) && override->appID == focus->appID ) { - override_focus = override; - break; - } - } - } - else if ( vecPossibleFocusWindows.size() > 0 ) + if ( vecPossibleFocusWindows.size() > 0 ) { for ( win *override : vecPossibleFocusWindows ) { @@ -2001,29 +1955,11 @@ found: ctx->currentOverrideWindow = override_focus; - if ( ctx->currentOverrideWindow != prevOverrideWindow ) - hasRepaint = true; - - unsigned long focusedWindow = 0; - unsigned long focusedAppId = 0; - if ( inputFocus == NULL ) { inputFocus = override_focus ? override_focus : focus; } - if ( focus ) - { - focusedWindow = focus->id; - focusedAppId = inputFocus->appID; - } - - XChangeProperty( ctx->dpy, ctx->root, ctx->atoms.gamescopeFocusedAppAtom, XA_CARDINAL, 32, PropModeReplace, - (unsigned char *)&focusedAppId, focusedAppId != 0 ? 1 : 0 ); - - XChangeProperty( ctx->dpy, ctx->root, ctx->atoms.gamescopeFocusedWindowAtom, XA_CARDINAL, 32, PropModeReplace, - (unsigned char *)&focusedWindow, focusedWindow != 0 ? 1 : 0 ); - if (!focus) { return; @@ -2031,29 +1967,6 @@ found: if ( prevFocusWindow != focus ) { - if ( g_FadeOutDuration != 0 && !g_bFirstFrame ) - { - if ( !g_HeldCommits[ HELD_COMMIT_FADE ] ) - { - ctx->currentFadeWindow = prevFocusWindow; - g_HeldCommits[ HELD_COMMIT_FADE ] = g_HeldCommits[ HELD_COMMIT_BASE ]; - g_bPendingFade = true; - } - else - { - // If we end up fading back to what we were going to fade to, cancel the fade. - if ( ctx->currentFadeWindow != None && focus == ctx->currentFadeWindow ) - { - g_HeldCommits[ HELD_COMMIT_FADE ] = nullptr; - g_bPendingFade = false; - fadeOutStartTime = 0; - ctx->currentFadeWindow = nullptr; - } - } - } - - hasRepaint = true; - /* Some games (e.g. DOOM Eternal) don't react well to being put back as * iconic, so never do that. Only take them out of iconic. */ uint32_t wmState[] = { ICCCM_NORMAL_STATE, None }; @@ -2070,9 +1983,6 @@ found: sprintf( buf, "xwininfo -id 0x%lx; xprop -id 0x%lx; xwininfo -root -tree", focus->id, focus->id ); system( buf ); } - - if ( !focus->isSteamStreamingClient ) - get_window_last_done_commit( focus, g_HeldCommits[ HELD_COMMIT_BASE ] ); } ctx->currentFocusWindow = focus; @@ -2090,25 +2000,6 @@ found: if ( inputFocus->inputFocusMode ) keyboardFocusWin = override_focus ? override_focus : focus; - if ( inputFocus->surface.wlr != nullptr || keyboardFocusWin->surface.wlr != nullptr ) - { - wlserver_lock(); - - if ( inputFocus->surface.wlr != nullptr ) - { - // Instantly stop pressing left mouse before transitioning to a new window. - // for focus. - // Fixes dropdowns not working. - wlserver_mousebutton( BTN_LEFT, false, 0 ); - wlserver_mousefocus( inputFocus->surface.wlr, ctx->cursor->x(), ctx->cursor->y() ); - } - - if ( keyboardFocusWin->surface.wlr != nullptr ) - wlserver_keyboardfocus( keyboardFocusWin->surface.wlr ); - - wlserver_unlock(); - } - if ( !override_focus || override_focus != keyboardFocusWin ) XSetInputFocus(ctx->dpy, keyboardFocusWin->id, RevertToNone, CurrentTime); @@ -2163,8 +2054,219 @@ found: } XFree(children); +} - sdlwindow_title( w->title ); +static void +determine_and_apply_focus() +{ + gamescope_xwayland_server_t *root_server = wlserver_get_xwayland_server(0); + xwayland_ctx_t *root_ctx = root_server->ctx.get(); + global_focus_t previous_focus = global_focus; + global_focus = global_focus_t{}; + global_focus.cursor = root_ctx->cursor.get(); + + std::vector< unsigned long > focusable_appids; + std::vector< unsigned long > focusable_windows; + + // Determine local context focuses + std::vector< win* > vecPossibleFocusWindows; + { + gamescope_xwayland_server_t *server = NULL; + for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) + { + determine_and_apply_focus(server->ctx.get(), vecPossibleFocusWindows); + } + } + + for ( win *focusable_window : vecPossibleFocusWindows ) + { + unsigned int unAppID = focusable_window->appID; + if ( unAppID != 0 ) + { + unsigned long j; + for( j = 0; j < focusable_appids.size(); j++ ) + { + if ( focusable_appids[ j ] == unAppID ) + { + break; + } + } + if ( j == focusable_appids.size() ) + { + focusable_appids.push_back( unAppID ); + } + } + + // list of [window, appid, pid] triplets + focusable_windows.push_back( focusable_window->id ); + focusable_windows.push_back( focusable_window->appID ); + focusable_windows.push_back( focusable_window->pid ); + } + + XChangeProperty( root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeFocusableAppsAtom, XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)focusable_appids.data(), focusable_appids.size() ); + + XChangeProperty( root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeFocusableWindowsAtom, XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)focusable_windows.data(), focusable_windows.size() ); + + // Determine global primary focus + std::stable_sort( vecPossibleFocusWindows.begin(), vecPossibleFocusWindows.end(), + is_focus_priority_greater ); + + if ( root_ctx->focusControlWindow != None || vecFocuscontrolAppIDs.size() > 0 ) + { + if ( root_ctx->focusControlWindow != None ) + { + if ( root_ctx->currentFocusWindow->id == root_ctx->focusControlWindow ) + { + global_focus.currentFocusWindow = root_ctx->currentFocusWindow; + goto found; + } + } + + for ( auto focusable_appid : vecFocuscontrolAppIDs ) + { + for ( win *focusable_window : vecPossibleFocusWindows ) + { + if ( focusable_window->appID == focusable_appid ) + { + global_focus.currentFocusWindow = focusable_window; + goto found; + } + } + } +found: + gameFocused = true; + } + else if ( vecPossibleFocusWindows.size() > 0 ) + { + global_focus.currentFocusWindow = vecPossibleFocusWindows[ 0 ]; + gameFocused = global_focus.currentFocusWindow->appID != 0; + } + + // Pick override and cursor from the same ctx as our primary focus. + { + gamescope_xwayland_server_t *server = NULL; + for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) + { + if (server->ctx->currentFocusWindow == global_focus.currentFocusWindow) + { + // Cursor source can change if we have an overlay. + global_focus.cursor = server->ctx->cursor.get(); + global_focus.currentOverrideWindow = server->ctx->currentOverrideWindow; + break; + } + } + } + + // Pick overlay/notifications from root ctx + global_focus.currentOverlayWindow = root_ctx->currentOverlayWindow; + global_focus.currentExternalOverlayWindow = root_ctx->currentExternalOverlayWindow; + global_focus.currentNotificationWindow = root_ctx->currentNotificationWindow; + + // Pick inputFocusWindow + if (global_focus.currentOverlayWindow && global_focus.currentOverlayWindow->inputFocusMode) + { + // If we have an overlay, pick our cursor from there instead. + global_focus.cursor = root_ctx->cursor.get(); + global_focus.currentInputFocusWindow = global_focus.currentOverlayWindow; + } + else if (global_focus.currentOverrideWindow) + global_focus.currentInputFocusWindow = global_focus.currentOverrideWindow; + else + global_focus.currentInputFocusWindow = global_focus.currentFocusWindow; + + if ( global_focus.currentInputFocusWindow != previous_focus.currentInputFocusWindow || + global_focus.currentInputFocusMode != previous_focus.currentInputFocusMode ) + { + win *keyboardFocusWin = global_focus.currentInputFocusWindow; + if ( global_focus.currentInputFocusWindow && global_focus.currentInputFocusWindow->inputFocusMode ) + { + keyboardFocusWin = global_focus.currentOverrideWindow + ? global_focus.currentOverrideWindow + : global_focus.currentFocusWindow; + } + + if ( (global_focus.currentInputFocusWindow && global_focus.currentInputFocusWindow->surface.wlr != nullptr) || + (keyboardFocusWin && keyboardFocusWin->surface.wlr != nullptr) ) + { + wlserver_lock(); + if ( global_focus.currentInputFocusWindow && global_focus.currentInputFocusWindow->surface.wlr != nullptr ) + { + // Instantly stop pressing left mouse before transitioning to a new window. + // for focus. + // Fixes dropdowns not working. + wlserver_mousebutton( BTN_LEFT, false, 0 ); + wlserver_mousefocus( global_focus.currentInputFocusWindow->surface.wlr, global_focus.cursor->x(), global_focus.cursor->y() ); + } + + if ( keyboardFocusWin && keyboardFocusWin->surface.wlr != nullptr ) + wlserver_keyboardfocus( keyboardFocusWin->surface.wlr ); + wlserver_unlock(); + } + } + + // Determine if we need to repaints + if (previous_focus.currentOverlayWindow != global_focus.currentOverlayWindow || + previous_focus.currentExternalOverlayWindow != global_focus.currentExternalOverlayWindow || + previous_focus.currentNotificationWindow != global_focus.currentNotificationWindow || + previous_focus.currentFocusWindow != global_focus.currentFocusWindow || + previous_focus.currentOverrideWindow != global_focus.currentOverrideWindow) + { + hasRepaint = true; + } + + // Backchannel to Steam + unsigned long focusedWindow = 0; + unsigned long focusedAppId = 0; + + if ( global_focus.currentFocusWindow ) + { + focusedWindow = global_focus.currentFocusWindow->id; + focusedAppId = global_focus.currentInputFocusWindow->appID; + } + + XChangeProperty( root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeFocusedAppAtom, XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&focusedAppId, focusedAppId != 0 ? 1 : 0 ); + + XChangeProperty( root_ctx->dpy, root_ctx->root, root_ctx->atoms.gamescopeFocusedWindowAtom, XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&focusedWindow, focusedWindow != 0 ? 1 : 0 ); + + // Sort out fading. + if (previous_focus.currentFocusWindow != global_focus.currentFocusWindow) + { + if ( g_FadeOutDuration != 0 && !g_bFirstFrame ) + { + if ( !g_HeldCommits[ HELD_COMMIT_FADE ] ) + { + global_focus.currentFadeWindow = previous_focus.currentFocusWindow; + g_HeldCommits[ HELD_COMMIT_FADE ] = g_HeldCommits[ HELD_COMMIT_BASE ]; + g_bPendingFade = true; + } + else + { + // If we end up fading back to what we were going to fade to, cancel the fade. + if ( global_focus.currentFadeWindow != nullptr && global_focus.currentFocusWindow == global_focus.currentFadeWindow ) + { + g_HeldCommits[ HELD_COMMIT_FADE ] = nullptr; + g_bPendingFade = false; + fadeOutStartTime = 0; + global_focus.currentFadeWindow = nullptr; + } + } + } + } + + // Update last focus commit + if ( global_focus.currentFocusWindow && + previous_focus.currentFocusWindow != global_focus.currentFocusWindow && + !global_focus.currentFocusWindow->isSteamStreamingClient ) + { + get_window_last_done_commit( global_focus.currentFocusWindow, g_HeldCommits[ HELD_COMMIT_BASE ] ); + } + + if ( global_focus.currentFocusWindow ) + sdlwindow_title( global_focus.currentFocusWindow->title ); } static void @@ -2748,10 +2850,9 @@ finish_destroy_win(xwayland_ctx_t *ctx, Window id, bool gone) static void destroy_win(xwayland_ctx_t *ctx, Window id, bool gone, bool fade) { + // Context if (x11_win(ctx->currentFocusWindow) == id && gone) ctx->currentFocusWindow = nullptr; - if (x11_win(ctx->currentFadeWindow) == id && gone) - ctx->currentFadeWindow = nullptr; if (x11_win(ctx->currentInputFocusWindow) == id && gone) ctx->currentInputFocusWindow = nullptr; if (x11_win(ctx->currentOverlayWindow) == id && gone) @@ -2764,6 +2865,21 @@ destroy_win(xwayland_ctx_t *ctx, Window id, bool gone, bool fade) ctx->currentOverrideWindow = nullptr; if (ctx->currentKeyboardFocusWindow == id && gone) ctx->currentKeyboardFocusWindow = None; + + // Global Focus + if (x11_win(global_focus.currentFocusWindow) == id && gone) + global_focus.currentFocusWindow = nullptr; + if (x11_win(global_focus.currentInputFocusWindow) == id && gone) + global_focus.currentInputFocusWindow = nullptr; + if (x11_win(global_focus.currentOverlayWindow) == id && gone) + global_focus.currentOverlayWindow = nullptr; + if (x11_win(global_focus.currentNotificationWindow) == id && gone) + global_focus.currentNotificationWindow = nullptr; + if (x11_win(global_focus.currentOverrideWindow) == id && gone) + global_focus.currentOverrideWindow = nullptr; + if (x11_win(global_focus.currentFadeWindow) == id && gone) + global_focus.currentFadeWindow = nullptr; + focusDirty = true; finish_destroy_win(ctx, id, gone); @@ -3122,7 +3238,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) globalScaleRatio = overscanScaleRatio * zoomScaleRatio; - if (ctx->currentFocusWindow) + if (global_focus.currentFocusWindow) { hasRepaint = true; } @@ -3135,7 +3251,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) globalScaleRatio = overscanScaleRatio * zoomScaleRatio; - if (ctx->currentFocusWindow) + if (global_focus.currentFocusWindow) { hasRepaint = true; } @@ -3161,7 +3277,7 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) } if (ev->atom == XA_WM_NAME || ev->atom == ctx->atoms.netWMNameAtom) { - if (ev->window == x11_win(ctx->currentFocusWindow)) + if (ev->window == x11_win(global_focus.currentFocusWindow)) { win *w = find_win(ctx, ev->window); if (w) { @@ -3360,12 +3476,12 @@ void handle_done_commits( xwayland_ctx_t *ctx ) // If this is an overlay that we're presenting, repaint if ( gameFocused ) { - if ( w == ctx->currentOverlayWindow && w->opacity != TRANSLUCENT ) + if ( w == global_focus.currentOverlayWindow && w->opacity != TRANSLUCENT ) { hasRepaint = true; } - if ( w == ctx->currentNotificationWindow && w->opacity != TRANSLUCENT ) + if ( w == global_focus.currentNotificationWindow && w->opacity != TRANSLUCENT ) { hasRepaint = true; } @@ -3376,7 +3492,7 @@ void handle_done_commits( xwayland_ctx_t *ctx ) hasRepaint = true; } // If this is the main plane, repaint - if ( w == ctx->currentFocusWindow && !w->isSteamStreamingClient ) + if ( w == global_focus.currentFocusWindow && !w->isSteamStreamingClient ) { // TODO: Check for a mangoapp atom in future. // (Needs the win* refactor from the multiple xwayland branch) @@ -3386,12 +3502,12 @@ void handle_done_commits( xwayland_ctx_t *ctx ) hasRepaint = true; } - if ( w == ctx->currentOverrideWindow ) + if ( w == global_focus.currentOverrideWindow ) { hasRepaint = true; } - if ( w->isSteamStreamingClientVideo && ctx->currentFocusWindow && ctx->currentFocusWindow->isSteamStreamingClient ) + if ( w->isSteamStreamingClientVideo && global_focus.currentFocusWindow && global_focus.currentFocusWindow->isSteamStreamingClient ) { if (ctx->currentExternalOverlayWindow != None) mangoapp_update(); @@ -4140,11 +4256,7 @@ steamcompmgr_main(int argc, char **argv) globalScaleRatio = overscanScaleRatio * zoomScaleRatio; - { - gamescope_xwayland_server_t *server = NULL; - for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) - determine_and_apply_focus(server->ctx.get()); - } + determine_and_apply_focus(); if ( readyPipeFD != -1 ) { @@ -4239,13 +4351,9 @@ steamcompmgr_main(int argc, char **argv) if (focusDirty == true) { - { - gamescope_xwayland_server_t *server = NULL; - for (size_t i = 0; (server = wlserver_get_xwayland_server(i)); i++) - determine_and_apply_focus(server->ctx.get()); - } + determine_and_apply_focus(); - hasFocusWindow = root_ctx->currentFocusWindow != None; + hasFocusWindow = global_focus.currentFocusWindow != nullptr; sdlwindow_pushupdate(); } @@ -4298,7 +4406,7 @@ steamcompmgr_main(int argc, char **argv) if ( ( g_bTakeScreenshot == true || hasRepaint == true || is_fading_out() ) && vblank == true ) { - paint_all(root_ctx, root_ctx->cursor.get()); + paint_all(); // Consumed the need to repaint here hasRepaint = false; diff --git a/src/xwayland_ctx.hpp b/src/xwayland_ctx.hpp index 2054362..2d3adfe 100644 --- a/src/xwayland_ctx.hpp +++ b/src/xwayland_ctx.hpp @@ -43,7 +43,6 @@ struct xwayland_ctx_t win *currentExternalOverlayWindow; win *currentNotificationWindow; win *currentOverrideWindow; - win *currentFadeWindow; Window focusControlWindow;