|
@@ -10,6 +10,9 @@ package eu.mjdev.desktop.managers.processes
|
|
|
|
|
|
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.DisposableEffect
|
|
import androidx.compose.runtime.DisposableEffect
|
|
|
|
|
+import androidx.compose.runtime.mutableStateListOf
|
|
|
|
|
+import androidx.compose.runtime.remember
|
|
|
|
|
+import androidx.compose.runtime.snapshots.SnapshotStateList
|
|
|
import eu.mjdev.desktop.data.App
|
|
import eu.mjdev.desktop.data.App
|
|
|
import eu.mjdev.desktop.extensions.Custom.orElse
|
|
import eu.mjdev.desktop.extensions.Custom.orElse
|
|
|
import eu.mjdev.desktop.provider.DesktopProvider
|
|
import eu.mjdev.desktop.provider.DesktopProvider
|
|
@@ -17,22 +20,25 @@ import eu.mjdev.desktop.provider.DesktopProvider.Companion.LocalDesktop
|
|
|
import kotlinx.coroutines.*
|
|
import kotlinx.coroutines.*
|
|
|
import kotlin.jvm.optionals.getOrNull
|
|
import kotlin.jvm.optionals.getOrNull
|
|
|
|
|
|
|
|
|
|
+// todo dbus
|
|
|
@Suppress("unused")
|
|
@Suppress("unused")
|
|
|
class ProcessManager(
|
|
class ProcessManager(
|
|
|
- val delay: Long = 1000L
|
|
|
|
|
-) : ArrayList<ProcessManager.ProcessWrapper>(), AutoCloseable {
|
|
|
|
|
|
|
+ private val checkDelay: Long = 1000L
|
|
|
|
|
+) : AutoCloseable {
|
|
|
|
|
+ val size: Int get() = processes.size
|
|
|
private val scope = CoroutineScope(Dispatchers.IO)
|
|
private val scope = CoroutineScope(Dispatchers.IO)
|
|
|
private val listeners = mutableListOf<ProcessListener>()
|
|
private val listeners = mutableListOf<ProcessListener>()
|
|
|
private var job: Job? = null
|
|
private var job: Job? = null
|
|
|
|
|
+ private val processes = mutableStateListOf<ProcessWrapper>()
|
|
|
|
|
|
|
|
init {
|
|
init {
|
|
|
job = scope.launch(Dispatchers.IO) {
|
|
job = scope.launch(Dispatchers.IO) {
|
|
|
while (isActive) {
|
|
while (isActive) {
|
|
|
ProcessHandle.allProcesses().toList().filterNotNull().let { phList ->
|
|
ProcessHandle.allProcesses().toList().filterNotNull().let { phList ->
|
|
|
phList.forEach { ph ->
|
|
phList.forEach { ph ->
|
|
|
- if (!containsProcess(ph)) {
|
|
|
|
|
|
|
+ if (!processes.containsProcess(ph)) {
|
|
|
ProcessWrapper(ph).also { pw ->
|
|
ProcessWrapper(ph).also { pw ->
|
|
|
- add(pw)
|
|
|
|
|
|
|
+ processes.add(pw)
|
|
|
}
|
|
}
|
|
|
listeners.filterIsInstance<ProcessAddListener>().forEach { l ->
|
|
listeners.filterIsInstance<ProcessAddListener>().forEach { l ->
|
|
|
l.onProcessAdded(ph)
|
|
l.onProcessAdded(ph)
|
|
@@ -41,13 +47,13 @@ class ProcessManager(
|
|
|
}
|
|
}
|
|
|
cleanup()
|
|
cleanup()
|
|
|
}
|
|
}
|
|
|
- delay(delay)
|
|
|
|
|
|
|
+ delay(checkDelay)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private fun cleanup() {
|
|
private fun cleanup() {
|
|
|
- iterator().apply {
|
|
|
|
|
|
|
+ processes.iterator().apply {
|
|
|
while (hasNext()) {
|
|
while (hasNext()) {
|
|
|
val pw = next()
|
|
val pw = next()
|
|
|
if (pw.processHandle?.isAlive != true) {
|
|
if (pw.processHandle?.isAlive != true) {
|
|
@@ -58,22 +64,13 @@ class ProcessManager(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fun addOnAddListener(listener: ProcessAddListener) {
|
|
|
|
|
|
|
+ fun addListener(listener: ProcessListener) {
|
|
|
listeners.add(listener)
|
|
listeners.add(listener)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fun addOnRemoveListener(listener: ProcessRemoveListener) {
|
|
|
|
|
- listeners.add(listener)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- fun removeOnAddListener(listener: ProcessAddListener) {
|
|
|
|
|
- listeners.remove(listener)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- fun removeOnRemoveListener(listener: ProcessRemoveListener) {
|
|
|
|
|
|
|
+ fun removeListener(listener: ProcessListener) {
|
|
|
listeners.remove(listener)
|
|
listeners.remove(listener)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -86,7 +83,7 @@ class ProcessManager(
|
|
|
val appCmd = app?.cmd
|
|
val appCmd = app?.cmd
|
|
|
val appName = app?.name
|
|
val appName = app?.name
|
|
|
val appFullName = app?.fullAppName
|
|
val appFullName = app?.fullAppName
|
|
|
- any { pw ->
|
|
|
|
|
|
|
+ processes.any { pw ->
|
|
|
(appName != null && pw.command.contains(appName)) ||
|
|
(appName != null && pw.command.contains(appName)) ||
|
|
|
(appCmd != null && pw.command.contains(appCmd)) ||
|
|
(appCmd != null && pw.command.contains(appCmd)) ||
|
|
|
(appFullName != null && pw.command.contains(appFullName)) ||
|
|
(appFullName != null && pw.command.contains(appFullName)) ||
|
|
@@ -98,15 +95,24 @@ class ProcessManager(
|
|
|
}.getOrNull() ?: false
|
|
}.getOrNull() ?: false
|
|
|
|
|
|
|
|
companion object {
|
|
companion object {
|
|
|
- fun ArrayList<ProcessWrapper>.containsProcess(ph: ProcessHandle) = ph.pid().let { pid ->
|
|
|
|
|
|
|
+ fun SnapshotStateList<ProcessWrapper>.containsProcess(
|
|
|
|
|
+ ph: ProcessHandle
|
|
|
|
|
+ ) = ph.pid().let { pid ->
|
|
|
any { p -> p.pid == pid }
|
|
any { p -> p.pid == pid }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- fun ArrayList<ProcessWrapper>.containsProcess(ph: ProcessWrapper) = any { p -> p.pid == ph.pid }
|
|
|
|
|
|
|
+ fun SnapshotStateList<ProcessWrapper>.containsProcess(
|
|
|
|
|
+ ph: ProcessWrapper
|
|
|
|
|
+ ) = any { p -> p.pid == ph.pid }
|
|
|
|
|
+
|
|
|
|
|
+ @Composable
|
|
|
|
|
+ fun rememberProcessManager(
|
|
|
|
|
+ checkDelay: Long = 1000L
|
|
|
|
|
+ ) = remember { ProcessManager(checkDelay) }
|
|
|
|
|
|
|
|
@Composable
|
|
@Composable
|
|
|
fun processManagerListener(
|
|
fun processManagerListener(
|
|
|
- onChanged: ProcessManager.(processHandle: ProcessHandle?) -> Unit,
|
|
|
|
|
|
|
+ onChanged: ProcessManager.(processHandle: ProcessHandle?) -> Unit = {},
|
|
|
) = processManagerListener(onChanged, onChanged)
|
|
) = processManagerListener(onChanged, onChanged)
|
|
|
|
|
|
|
|
@Composable
|
|
@Composable
|
|
@@ -115,7 +121,7 @@ class ProcessManager(
|
|
|
onRemove: ProcessManager.(processHandle: ProcessHandle?) -> Unit,
|
|
onRemove: ProcessManager.(processHandle: ProcessHandle?) -> Unit,
|
|
|
api: DesktopProvider = LocalDesktop.current,
|
|
api: DesktopProvider = LocalDesktop.current,
|
|
|
processManger: ProcessManager = api.processManager
|
|
processManger: ProcessManager = api.processManager
|
|
|
- ) {
|
|
|
|
|
|
|
+ ): ProcessManager {
|
|
|
val addListener = object : ProcessAddListener {
|
|
val addListener = object : ProcessAddListener {
|
|
|
override fun onProcessAdded(processHandle: ProcessHandle?) {
|
|
override fun onProcessAdded(processHandle: ProcessHandle?) {
|
|
|
onAdd.invoke(processManger, processHandle)
|
|
onAdd.invoke(processManger, processHandle)
|
|
@@ -127,13 +133,14 @@ class ProcessManager(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
DisposableEffect(Unit) {
|
|
DisposableEffect(Unit) {
|
|
|
- processManger.addOnAddListener(addListener)
|
|
|
|
|
- processManger.addOnRemoveListener(removeListener)
|
|
|
|
|
|
|
+ processManger.addListener(addListener)
|
|
|
|
|
+ processManger.addListener(removeListener)
|
|
|
onDispose {
|
|
onDispose {
|
|
|
- processManger.removeOnAddListener(addListener)
|
|
|
|
|
- processManger.removeOnRemoveListener(removeListener)
|
|
|
|
|
|
|
+ processManger.removeListener(addListener)
|
|
|
|
|
+ processManger.removeListener(removeListener)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ return processManger
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|