Refac.
This commit is contained in:
parent
8aef536527
commit
359fecb027
8 changed files with 243 additions and 62 deletions
10
laptop-mode.service
Normal file
10
laptop-mode.service
Normal file
|
@ -0,0 +1,10 @@
|
|||
[Unit]
|
||||
Description=Configure system for laptop mode
|
||||
Conflicts=tablet-mode.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/setsysmode laptop
|
||||
StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
129
setsysmode
Executable file
129
setsysmode
Executable file
|
@ -0,0 +1,129 @@
|
|||
#! /usr/bin/env python3
|
||||
"""Sets the system mode."""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from subprocess import DEVNULL, CalledProcessError, check_call, run
|
||||
from sys import stderr
|
||||
|
||||
|
||||
DESCRIPTION = 'Sets or toggles the system mode.'
|
||||
LAPTOP_MODE_SERVICE = 'laptop-mode.service'
|
||||
TABLET_MODE_SERVICE = 'tablet-mode.service'
|
||||
|
||||
|
||||
def get_arguments():
|
||||
"""Returns the CLI arguments."""
|
||||
|
||||
parser = ArgumentParser(description=DESCRIPTION)
|
||||
parser.add_argument(
|
||||
'-n', '--notify', action='store_true',
|
||||
help='display an on-screen notification')
|
||||
subparsers = parser.add_subparsers(dest='mode')
|
||||
subparsers.add_parser('toggle', help='toggles the system mode')
|
||||
subparsers.add_parser('laptop', help='switch to laptop mode')
|
||||
subparsers.add_parser('tablet', help='switch to tablet mode')
|
||||
subparsers.add_parser('default', help='do not disable any input devices')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def systemctl(action, unit, *, root=False):
|
||||
"""Runs systemctl."""
|
||||
|
||||
command = ['/usr/bin/sudo'] if root else []
|
||||
command.append('systemctl')
|
||||
command.append(action)
|
||||
command.append(unit)
|
||||
|
||||
try:
|
||||
check_call(command, stdout=DEVNULL) # Return 0 on success.
|
||||
except CalledProcessError:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def notify_send(summary, body=None):
|
||||
"""Sends the respective message."""
|
||||
|
||||
command = ['/usr/bin/notify-send', summary]
|
||||
|
||||
if body is not None:
|
||||
command.append(body)
|
||||
|
||||
return run(command, stdout=DEVNULL)
|
||||
|
||||
|
||||
def notify_laptop_mode():
|
||||
"""Notifies about laptop mode."""
|
||||
|
||||
return notify_send('Laptop mode.', 'The system is now in laptop mode.')
|
||||
|
||||
|
||||
def notify_tablet_mode():
|
||||
"""Notifies about tablet mode."""
|
||||
|
||||
return notify_send('Tablet mode.', 'The system is now in tablet mode.')
|
||||
|
||||
|
||||
def toggle_mode(notify):
|
||||
"""Toggles between laptop and tablet mode."""
|
||||
|
||||
if systemctl('status', LAPTOP_MODE_SERVICE):
|
||||
systemctl('stop', LAPTOP_MODE_SERVICE, root=True)
|
||||
systemctl('start', TABLET_MODE_SERVICE, root=True)
|
||||
|
||||
if notify:
|
||||
notify_tablet_mode()
|
||||
else:
|
||||
systemctl('stop', TABLET_MODE_SERVICE, root=True)
|
||||
systemctl('start', LAPTOP_MODE_SERVICE, root=True)
|
||||
|
||||
if notify:
|
||||
notify_laptop_mode()
|
||||
|
||||
|
||||
def default_mode(notify):
|
||||
"""Restores all blocked input devices."""
|
||||
|
||||
systemctl('stop', LAPTOP_MODE_SERVICE, root=True)
|
||||
systemctl('stop', TABLET_MODE_SERVICE, root=True)
|
||||
|
||||
if notify:
|
||||
notify_send('Default mode.', 'The system is now in default mode.')
|
||||
|
||||
|
||||
def laptop_mode(notify):
|
||||
"""Starts the laptop mode."""
|
||||
|
||||
systemctl('stop', TABLET_MODE_SERVICE, root=True)
|
||||
systemctl('start', LAPTOP_MODE_SERVICE, root=True)
|
||||
|
||||
if notify:
|
||||
notify_laptop_mode()
|
||||
|
||||
|
||||
def tablet_mode(notify):
|
||||
"""Starts the tablet mode."""
|
||||
|
||||
systemctl('stop', LAPTOP_MODE_SERVICE, root=True)
|
||||
systemctl('start', TABLET_MODE_SERVICE, root=True)
|
||||
|
||||
if notify:
|
||||
notify_tablet_mode()
|
||||
|
||||
|
||||
def main():
|
||||
"""Runs the main program."""
|
||||
|
||||
arguments = get_arguments()
|
||||
|
||||
if arguments.mode == 'toggle':
|
||||
toggle_mode(arguments.notify)
|
||||
elif arguments.mode == 'default':
|
||||
default_mode(arguments.notify)
|
||||
elif arguments.mode == 'laptop':
|
||||
laptop_mode(arguments.notify)
|
||||
elif arguments.mode == 'tablet':
|
||||
tablet_mode(arguments.notify)
|
||||
else:
|
||||
print('Must specify a mode.', file=stderr, flush=True)
|
84
sysmoded
Executable file
84
sysmoded
Executable file
|
@ -0,0 +1,84 @@
|
|||
#! /usr/bin/env python3
|
||||
"""System mode daemon."""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from json import load
|
||||
from logging import DEBUG, INFO, basicConfig, getLogger
|
||||
from pathlib import Path
|
||||
from subprocess import Popen
|
||||
|
||||
|
||||
CONFIG_FILE = Path('/etc/tablet-mode.json')
|
||||
DESCRIPTION = 'Setup system for laptop or tablet mode.'
|
||||
EVTEST = '/usr/bin/evtest'
|
||||
LOG_FORMAT = '[%(levelname)s] %(name)s: %(message)s'
|
||||
LOGGER = getLogger(__file__)
|
||||
|
||||
|
||||
def get_arguments():
|
||||
"""Parses the CLI arguments."""
|
||||
|
||||
parser = ArgumentParser(description=DESCRIPTION)
|
||||
parser.add_argument(
|
||||
'-v', '--verbose', action='store_true',
|
||||
help='turn on verbose logging')
|
||||
subparsers = parser.add_subparsers(dest='mode')
|
||||
subparsers.add_parser('laptop', help='enable laptop mode')
|
||||
subparsers.add_parser('tablet', help='enable tablet mode')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def load_configuration():
|
||||
"""Returns the configuration."""
|
||||
|
||||
try:
|
||||
with CONFIG_FILE.open('r') as cfg:
|
||||
return load(cfg)
|
||||
except FileNotFoundError:
|
||||
LOGGER.warning('Config file %s does not exist.', CONFIG_FILE)
|
||||
return {}
|
||||
|
||||
|
||||
def disable_device(device):
|
||||
"""Disables the respective device via evtest."""
|
||||
|
||||
return Popen((EVTEST, '--grab', device))
|
||||
|
||||
|
||||
def disable_devices(devices):
|
||||
"""Disables the given devices."""
|
||||
|
||||
subprocesses = []
|
||||
|
||||
for device in devices:
|
||||
subprocess = disable_device(device)
|
||||
subprocesses.append(subprocess)
|
||||
|
||||
for subprocess in subprocesses:
|
||||
subprocess.wait()
|
||||
|
||||
|
||||
def get_devices(mode):
|
||||
"""Reads the device from the config file."""
|
||||
|
||||
configuration = load_configuration()
|
||||
devices = configuration.get(mode) or ()
|
||||
|
||||
if not devices:
|
||||
LOGGER.info('No devices configured to disable.')
|
||||
|
||||
return devices
|
||||
|
||||
|
||||
def main():
|
||||
"""Runs the main program."""
|
||||
|
||||
arguments = get_arguments()
|
||||
level = DEBUG if arguments.verbose else INFO
|
||||
basicConfig(level=level, format=LOG_FORMAT)
|
||||
devices = get_devices(arguments.mode)
|
||||
disable_devices(devices)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
48
tablet-mode
48
tablet-mode
|
@ -1,48 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
"""Grabs the respective device to discard any input from it."""
|
||||
|
||||
from configparser import ConfigParser
|
||||
from contextlib import suppress
|
||||
from subprocess import run
|
||||
from threading import Thread
|
||||
|
||||
|
||||
CONFIG_FILE = '/etc/tablet-mode.conf'
|
||||
EVTEST = '/usr/bin/evtest'
|
||||
|
||||
|
||||
def grab_device(device):
|
||||
"""Grabs the respective device via evtest."""
|
||||
|
||||
return run((EVTEST, '--grab', device))
|
||||
|
||||
|
||||
def get_devices():
|
||||
"""Reads the device from the config file."""
|
||||
|
||||
parser = ConfigParser()
|
||||
parser.read(CONFIG_FILE)
|
||||
|
||||
with suppress(KeyError):
|
||||
yield parser['Devices']['keyboard']
|
||||
|
||||
with suppress(KeyError):
|
||||
yield parser['Devices']['touchpad']
|
||||
|
||||
|
||||
def disable_devices(devices):
|
||||
"""Disables the given devices."""
|
||||
|
||||
threads = []
|
||||
|
||||
for device in devices:
|
||||
thread = Thread(target=grab_device, args=[device])
|
||||
threads.append(thread)
|
||||
thread.start()
|
||||
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
disable_devices(get_devices())
|
|
@ -2,6 +2,6 @@
|
|||
Comment=Toggle tablet mode
|
||||
Terminal=false
|
||||
Name=Tablet Mode
|
||||
Exec=/usr/bin/toggle-tablet-mode
|
||||
Exec=/usr/bin/setsysmode toggle
|
||||
Type=Application
|
||||
Icon=pda-symbolic
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
[Unit]
|
||||
Description=Disable keyboard and touchpad for tablet mode
|
||||
Description=Configure system for tablet mode
|
||||
Conflicts=laptop-mode.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/tablet-mode
|
||||
ExecStart=/usr/bin/setsysmode tablet
|
||||
StandardOutput=null
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
@ -1 +1,13 @@
|
|||
%tablet ALL=(ALL) NOPASSWD: /usr/bin/systemctl start tablet-mode.service, /usr/bin/systemctl stop tablet-mode.service
|
||||
# This file is part of tablet-mode.
|
||||
#
|
||||
# It allows users in the group "tablet" to toggle
|
||||
# the system between tablet and laptop mode.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
Cmnd_Alias START_LAPTOP_MODE = /usr/bin/systemctl start laptop-mode.service
|
||||
Cmnd_Alias STOP_LAPTOP_MODE = /usr/bin/systemctl stop laptop-mode.service
|
||||
Cmnd_Alias START_TABLET_MODE = /usr/bin/systemctl start tablet-mode.service
|
||||
Cmnd_Alias STOP_TABLET_MODE = /usr/bin/systemctl stop tablet-mode.service
|
||||
|
||||
%tablet ALL=(ALL) NOPASSWD: START_LAPTOP_MODE, STOP_LAPTOP_MODE, START_TABLET_MODE, STOP_TABLET_MODE
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
if ( systemctl status tablet-mode.service ); then
|
||||
sudo systemctl stop tablet-mode.service
|
||||
notify-send "Laptop mode" "The system is now in laptop mode."
|
||||
else
|
||||
sudo systemctl start tablet-mode.service
|
||||
notify-send "Tablet mode" "The system is now in tablet mode."
|
||||
fi
|
||||
|
Loading…
Reference in a new issue