popsUlfr / SDH-PauseGames

Decky Loader Plugin for Steam Deck to Pause and Resume games
GNU General Public License v3.0
76 stars 8 forks source link

Add 'Pause On Overlay' feature #4

Closed therealpaulgg closed 1 year ago

therealpaulgg commented 1 year ago

Adds feature for pause on overlay.

image

therealpaulgg commented 1 year ago

The more I think about it, I prefer thinking of the 'pause on overlay' as an extension of the pause on focus feature and they should be used together. While they technically could be used separately, it would be a little weird in my opinion to have a case where you have all your apps running in the background AND you pause them all on overlay. Making it a sub-option makes more sense to me currently.

Basically when the overlay is open, all apps (aside from stickied ones) should be paused. When it's closed, the only app that should be resumed is the one currently in focus.

I'll make some tweaks and do a bit more testing and see how this works.

therealpaulgg commented 1 year ago

Ok, here's where we're at: image

Made the overlay fully dependent on the focus loss feature, and if focus loss gets turned off so does overlay.

I am having trouble figuring out styling here. There's an indentLevel prop on ToggleField but it seems to do nothing. using a div seems to add padding around the entire element (when I just asked for padding-left).

Any tips?

popsUlfr commented 1 year ago

The more I think about it, I prefer thinking of the 'pause on overlay' as an extension of the pause on focus feature and they should be used together. While they technically could be used separately, it would be a little weird in my opinion to have a case where you have all your apps running in the background AND you pause them all on overlay. Making it a sub-option makes more sense to me currently.

Basically when the overlay is open, all apps (aside from stickied ones) should be paused. When it's closed, the only app that should be resumed is the one currently in focus.

I also have a hard time to find real world useful uses for it as a standalone feature. It's something you would expect as being part of the "Pause on focus loss" feature but it could be annoying in some cases to have it on by default for users (for the reasons a talked about a bit earlier). As an additional option to the "Pause on focus loss" for a more complete pause for everything seems to be the sensible way to go indeed.

I am having trouble figuring out styling here. There's an indentLevel prop on ToggleField but it seems to do nothing. using a div seems to add padding around the entire element (when I just asked for padding-left).

CSS Loader is using an indentation with arrow for sub-options which looks neat: 20230110100520_1 Maybe we could follow that too (https://github.com/suchmememanyskill/SDH-CssLoader)

The sub-options in CSS Loader only appear when the root option is on. For the text maybe it could be something like Also on overlay with a short help text about it in the help panel when no app is running ?

therealpaulgg commented 1 year ago

I figured it would be something sort of like what they did, thanks for the pointer.

Here is how it looks now:

image

The helper text at the bottom does go a bit off the screen now unfortunately but it's possible to scroll down at least with the touch screen. I personally think it's ok but let me know.

popsUlfr commented 1 year ago

So the complete changes on top of the current pull request I'm testing right now look like this:

diff --git a/src/backend.ts b/src/backend.ts
index 662ee26..e1df29d 100644
--- a/src/backend.ts
+++ b/src/backend.ts
@@ -331,6 +331,9 @@ export function setupFocusChangeHandler(): () => void {
       // Have not found any race condition issues with this approach since the key event fires long before focus change
       validKeyEvent = e;
       cancelDebouncedEvent();
+    } else {
+      cancelDebouncedEvent.cancel();
+      validKeyEvent = null;
     }
   };
   const unregisterSystemKeyEvents = () => {
@@ -351,41 +354,13 @@ export function setupFocusChangeHandler(): () => void {
           return;
         lastPid = fce.focusedApp.pid;
         lastAppid = fce.focusedApp.appid;
-        // Only pause if the user has enabled it
-        if (
-          fce.focusedApp.appid === 769 &&
-          fce.focusedApp.strExeName !== "steamwebhelper" &&
-          (await loadSettings()).overlayPause
-        ) {
-          // Key event must be if the user pressed the 'STEAM' button. Don't pause for other buttons
-          if (validKeyEvent?.eKey === 0) {
-            validKeyEvent = null;
-            await Promise.all(
-              (Router.RunningApps as AppOverviewExt[]).map(async (a) => {
-                const appMD = await getAppMetaData(Number(a.appid));
-                // if the sticky pause state is on for this app don't do anything to it
-                if (appMD.sticky_state) {
-                  return a;
-                }
-                appMD.is_paused = await is_paused(appMD.instanceid);
-                // the app is not in focus
-                if (!appMD.is_paused) {
-                  appMD.is_paused = await pause(appMD.instanceid);
-                  appMD.pause_state_callbacks.forEach((cb) =>
-                    cb(appMD.is_paused)
-                  );
-                }
-                return a;
-              })
-            );
-            return;
-          } else {
-            return;
-          }
-        }
-
         if (!(await loadSettings()).autoPause) return;
         // AppID 769 is the Steam Overlay or a non-steam app
+        // Key event must be if the user pressed the 'STEAM' button. Don't pause for other buttons
+        const overlayPause =
+          fce.focusedApp.appid === 769 &&
+          validKeyEvent?.eKey === 0 &&
+          (await loadSettings()).overlayPause;
         if (!fce.focusedApp.appid || fce.focusedApp.appid === 769) {
           const appid = await appid_from_pid(fce.focusedApp.pid);
           if (appid) {
@@ -409,7 +384,7 @@ export function setupFocusChangeHandler(): () => void {
               return a;
             }
             appMD.is_paused = await is_paused(appMD.instanceid);
-            if (appMD.instanceid === fce.focusedApp.pid) {
+            if (!overlayPause && appMD.instanceid === fce.focusedApp.pid) {
               // this is the focused app
               if (appMD.is_paused) {
                 appMD.is_paused = !(await resume(appMD.instanceid));
@@ -418,7 +393,7 @@ export function setupFocusChangeHandler(): () => void {
                 );
               }
             } else {
-              // the app is not in focus
+              // the app is not in focus or the overlay is on
               if (!appMD.is_paused) {
                 appMD.is_paused = await pause(appMD.instanceid);
                 appMD.pause_state_callbacks.forEach((cb) =>
diff --git a/src/index.tsx b/src/index.tsx
index aa4d9b0..e32cfe2 100755
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -138,12 +138,8 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
           onChange={async (state) => {
             const settings = await backend.loadSettings();
             settings.autoPause = state;
-            setAutoPause(state);
-            if (!state) {
-              settings.overlayPause = false;
-              setOverlayPause(false);
-            }
             await backend.saveSettings(settings);
+            setAutoPause(state);
             backend.resetStickyPauseStates();
           }}
         />
@@ -171,7 +167,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
           </PanelSectionRow>
         ))
       ) : (
-        <div>
+        <div style={{ fontSize: "80%" }}>
           <strong>
             <em>- Pause before Suspend</em>
           </strong>
popsUlfr commented 1 year ago

It works well. One thing to keep in mind is that using the "Exit game" feature from the overlay will most likely end up force killing the application instead of sending SIGTERM which would have done proper saving and cleanup for the application if it was designed to do that.

popsUlfr commented 1 year ago

@therealpaulgg Could you squash your commits together into one and force push if it all looks good to you ? Thanks.

EDIT: yikes... latest Steam Beta killed decky again.

therealpaulgg commented 1 year ago

Ok I squashed the commits. I'll be able to test a bit later today if needed.

Noted on steam beta, I'm on normal release so hope it should be ok?

popsUlfr commented 1 year ago

Ok I squashed the commits. I'll be able to test a bit later today if needed.

Noted on steam beta, I'm on normal release so hope it should be ok?

Thank you so much! I've also updated the dependencies and applied the upstream changes. Also using the Marquee component for game titles that are too long to fit to scroll with an animation.

Steam Client Stable still works with decky but Steam Client Beta has changed a bunch of stuff that have killed decky for now.