diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2013-03-06 14:16:47 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2013-03-06 14:16:47 +0100 |
commit | 4659883ba00bd499f41f4cc1a5f96e4bdd5ac9de (patch) | |
tree | 74211870b90bb20c0041c8a76d677579a88206a9 | |
parent | e342d5c7241cd04352948fb6937e05a98000b70c (diff) | |
download | pylock-4659883ba00bd499f41f4cc1a5f96e4bdd5ac9de.tar pylock-4659883ba00bd499f41f4cc1a5f96e4bdd5ac9de.zip |
Rework pylock to behave like xlock
-rw-r--r-- | Idle.py | 71 | ||||
-rw-r--r-- | Locker.py | 25 | ||||
-rw-r--r-- | Selection.py (renamed from Message.py) | 22 | ||||
-rw-r--r-- | pylock.py | 77 |
4 files changed, 42 insertions, 153 deletions
diff --git a/Idle.py b/Idle.py deleted file mode 100644 index d9ea53a..0000000 --- a/Idle.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -import ctypes -import ctypes.util - -from gi.repository import GdkX11 - - -class XScreenSaverInfo(ctypes.Structure): - _fields_ = [ - ('window', ctypes.c_ulong), - ('state', ctypes.c_int), - ('kind', ctypes.c_int), - ('til_or_since', ctypes.c_ulong), - ('idle', ctypes.c_ulong), - ('eventMask', ctypes.c_ulong) - ] -XScreenSaverInfo_p = ctypes.POINTER(XScreenSaverInfo) - -display_p = ctypes.c_void_p -xid = ctypes.c_ulong -c_int_p = ctypes.POINTER(ctypes.c_int) - -libXsspath = ctypes.util.find_library('Xss') -if libXsspath == None: - raise OSError('libXss could not be found.') -libXss = ctypes.cdll.LoadLibrary(libXsspath) -libXss.XScreenSaverQueryExtension.argtypes = display_p, c_int_p, c_int_p -libXss.XScreenSaverAllocInfo.restype = XScreenSaverInfo_p -libXss.XScreenSaverQueryInfo.argtypes = (display_p, xid, XScreenSaverInfo_p) - -dpy_p = hash(GdkX11.x11_get_default_xdisplay()) -rootwindow = GdkX11.x11_get_default_root_xwindow() - -_event_basep = ctypes.c_int() -_error_basep = ctypes.c_int() -if libXss.XScreenSaverQueryExtension(ctypes.c_void_p(dpy_p), ctypes.byref(_event_basep), - ctypes.byref(_error_basep)) == 0: - raise OSError('XScreenSaver Extension not available on display.') - -xss_info_p = libXss.XScreenSaverAllocInfo() -if xss_info_p == None: - raise OSError('XScreenSaverAllocInfo: Out of Memory.') - -def getIdleSec(): - if libXss.XScreenSaverQueryInfo(dpy_p, rootwindow, xss_info_p) == 0: - return 0 - else: - return int(xss_info_p.contents.idle) / 1000 @@ -24,35 +24,16 @@ from gi.repository import Gtk, GLib -import Idle - class Locker(object): - def __init__(self, lockTimeout, doLock, doUnlock, logoutTimeout = None, doLogout = None, updateLogoutTimeout = None): + def __init__(self, doLock, doUnlock, logoutTimeout = None, doLogout = None, updateLogoutTimeout = None): self.locked = False - self.lockTimeout = lockTimeout self.logoutTimeout = logoutTimeout self.doLock = doLock self.doUnlock = doUnlock self.doLogout = doLogout self.updateLogoutTimeout = updateLogoutTimeout - if self.lockTimeout > 0: - GLib.timeout_add_seconds(1, self._checkLock) - else: - GLib.idle_add(self.lock) - - def _checkLock(self): - if self.locked: - return False - - idle = Idle.getIdleSec() - if (idle >= self.lockTimeout): - GLib.idle_add(self.lock) - return False - else: - return True - def _checkLogout(self): if not self.locked: return False @@ -68,7 +49,7 @@ class Locker(object): self.locked = True if not self.doLock(self.logoutTimeout): self.locked = False - GLib.timeout_add_seconds(1, self._checkLock) + GLib.timeout_add_seconds(1, self.lock) return False if self.doLogout is not None: @@ -84,8 +65,6 @@ class Locker(object): self.doUnlock() self.locked = False - GLib.timeout_add_seconds(1, self._checkLock) - def _canLogout(self): return (self.locked and self.doLogout is not None and self.currentLogoutTimeout <= 0) diff --git a/Message.py b/Selection.py index b78a0f3..11a7285 100644 --- a/Message.py +++ b/Selection.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> +# Copyright (c) 2012-2013, Matthias Schiffer <mschiffer@universe-factory.net> # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -41,8 +41,6 @@ if libX11 == None: raise OSError('libX11 could not be found.') libX11 = ctypes.cdll.LoadLibrary(libX11) -libX11.XSendEvent.argtypes = display_p, xid, x11_bool, ctypes.c_long, XEvent_p -libX11.XSendEvent.restype = status libX11.XSetSelectionOwner.argtypes = display_p, xid, xid, x11_time libX11.XSetSelectionOwner.restype = ctypes.c_int libX11.XGetSelectionOwner.argtypes = display_p, xid @@ -52,27 +50,17 @@ libX11.XGetSelectionOwner.restype = xid display = Gdk.Display.get_default() dpy_p = display_p(hash(GdkX11.X11Display.get_xdisplay(display))) atomPylockWindow = GdkX11.x11_get_xatom_by_name("PYLOCK_WINDOW") -atomPylockActionLock = GdkX11.x11_get_xatom_by_name("PYLOCK_ACTION_LOCK") -def getSelection(): +def get(): return libX11.XGetSelectionOwner(dpy_p, atomPylockWindow) -def sendLockMessage(): - window = getSelection() - if window == 0: - return - - gdkWindow = GdkX11.X11Window.foreign_new_for_display(display, window) - gdkWindow.show() - display.sync() - -def acquireSelection(window): - if getSelection() != 0: +def acquire(window): + if get() != 0: return False window.realize() xid = GdkX11.X11Window.get_xid(window.get_window()) libX11.XSetSelectionOwner(dpy_p, atomPylockWindow, xid, 0) - return (getSelection() == xid) + return (get() == xid) @@ -30,33 +30,27 @@ import sys import os import pwd import locale -import argparse +import configparser -from gi.repository import Gtk, Gdk, Gio +from gi.repository import Gtk, GLib from Locker import Locker from LockWindow import LockWindow -import Message +import Selection import pam -_ = locale.gettext - +CONFIG_FILE = '/etc/pylock.conf' -def get_username(): - return pwd.getpwuid(os.getuid())[0] - -theme = 'UzL-login' +_ = locale.gettext -parser = argparse.ArgumentParser(prog='pylock', description=_('GTK-based screen locker.')) -parser.add_argument('-t', '--timeout', type=int, default=0, help=_('Start in daemon mode that will automatically activate after a given time of inactivity.')) -parser.add_argument('-l', '--logout', type=int, default=0, help=_('Allow to logout the current user after a given time.')) -parser.add_argument('-c', '--logout-command', help=_('Specifies the command to be called to log out a user.')) -parser.add_argument('-u', '--username', default=get_username(), help=_('Set the name of the user that is able to unlock the screen.')) +configParser = configparser.ConfigParser() +configParser.read_file(open(CONFIG_FILE)) -args = parser.parse_args() +config = configParser['pylock'] +username = pwd.getpwuid(os.getuid())[0] def handler(signum, frame): @@ -71,66 +65,65 @@ signal.signal(signal.SIGQUIT, handler) locale.setlocale(locale.LC_ALL, '') locale.textdomain('pylock') -Gtk.Settings.get_default().set_property('gtk-theme-name', theme) +Gtk.Settings.get_default().set_property('gtk-theme-name', config['theme']) -if Message.getSelection() != 0: - if args.timeout == 0: - Message.sendLockMessage() - exit(0) - else: - print('There seems to be a Pylock instance already running.', file=sys.stderr) - exit(1) +def waitForSelection(): + if Selection.get() != 0: + return True + + Gtk.main_quit() + return False + +if Selection.get() != 0: + GLib.timeout_add_seconds(1, waitForSelection) + Gtk.main() + exit(0) window = LockWindow() -if not Message.acquireSelection(window): - print('Unable to register for lock messages', file=sys.stderr) +if not Selection.acquire(window): + print('Unable to register pylock at X server', file=sys.stderr) + exit(1) def lock(timeLeft): - window.updateLockMessage(args.username, timeLeft) + window.updateLockMessage(username, timeLeft) return window.lock() def logout(): try: - os.system(args.logout_command) + os.system(config['logout_command']) except: pass window.reset(False) def updateTimeout(timeLeft): - window.updateLockMessage(args.username, timeLeft) + window.updateLockMessage(username, timeLeft) -if args.logout_command is None: - locker = Locker(args.timeout, lock, window.unlock) +if not ('logout_timeout' in config and 'logout_command' in config): + locker = Locker(lock, window.unlock) else: - locker = Locker(args.timeout, lock, window.unlock, args.logout, logout, updateTimeout) - - -def _triggerLock(w, e): - locker.lock() - -window.connect('map-event', _triggerLock) - + locker = Locker(lock, window.unlock, int(config['logout_timeout']), logout, updateTimeout) pamAuth = pam.pam() def tryUnlock(w, password): - if pamAuth.authenticate(args.username, password): + if pamAuth.authenticate(username, password): locker.unlock() - - if args.timeout == 0: - Gtk.main_quit() + Gtk.main_quit() else: window.reset() window.setAuthMessage(pamAuth.reason) return True + window.connect('logout', lambda w: locker.logout()) window.connect('tryUnlock', tryUnlock) +GLib.idle_add(lambda: locker.lock()) + Gtk.main() |