156 lines
5.9 KiB
Python
156 lines
5.9 KiB
Python
# 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 sys
|
|
import locale
|
|
|
|
from gi.repository import Gtk, Gdk, GObject, GLib
|
|
|
|
|
|
_ = locale.gettext
|
|
|
|
|
|
class LockWindow(Gtk.Window):
|
|
__gsignals__ = {
|
|
'logout': (GObject.SIGNAL_RUN_FIRST, None, ()),
|
|
'tryUnlock': (GObject.SIGNAL_RUN_FIRST, None, (str,))
|
|
}
|
|
|
|
def __init__(self):
|
|
Gtk.Window.__init__(self)
|
|
|
|
self.display = Gdk.Display.get_default()
|
|
self.screen = self.display.get_default_screen()
|
|
|
|
self.overlay = Gtk.Overlay()
|
|
self.add(self.overlay)
|
|
|
|
self.bg = Gtk.Image.new_from_file("bg.svg")
|
|
self.overlay.add(self.bg)
|
|
|
|
self.realize()
|
|
self.get_window().set_override_redirect(True)
|
|
|
|
self.set_default_size(self.screen.get_width(), self.screen.get_height())
|
|
|
|
self.set_has_resize_grip(False)
|
|
|
|
builder = Gtk.Builder()
|
|
|
|
if not builder.add_from_file("unlock.ui"):
|
|
sys.exit(1)
|
|
|
|
self.unlockWindow = builder.get_object('unlock_window')
|
|
self.lockLabel = builder.get_object('lock_label')
|
|
self.promptEntry = builder.get_object('prompt_entry')
|
|
self.messageLabel = builder.get_object('message_label')
|
|
self.logoutButton = builder.get_object('logout_button')
|
|
self.unlockButton = builder.get_object('unlock_button')
|
|
|
|
self.overlay.add_overlay(self.unlockWindow)
|
|
|
|
self.connect('delete-event', lambda w, e: True)
|
|
|
|
self.promptEntry.connect('activate', lambda w: self._tryUnlock())
|
|
self.logoutButton.connect('clicked', lambda w: self._logout())
|
|
self.unlockButton.connect('clicked', lambda w: self._tryUnlock())
|
|
|
|
self.reset(False, True)
|
|
|
|
self.deviceManager = self.display.get_device_manager()
|
|
|
|
self.connect('map-event', self._grabDevices)
|
|
self.connect('configure-event', lambda w, e: self.get_window().move_resize(0, 0, self.screen.get_width(), self.screen.get_height()) and False)
|
|
|
|
def _logout(self):
|
|
self.promptEntry.set_sensitive(False)
|
|
self.unlockButton.set_sensitive(False)
|
|
self.logoutButton.set_sensitive(False)
|
|
GLib.idle_add(lambda: self.emit('logout'))
|
|
|
|
def _tryUnlock(self):
|
|
self.promptEntry.set_sensitive(False)
|
|
self.unlockButton.set_sensitive(False)
|
|
self.logoutButton.set_sensitive(False)
|
|
GLib.idle_add(lambda: self.emit('tryUnlock', self.promptEntry.get_text()))
|
|
|
|
def _update(self):
|
|
self.promptEntry.set_sensitive(self._enablePromptEntry)
|
|
self.logoutButton.set_sensitive(self._enableLogoutButton)
|
|
self.unlockButton.set_sensitive(self._enableUnlockButton)
|
|
|
|
def reset(self, regrab = True, resetButtons = False):
|
|
if resetButtons:
|
|
self._enablePromptEntry = True
|
|
self._enableLogoutButton = False
|
|
self._enableUnlockButton = True
|
|
|
|
self.promptEntry.set_text('')
|
|
self.messageLabel.set_label('')
|
|
self._update()
|
|
|
|
if regrab:
|
|
self._grabDevices(None, None)
|
|
|
|
def updateLockMessage(self, username, logoutTime = None):
|
|
if logoutTime is None:
|
|
self.lockLabel.set_markup(_('This computer is currently locked by the user <i>{username}</i>.').format(username=GLib.markup_escape_text(username)))
|
|
self._enableLogoutButton = False
|
|
elif logoutTime > 0:
|
|
self.lockLabel.set_markup(
|
|
_('This computer is currently locked by the user <i>{username}</i>.\nThe user can be logged out in {minutes:02}:{seconds:02} minutes.').format(
|
|
username=GLib.markup_escape_text(username), minutes=logoutTime//60, seconds=logoutTime%60))
|
|
self._enableLogoutButton = False
|
|
else:
|
|
self.lockLabel.set_markup(
|
|
_('This computer is currently locked by the user <i>{username}</i>.\nThe user can be logged out now.').format(
|
|
username=GLib.markup_escape_text(username)))
|
|
self._enableLogoutButton = True
|
|
self._update()
|
|
|
|
def setAuthMessage(self, message):
|
|
self.messageLabel.set_label(message)
|
|
|
|
def _grabDevices(self, w, e):
|
|
self.promptEntry.grab_focus()
|
|
|
|
for device in self.deviceManager.list_devices(Gdk.DeviceType.MASTER):
|
|
device.grab(self.get_window(), Gdk.GrabOwnership.APPLICATION, True, Gdk.EventMask.ALL_EVENTS_MASK, None, Gdk.CURRENT_TIME)
|
|
|
|
self.present()
|
|
|
|
return False
|
|
|
|
def _ungrabDevices(self):
|
|
for device in self.deviceManager.list_devices(Gdk.DeviceType.MASTER):
|
|
device.ungrab(Gdk.CURRENT_TIME)
|
|
|
|
def lock(self):
|
|
self.show_all()
|
|
|
|
def unlock(self):
|
|
self._ungrabDevices()
|
|
|
|
self.hide()
|
|
self.reset(False, True)
|