From ee1c2416f27894ab1edfead6a6e9ff5ac2604eec Mon Sep 17 00:00:00 2001 From: Zhang Yueqian Date: Tue, 1 Nov 2022 19:10:01 +0800 Subject: [PATCH] Initial commit --- .gitignore | 1 + .vscode/settings.json | 12 +++ backend/50-medr-dpms.conf | 5 ++ backend/medr-lightdm-dpms-disable | 22 +++++ backend/medr-lightdm-dpms-enable | 51 ++++++++++++ backend/medr-screensaver-backend.py | 123 ++++++++++++++++++++++++++++ command/medr-screensaver-command.py | 23 ++++++ dialog/medr-screensaver-dialog.py | 113 +++++++++++++++++++++++++ 8 files changed, 350 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 backend/50-medr-dpms.conf create mode 100755 backend/medr-lightdm-dpms-disable create mode 100755 backend/medr-lightdm-dpms-enable create mode 100755 backend/medr-screensaver-backend.py create mode 100644 command/medr-screensaver-command.py create mode 100755 dialog/medr-screensaver-dialog.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f21b54 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/venv/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bf859b9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "python.formatting.provider": "black", + "python.formatting.blackPath": "/home/zos/ohos_env/bin/black", + "syncmate.dest": "/home/antiy/", + "syncmate.enabled": true, + "syncmate.user": "antiy", + "syncmate.verbose": true, + "syncmate.host": "localhost:10022", + "sync-rsync.onSaveIndividual": true, + "sync-rsync.remote": "antiy@localhost:/home/antiy/", + "sync-rsync.shell": "ssh -p 10022" +} diff --git a/backend/50-medr-dpms.conf b/backend/50-medr-dpms.conf new file mode 100644 index 0000000..0e7187c --- /dev/null +++ b/backend/50-medr-dpms.conf @@ -0,0 +1,5 @@ +# 本文件需安装在 /etc/lightdm/lightdm.conf.d/ 目录下 + +[SeatDefaults] +display-setup-script=/usr/local/bin/medr-lightdm-dpms-enable +session-setup-script=/usr/local/bin/medr-lightdm-dpms-disable diff --git a/backend/medr-lightdm-dpms-disable b/backend/medr-lightdm-dpms-disable new file mode 100755 index 0000000..c7c4968 --- /dev/null +++ b/backend/medr-lightdm-dpms-disable @@ -0,0 +1,22 @@ +#!/bin/bash +### +# @Author: Zhang Yueqian zhangyueqian@antiy.cn +# @Date: 2022-11-01 10:24:40 +# @LastEditors: Zhang Yueqian zhangyueqian@antiy.cn +# @LastEditTime: 2022-11-01 10:28:04 +# @FilePath: /screensaver/backend/medr-lightdm-dpms-disable +# @Description: 在lightdm(greeter)登陆之后禁用屏幕休眠功能 +# +# 本程序需安装在 /usr/local/bin/ 目录下, 配置到 /etc/lightdm/50-medr-dpms.conf 文件中 +### + +# 入口函数, 调用xset +function main() { + # 等待X启动(大概?) + sleep 10 + + # 将超时配置设为0(禁用) + xset dpms 0 0 0 +} + +main & diff --git a/backend/medr-lightdm-dpms-enable b/backend/medr-lightdm-dpms-enable new file mode 100755 index 0000000..5af8f87 --- /dev/null +++ b/backend/medr-lightdm-dpms-enable @@ -0,0 +1,51 @@ +#!/bin/bash +### +# @Author: Zhang Yueqian zhangyueqian@antiy.cn +# @Date: 2022-11-01 09:47:56 +# @LastEditors: Zhang Yueqian zhangyueqian@antiy.cn +# @LastEditTime: 2022-11-01 13:45:07 +# @FilePath: /screensaver/backend/medr-lightdm-dpms-enable +# @Description: 在lightdm(greeter)界面启用屏幕休眠功能 +# +# 本程序需安装在 /usr/local/bin/ 目录下, 配置到 /etc/lightdm/50-medr-dpms.conf 文件中 +### + +# 休眠时间设置文件路径 +TIMEOUT_FILE=/var/run/medr-lightdm + +# 默认休眠时间(分钟) +DEFAULT_TIMEOUT=10 +# 确认文件存在 +if [ ! -f $TIMEOUT_FILE ]; then + touch $TIMEOUT_FILE +fi + +# 获取休眠超时配置, 如果未设置或设置格式非数字, 则返回默认配置 $DEFAULT_TIMEOUT +function get_timeout() { + + # 首先保证TIMEOUT文件可被修改 + chmod 777 $TIMEOUT_FILE + + # 读取TIMEOUT内容并确认为数字 + TIMEOUT=$(cat $TIMEOUT_FILE) + + case $TIMEOUT in + '' | *[!0-9]*) echo $DEFAULT_TIMEOUT ;; + *) echo $TIMEOUT ;; + esac +} + +# 入口函数, 读取设置并调用xset +function main() { + # 读取超时配置并转换为秒 + TIMEOUT=$(get_timeout) + TIMEOUT=$((TIMEOUT * 60)) + + # 必须的, 似乎是需要等待X启动 + sleep 10 + + # 利用X的dpms功能触发屏幕休眠 + xset dpms 0 0 $TIMEOUT +} + +main & diff --git a/backend/medr-screensaver-backend.py b/backend/medr-screensaver-backend.py new file mode 100755 index 0000000..37cbfe3 --- /dev/null +++ b/backend/medr-screensaver-backend.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +""" +Author: Zhang Yueqian zhangyueqian@antiy.cn +Date: 2022-10-31 11:20:48 +LastEditors: Zhang Yueqian zhangyueqian@antiy.cn +LastEditTime: 2022-10-31 11:34:00 +FilePath: /screensaver/backend/medr-screensaver-backend.py +Description: 屏保程序 for MEDR项目. 本文件为后台监控的部分. + +原理: 主要负责实现两部分功能 +1. 通过dbus方法提供开始菜单中的锁屏功能 +2. 通过监听org.gnome.SessionManager.Presence的StatusChanged信号完成自动锁屏功能 +以上两种锁屏通过调用 medr-screensaver-command 来实现, 提供不同的参数 `--session-idle` 和 `--lock` + +另外: 对于锁屏情况下的黑屏时长, 需要控制lightdm配置实现, 参考 +https://askubuntu.com/questions/403859/how-to-control-lightdm-power-saving-preferences +利用额外的文件 /var/run/medr-lightdm 来设置 +""" + +from datetime import datetime +import threading +from time import sleep +import dbus +import dbus.service +import dbus.glib +import os + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import GObject, Gio + + +BUS_NAME = "org.ukui.ScreenSaver" +TIMEOUT_FILE = "/var/run/medr-lightdm" +DEFAULT_TIMEOUT = 10 + + +class Service(dbus.service.Object): + """锁屏dbus服务""" + + def __init__(self, bus_name, obj_path): + """使用bus_name和obj_path初始化dbus服务 + + Args: + bus_name (dbus.service.BusName): 要注册的bus名 + obj_path (str): 要注册的路径 + """ + dbus.service.Object.__init__(self, bus_name, obj_path) + self._locked = False + + @dbus.service.method(BUS_NAME, in_signature="", out_signature="b") + def GetLockState(self): + print(" sending out lockstate: ", self._state) + return self._state + + @dbus.service.method(BUS_NAME, in_signature="b", out_signature="") + def SetLockState(self, state): + print(" got lock state:", state) + self._state = state + + @dbus.service.method(BUS_NAME, in_signature="", out_signature="") + def Lock(self): + print(" lock command called!") + os.system("ukui-screensaver-dialog --lock") + + @dbus.service.method(BUS_NAME, in_signature="", out_signature="") + def Quit(self): + print(" got quit request.") + self._loop.quit() + + @dbus.service.signal(BUS_NAME) + def SessionIdle(self): + print(" signal triggered") + os.system("wall session idle triggerd!") + os.system("ukui-screensaver-dialog --session-idle") + + +loop = GObject.MainLoop() +bus = dbus.SessionBus() +bus_name = dbus.service.BusName(BUS_NAME, bus=bus) +service = Service(bus_name, "/") + + +def sessionStatusChanged(sessionStatus): + print("---- Caught signal ----") + + if sessionStatus == 3: + service.SessionIdle() + + print("\n") + + +def checkSessionIdle(): + """检查gsettings中配置的会话闲置时间并写入到配置文件 TIMEOUT_FILE 中""" + while True: + mate_session = Gio.Settings("org.mate.session") + sys_timeout = mate_session.get_value("idle-delay").get_int32() + + with open(TIMEOUT_FILE, "r") as fp: + try: + medr_timeout = int(fp.read()) + except ValueError: + medr_timeout = DEFAULT_TIMEOUT + + if medr_timeout != sys_timeout: + with open(TIMEOUT_FILE, "w") as fp: + fp.write("%s" % sys_timeout) + + sleep(5) + + +t = threading.Thread(target=checkSessionIdle) + + +if __name__ == "__main__": + bus.add_signal_receiver( + sessionStatusChanged, dbus_interface="org.gnome.SessionManager.Presence", signal_name="StatusChanged" + ) + # org.gnome.SessionManager.Presence:StatusChanged + t.start() + loop.run() diff --git a/command/medr-screensaver-command.py b/command/medr-screensaver-command.py new file mode 100644 index 0000000..b9df635 --- /dev/null +++ b/command/medr-screensaver-command.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +""" +Author: Zhang Yueqian zhangyueqian@antiy.cn +Date: 2022-10-31 11:32:15 +LastEditors: Zhang Yueqian zhangyueqian@antiy.cn +LastEditTime: 2022-10-31 11:38:24 +FilePath: /screensaver/command/medr-screensaver-command.py +Description: 屏保程序 for MEDR项目. 本文件为提供命令行交互功能的部分. +""" + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import GObject, Gio + + +def monitorSessionIdle(): + pass + + +if __name__ == "__main__": + pass diff --git a/dialog/medr-screensaver-dialog.py b/dialog/medr-screensaver-dialog.py new file mode 100755 index 0000000..afa06eb --- /dev/null +++ b/dialog/medr-screensaver-dialog.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +""" +Author: Zhang Yueqian zhangyueqian@antiy.cn +Date: 2022-10-31 11:32:24 +LastEditors: Zhang Yueqian zhangyueqian@antiy.cn +LastEditTime: 2022-10-31 11:34:16 +FilePath: /screensaver/dialog/medr-screensaver-dialog.py +Description: 屏保程序 for MEDR项目. 本文件为负责锁屏的部分. + +提供实际锁屏功能, 支持两个参数: --lock 和 --session-idle +锁屏包括两个含义: 熄灭屏幕 & 触发lightdm锁定 +--lock: 熄灭屏幕并直接锁定lightdm +--session-idle: 首先熄灭屏幕, 然后根据系统设置, 如果系统设置为idle后锁屏则锁屏 +""" + +from argparse import ArgumentParser +from multiprocessing.managers import BaseManager +import os, socket + +MEDR_PIPE = "/tmp/medr-screensaver.sock" +_command = [] + + +def parse_args(): + argparser = ArgumentParser(add_help=False) + + argparser.add_argument("-h", "--help", dest="help", action="store_true", help="Show this message and exit.") + argparser.add_argument("-l", "--lock", dest="lock", action="store_true", help="Locks the screen.") + argparser.add_argument( + "--session-idle", dest="session_idle", action="store_true", help="Activated by session idle signal." + ) + argparser.add_argument( + "--screensaver", + dest="screensaver", + action="store_true", + help="Locks the screen and shows screensaver immediatelly.", + ) + + return argparser.parse_args(), argparser.format_help() + + +def action(args, help): + if args.help: + print(help) + return + + if args.lock: + os.system("dm-tool lock") + return + + if args.session_idle: + # if idle-lock checked, locks + return + + if args.screensaver: + os.system("xset dpms force off") + return + + print(help) + + +def get_command(): + return _command + + +def singleton(): + # 通过client连接已有的BaseManager, 如果失败则自己启动一个, 成功则退出 + BaseManager.register("medr-screensaver") + m = BaseManager(address=("127.0.0.1", 5000), authkey=b"medr-screensaver") + try: + print("Trying connect to %s" % m) + m.connect() + except Exception as e: + print(e) + else: + print("Failed, trying start server") + BaseManager.register("medr-screensaver", callable=get_command) + m = BaseManager(address=("127.0.0.1", 5000), authkey=b"medr-screensaver") + m.start() + + +# 必须先删除 +# try: +# os.unlink(MEDR_PIPE) +# except OSError: +# if os.path.exists(MEDR_PIPE): +# raise + +# 指定协议 +server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +try: + server.bind(MEDR_PIPE) +except socket.error as e: + # running + print("Error: ", e) + print("Running") +finally: + # 监听 + server.listen(1) + +clientsocket, address = server.accept() +# 接收消息 +data = clientsocket.recv(1024) +print(data) +# 关闭socket +clientsocket.close() +server.close() + +if __name__ == "__main__": + args, msg = parse_args() + # singleton() + action(args, msg)