Skip to content

Commit

Permalink
Added watcher improvements for KDE to detect best environment to copy
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim-Luca Lagmöller committed May 14, 2022
1 parent 993f55b commit b035a8a
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 27 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.3
1.0.4
8 changes: 2 additions & 6 deletions rescreen/lib/watcher_service/service_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,15 @@ def run(self) -> None:
logger.exception("Not authorized to change linux environment")
sys.exit(126)

app = QApplication()
logger.info(f"Service Worker started for XSession {self.__environment_vars['DISPLAY']}")
logger.debug(f"User Data: {self.__user_data}")
logger.debug(f"Environment: {self.__environment_vars}")

listener = XEventWatcher()
listener.daemon = True
listener.add_connection_event_callback(self.load_current_profile)
self.load_current_profile()
listener.start()

listener.join()
app.exec_()

@staticmethod
def load_current_profile():
Expand All @@ -70,8 +68,6 @@ def load_current_profile():
configuration = ConfigurationManager().load_configuration(current_configuration)

try:
application = QApplication()
configuration.apply(prompt)
application.exit()
except Exception:
logger.exception("Failed to apply configuration")
90 changes: 70 additions & 20 deletions rescreen/lib/watcher_service/watcher_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
import enum
import multiprocessing
import pwd
import sys
import time
import dataclasses
from pathlib import Path
from typing import Dict

from typing import Dict, Tuple
from queue import PriorityQueue
from loguru import logger

from rescreen.lib.watcher_service.service_worker import ServiceWorker


class EnvironmentQuality(int, enum.Enum):
HIGH = 1
MEDIUM = 3
LOW = 5


@dataclasses.dataclass(order=True)
class ComparableEnvironment:
priority: float
environment: Dict[str, str] = dataclasses.field(compare=False)
uid: int = dataclasses.field(compare=False)


class WatcherService:
def __init__(self, session_detection_interval=5):
self.session_detection_interval = session_detection_interval
Expand All @@ -18,7 +33,8 @@ def __init__(self, session_detection_interval=5):
self.__stop = False

def __update_service_workers(self):
maybe_working = []
envs_per_session: Dict[str, PriorityQueue[ComparableEnvironment]] = {}

for path in Path("/proc").iterdir():
if not path.is_dir():
continue
Expand All @@ -28,6 +44,13 @@ def __update_service_workers(self):
if not environ_file.is_file():
continue

cmdline = None
cmdline_file = path / "cmdline"

if cmdline_file.is_file():
with open(cmdline_file, "r", encoding="utf-8") as f:
cmdline = f.readline().strip()

uid = environ_file.stat().st_uid

if uid < 1000:
Expand All @@ -53,35 +76,62 @@ def __update_service_workers(self):
if "DISPLAY" not in environment_vars:
continue

env_score = 1 / len(environment_vars)

display = environment_vars["DISPLAY"]

envs_per_session.setdefault(display, PriorityQueue())

if "XAUTHORITY" not in environment_vars:
maybe_working.append((environment_vars, uid))
envs_per_session[display].put(
ComparableEnvironment(
priority=EnvironmentQuality.LOW.value + env_score,
environment=environment_vars,
uid=uid
)
)
continue

if not self._add_service_worker(uid, environment_vars):
# Basic Requirements for Service Worker environment should be fulfilled here

if cmdline in ["/usr/bin/kded5"]:
envs_per_session[display].put(
ComparableEnvironment(
priority=EnvironmentQuality.HIGH.value + env_score,
environment=environment_vars,
uid=uid
)
)
continue

envs_per_session[display].put(
ComparableEnvironment(
priority=EnvironmentQuality.MEDIUM.value + env_score,
environment=environment_vars,
uid=uid
)
)

except (OSError, PermissionError):
logger.exception("Permission error while trying to access process files")
sys.exit(126)

for environment_vars, uid in maybe_working:
if not self._add_service_worker(uid, environment_vars):
for display, queue in envs_per_session.items():
if display in self.__service_workers.keys():
continue

def _add_service_worker(self, uid: int, environment_vars: Dict[str, str]) -> bool:
display = environment_vars["DISPLAY"]

if display in self.__service_workers.keys():
return False
while not queue.empty():
item = queue.get()

try:
user_data = pwd.getpwuid(uid)
except KeyError:
return False
try:
user_data = pwd.getpwuid(item.uid)
except KeyError:
continue

service_worker = ServiceWorker(user_data, environment_vars)
service_worker.start()
self.__service_workers[display] = service_worker
return True
service_worker = ServiceWorker(user_data, item.environment)
service_worker.start()
self.__service_workers[display] = service_worker
break

def start(self):
self.__stop = False
Expand Down

0 comments on commit b035a8a

Please sign in to comment.