feat: task manager from qam#1121
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR adds a new TOOLS tab to QuickMenu to list and terminate Wine processes, extends QuickMenu's public signature to accept a WinHandler and process state, implements polling in XServerScreen to fetch/sort process snapshots, enriches ProcessInfo with RSS bytes, and adds localized strings. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant XServer as XServerScreen
participant Quick as QuickMenu
participant Row as QuickMenuProcessRow
participant Win as WinHandler
participant Proc as ProcessHelper
User->>XServer: Open QuickMenu -> select TOOLS
XServer->>XServer: quickMenuToolsVisible = true
loop while TOOLS visible
XServer->>Win: request wine process list
Win->>Proc: listProcesses() / parse ps (rss)
Proc-->>Win: ProcessInfo[]
Win-->>XServer: snapshot
XServer->>XServer: sort processes (essentiality, rss)
XServer->>Quick: render TOOLS with wineProcesses
Quick->>Row: render each process row
User->>Row: click / keypress to end process
Row->>Win: killProcess(name, pid)
XServer->>XServer: delay (poll interval)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
app/src/main/java/app/gamenative/ui/component/QuickMenu.kt (2)
585-585: Optional: Hoist scroll state toQuickMenufor consistency.The
scrollStateis defined locally here, whereas other tabs (hudScrollState,effectsScrollState,controllerScrollState) have their scroll states defined at theQuickMenulevel. This means the TOOLS tab loses scroll position when switching tabs.Given the 2-second refresh interval for the process list, this may be acceptable, but hoisting the state would provide consistency.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt` at line 585, Move the local val scrollState = rememberScrollState() up into the QuickMenu composable alongside hudScrollState, effectsScrollState and controllerScrollState so the TOOLS tab preserves its scroll position; then replace the local declaration in the TOOLS tab with a reference to that hoisted scrollState (or pass it into the TOOLS tab child composable) so all tabs use scroll state defined at QuickMenu level for consistent behavior.
614-617: Consider adding a confirmation step before killing processes.Tapping a row immediately kills the process without confirmation. While this provides quick access, accidental taps could terminate important processes. Consider either:
- A brief toast/snackbar with undo capability, or
- A confirmation dialog for processes that aren't marked as safe to kill.
This is optional given the "tap to close" design intent mentioned in the PR.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt` around lines 614 - 617, The quick-tap handler in QuickMenu.kt currently calls winHandler?.killProcess(process.name, process.pid) directly in the onEndProcess lambda; update this to present a confirmation UI (either a confirmation dialog for non-safe processes or a brief snackbar with an undo for quick closes) before calling winHandler?.killProcess. Specifically, change the onEndProcess flow to check a process safety flag (e.g., process.safeToKill or process.isCritical) and if not safe show a confirmation dialog and only call killProcess on confirm, or for quick-close show a snackbar that delays the actual call and cancels it if the user taps undo; ensure the final kill call still uses winHandler?.killProcess(process.name, process.pid).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt`:
- Around line 245-284: The current code in requestWineProcessSnapshot replaces
WinHandler's single OnGetProcessInfoListener and can race with
startExitWatchForUnmappedGameWindow which does the same; instead, create a
single shared dispatcher/listener in this class (e.g., a private val
processInfoDispatcher: OnGetProcessInfoListener or a small manager object) that
you register once via
winHandler.setOnGetProcessInfoListener(processInfoDispatcher) and have that
dispatcher multiplex events to callers. Change requestWineProcessSnapshot to
enqueue a CompletableDeferred and expectedCount into the dispatcher (keyed by a
request token or by storing the deferred + logic in a list) rather than calling
setOnGetProcessInfoListener, and update startExitWatchForUnmappedGameWindow to
use the same dispatcher for its callbacks; ensure the finally blocks only
unregister the dispatcher when no pending consumers remain and synchronize
access with a mutex to serialize ownership.
In `@app/src/main/res/values-fr/strings.xml`:
- Line 252: Replace the awkward French phrasing in the string resource
tools_wine_processes_running_hint: change the text "%1$d en cours,
touchez/cliquez sur un processus pour le fermer" to a natural French sentence
that includes the noun "processus", for example "%1$d processus en cours,
touchez ou cliquez sur un processus pour le fermer" (or "%1$d processus en
cours, appuyez ou cliquez sur un processus pour le fermer") so the UI copy reads
naturally.
---
Nitpick comments:
In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt`:
- Line 585: Move the local val scrollState = rememberScrollState() up into the
QuickMenu composable alongside hudScrollState, effectsScrollState and
controllerScrollState so the TOOLS tab preserves its scroll position; then
replace the local declaration in the TOOLS tab with a reference to that hoisted
scrollState (or pass it into the TOOLS tab child composable) so all tabs use
scroll state defined at QuickMenu level for consistent behavior.
- Around line 614-617: The quick-tap handler in QuickMenu.kt currently calls
winHandler?.killProcess(process.name, process.pid) directly in the onEndProcess
lambda; update this to present a confirmation UI (either a confirmation dialog
for non-safe processes or a brief snackbar with an undo for quick closes) before
calling winHandler?.killProcess. Specifically, change the onEndProcess flow to
check a process safety flag (e.g., process.safeToKill or process.isCritical) and
if not safe show a confirmation dialog and only call killProcess on confirm, or
for quick-close show a snackbar that delays the actual call and cancels it if
the user taps undo; ensure the final kill call still uses
winHandler?.killProcess(process.name, process.pid).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1c14806e-e3b7-43a5-bac7-75b53e23e6b9
📒 Files selected for processing (17)
app/src/main/java/app/gamenative/ui/component/QuickMenu.ktapp/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.ktapp/src/main/java/com/winlator/core/ProcessHelper.javaapp/src/main/res/values-da/strings.xmlapp/src/main/res/values-de/strings.xmlapp/src/main/res/values-es/strings.xmlapp/src/main/res/values-fr/strings.xmlapp/src/main/res/values-it/strings.xmlapp/src/main/res/values-ko/strings.xmlapp/src/main/res/values-pl/strings.xmlapp/src/main/res/values-pt-rBR/strings.xmlapp/src/main/res/values-ro/strings.xmlapp/src/main/res/values-ru/strings.xmlapp/src/main/res/values-uk/strings.xmlapp/src/main/res/values-zh-rCN/strings.xmlapp/src/main/res/values-zh-rTW/strings.xmlapp/src/main/res/values/strings.xml
There was a problem hiding this comment.
3 issues found across 17 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/src/main/res/values-ru/strings.xml">
<violation number="1" location="app/src/main/res/values-ru/strings.xml:1168">
P2: Russian count-based hint uses a single fixed phrase, causing grammatically incorrect text for many numeric values.</violation>
</file>
<file name="app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt">
<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt:277">
P1: Quick-menu process polling races with exit-watch by overwriting the single global WinHandler process listener, which can mix callbacks and corrupt process snapshots.</violation>
</file>
<file name="app/src/main/java/com/winlator/core/ProcessHelper.java">
<violation number="1" location="app/src/main/java/com/winlator/core/ProcessHelper.java:138">
P2: New RSS parsing from `ps` output is unchecked; malformed output can throw `NumberFormatException` and break subprocess listing flow.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| } | ||
|
|
||
| return try { | ||
| winHandler.setOnGetProcessInfoListener(listener) |
There was a problem hiding this comment.
P1: Quick-menu process polling races with exit-watch by overwriting the single global WinHandler process listener, which can mix callbacks and corrupt process snapshots.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt, line 277:
<comment>Quick-menu process polling races with exit-watch by overwriting the single global WinHandler process listener, which can mix callbacks and corrupt process snapshots.</comment>
<file context>
@@ -241,6 +242,48 @@ private fun buildEssentialProcessAllowlist(): Set<String> {
+ }
+
+ return try {
+ winHandler.setOnGetProcessInfoListener(listener)
+ winHandler.listProcesses()
+ withTimeoutOrNull(EXIT_PROCESS_RESPONSE_TIMEOUT_MS) {
</file context>
| <string name="tab_local">Пользовательское</string> | ||
| <string name="tab_steam">Steam</string> | ||
| <string name="task_manager">Менеджер задач</string> | ||
| <string name="tools_wine_processes_running_hint">%1$d запущено, нажмите/кликните по процессу, чтобы закрыть его</string> |
There was a problem hiding this comment.
P2: Russian count-based hint uses a single fixed phrase, causing grammatically incorrect text for many numeric values.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/res/values-ru/strings.xml, line 1168:
<comment>Russian count-based hint uses a single fixed phrase, causing grammatically incorrect text for many numeric values.</comment>
<file context>
@@ -1165,6 +1165,7 @@ https://gamenative.app
<string name="tab_local">Пользовательское</string>
<string name="tab_steam">Steam</string>
<string name="task_manager">Менеджер задач</string>
+ <string name="tools_wine_processes_running_hint">%1$d запущено, нажмите/кликните по процессу, чтобы закрыть его</string>
<string name="template_percent">%1$d процент.</string>
<string name="thumbstick_buttons">Кнопки джойстика</string>
</file context>
| String user = parts[0]; | ||
| int pid = Integer.parseInt(parts[1]); | ||
| int ppid = Integer.parseInt(parts[2]); | ||
| long rssKb = Long.parseLong(parts[4]); |
There was a problem hiding this comment.
P2: New RSS parsing from ps output is unchecked; malformed output can throw NumberFormatException and break subprocess listing flow.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/java/com/winlator/core/ProcessHelper.java, line 138:
<comment>New RSS parsing from `ps` output is unchecked; malformed output can throw `NumberFormatException` and break subprocess listing flow.</comment>
<file context>
@@ -111,59 +117,29 @@ public static int exec(String command, String[] envp, File workingDir, Callback<
String user = parts[0];
int pid = Integer.parseInt(parts[1]);
int ppid = Integer.parseInt(parts[2]);
+ long rssKb = Long.parseLong(parts[4]);
String processName = parts[8];
</file context>
| // First get our username using the id command | ||
| try { | ||
| java.lang.Process idProcess = Runtime.getRuntime().exec("id"); | ||
| try ( | ||
| InputStreamReader isr = new InputStreamReader(idProcess.getInputStream()); | ||
| BufferedReader idReader = new BufferedReader(isr); | ||
| ) { | ||
| String idOutput = idReader.readLine(); | ||
| if (idOutput != null) { | ||
| // id output format: uid=10290(u0_a290) gid=10290(u0_a290) ... | ||
| int startIndex = idOutput.indexOf('('); | ||
| int endIndex = idOutput.indexOf(')'); | ||
| if (startIndex != -1 && endIndex != -1) { | ||
| myUser = idOutput.substring(startIndex + 1, endIndex); | ||
| } | ||
| } | ||
| } | ||
| } catch (IOException e) { | ||
| Log.e("ProcessHelper", "Failed to retrieve user id in order to list processes: " + e); | ||
| return processes; | ||
| } | ||
|
|
||
| if (myUser == null) { | ||
| return processes; | ||
| } | ||
|
|
||
| // Log.d("ProcessHelper", "Found user value to be: " + myUser); | ||
|
|
||
| // Now get the processes |
There was a problem hiding this comment.
concerning that this was removed - this function is used in other places
There was a problem hiding this comment.
or was it just moved to getCurrentProcessUser - if so, why? i don't see the function being used anywhere else so if it's not required please undo. As far as i know this file shouldn't need any changes
There was a problem hiding this comment.
yeah was moved to a helper but prob not necessary here. There was one change to add rssBytes in processInfo and changes to ps parsing, so we can get per proc memory usage. will put it back where it was so diff is more obvious
Description
adds a new view to quick menu that lets you see a list of running procs, and quickly kill them if needed.
Recording
Checklist
#code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.CONTRIBUTING.md.Summary by cubic
Adds a Task Manager tab in the Quick Menu that lists running Wine EXEs with memory usage and lets you end processes without leaving the game. The list auto-refreshes while the tab is open and prioritizes non‑essential apps.
New Features
QuickMenuwith a live “Running EXEs” list (updates every 2s), shows non‑essential apps first, and lets you tap/click to end a process viaWinHandler(WOW64 marked “*32”); includes memory per process and an empty state.Refactors
ProcessHelpernow inlines process user lookup and parsespsRSS to provide per‑process memory in bytes.Written for commit 44720d8. Summary will update on new commits.
Summary by CodeRabbit