| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,63 +1,18 @@ | ||
| NULL = | ||
|
|
||
| dbussessionservicedir = $(DBUS_SESSION_SERVICE_DIR) | ||
| dbussessionservice_DATA = org.cinnamon.ScreenSaver.service \ | ||
| org.cinnamon.ScreenSaver.PAMHelper.service | ||
|
|
||
| SUBDIRS = screensavers | ||
|
|
||
| EXTRA_DIST = \ | ||
| org.cinnamon.ScreenSaver.service.in \ | ||
| org.cinnamon.ScreenSaver.PAMHelper.service.in | ||
| $(NULL) | ||
|
|
||
| MAINTAINERCLEANFILES = \ | ||
| *~ \ | ||
| Makefile.in | ||
|
|
||
| -include $(top_srcdir)/git.mk |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [D-BUS Service] | ||
| Name=org.cinnamon.ScreenSaver.PAMHelper | ||
| Exec=@EXPANDED_BINDIR@/cinnamon-screensaver-pam-helper |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,14 @@ | ||
| #!/usr/bin/make -f | ||
|
|
||
| %: | ||
| dh $@ --parallel --with=autoreconf,gnome | ||
|
|
||
| override_dh_gnome_clean: | ||
| dh_gnome_clean --no-control | ||
|
|
||
| DEB_CONFIGURE_SCRIPT_ENV += PYTHON="/usr/bin/python3" | ||
|
|
||
| DEB_MAKE_EXTRA_ARGS += pythondir=/usr/share/cinnamon-screensaver | ||
|
|
||
| install/cinnamon-screensaver:: | ||
| dh_python3 -p$(cdbs_curpkg) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| #!/bin/bash | ||
| xgettext --language=Python --from-code=UTF-8 --keyword=_ --output=cinnamon-screensaver.pot src/*.py |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,4 @@ | ||
| # List of source files containing translatable strings. | ||
| # Please keep this file sorted alphabetically. | ||
| src/clock.py | ||
| src/lock.py |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| #! /usr/bin/python3 | ||
|
|
||
| import PAM | ||
|
|
||
| from gi.repository import Gio, GObject | ||
| import threading | ||
| import dbus | ||
| import constants as c | ||
|
|
||
| class PAMServiceProxy: | ||
| def __init__(self): | ||
| self.callback = None | ||
| self.proxy = None | ||
|
|
||
| try: | ||
| Gio.DBusProxy.new_for_bus(Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, | ||
| c.PAM_SERVICE, c.PAM_PATH, c.PAM_SERVICE, | ||
| None, self._onProxyReady, None) | ||
| except dbus.exceptions.DBusException as e: | ||
| print(e) | ||
| self.proxy = None | ||
|
|
||
| def _onProxyReady(self, object, result, data=None): | ||
| self.proxy = Gio.DBusProxy.new_for_bus_finish(result) | ||
|
|
||
| def check_password(self, username, password, callback): | ||
| self.callback = callback | ||
|
|
||
| if self.proxy: | ||
| thread = threading.Thread(target=self.check_password_thread, args=(username, password, callback)) | ||
| thread.start() | ||
| else: | ||
| success, msg = self.check_password_fallback(username, password) | ||
| GObject.idle_add(self.idle_callback_and_clear, success, msg) | ||
|
|
||
| def check_password_thread(self, username, password, callback): | ||
| if self.proxy: | ||
| try: | ||
| success, msg = self.proxy.authenticate('(ss)', username, password) | ||
| except Exception as e: | ||
| print(str(e)) | ||
| success, msg = self.check_password_fallback(username, password) | ||
| else: | ||
| success, msg = self.check_password_fallback(username, password) | ||
|
|
||
| GObject.idle_add(self.idle_callback_and_clear, success, msg) | ||
|
|
||
| def check_password_fallback(self, username, password): | ||
| print("PAM Helper service unavailable, using sync method") | ||
| success, msg = real_check_password(username, password) | ||
|
|
||
| return (success, msg) | ||
|
|
||
| def idle_callback_and_clear(self, success, msg): | ||
| self.callback(success, msg) | ||
| self.callback = None | ||
|
|
||
| return False | ||
|
|
||
| def real_check_password(username, password): | ||
| ret = None | ||
|
|
||
| pam_auth = PAM.pam() | ||
|
|
||
| pam_auth.start("cinnamon-screensaver") | ||
| pam_auth.set_item(PAM.PAM_USER, username) | ||
|
|
||
| def _pam_conv(auth, query_list, user_data = None): | ||
| resp = [] | ||
| for i in range(len(query_list)): | ||
| query, qtype = query_list[i] | ||
| if qtype == PAM.PAM_PROMPT_ECHO_ON: | ||
| resp.append((username, 0)) | ||
| elif qtype == PAM.PAM_PROMPT_ECHO_OFF: | ||
| resp.append((password, 0)) | ||
| else: | ||
| return None | ||
| return resp | ||
|
|
||
| pam_auth.set_item(PAM.PAM_CONV, _pam_conv) | ||
|
|
||
| try: | ||
| pam_auth.authenticate() | ||
| pam_auth.acct_mgmt() | ||
| except PAM.error as res: | ||
| ret = (False, res.args[0]) | ||
| except Exception as e: | ||
| log.warn("Error with PAM: %s" % str(e)) | ||
| ret = (False, e) | ||
| else: | ||
| ret = (True, "") | ||
|
|
||
| return ret | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| #! /usr/bin/python3 | ||
|
|
||
| from gi.repository import Gtk, GObject | ||
| import trackers | ||
|
|
||
| class BaseWindow(Gtk.Revealer): | ||
| REVEALER_DURATION = 250 | ||
|
|
||
| def __init__(self): | ||
| super(BaseWindow, self).__init__() | ||
|
|
||
| self.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE) | ||
| self.set_transition_duration(self.REVEALER_DURATION) | ||
|
|
||
| def reveal(self): | ||
| GObject.idle_add(self.set_reveal_child, True) | ||
|
|
||
| def unreveal(self): | ||
| GObject.idle_add(self.set_reveal_child, False) | ||
|
|
||
| def blink(self): | ||
| self.set_reveal_child(False) | ||
| GObject.timeout_add(self.REVEALER_DURATION + 10, self._blink_callback) | ||
|
|
||
| def _blink_callback(self): | ||
| self.set_reveal_child(True) | ||
|
|
||
| return False | ||
|
|
||
| def destroy_window(self): | ||
| trackers.con_tracker_get().connect_after(self, | ||
| "notify::child-revealed", | ||
| self.destroy_after_hiding) | ||
|
|
||
| self.unreveal() | ||
|
|
||
| def destroy_after_hiding(self, pspec, data): | ||
| trackers.con_tracker_get().disconnect(self, | ||
| "notify::child-revealed", | ||
| self.destroy_after_hiding) | ||
|
|
||
| self.destroy() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #! /usr/bin/python3 | ||
|
|
||
| import gi | ||
| gi.require_version('Gtk', '3.0') | ||
| from gi.repository import Gtk | ||
|
|
||
| import dbus | ||
| from dbus.mainloop.glib import DBusGMainLoop | ||
|
|
||
| import signal | ||
| signal.signal(signal.SIGINT, signal.SIG_DFL) | ||
|
|
||
| import gettext | ||
| import os | ||
| import sys | ||
| import argparse | ||
|
|
||
| import config | ||
| from service import ScreensaverService | ||
|
|
||
| gettext.install("cinnamon-screensaver", "/usr/share/locale") | ||
|
|
||
| class Main: | ||
| def __init__(self): | ||
| parser = argparse.ArgumentParser(description='Cinnamon Screensaver') | ||
| parser.add_argument('--version', dest='version', action='store_true', | ||
| help='Display the current version') | ||
| parser.add_argument('--no-daemon', dest='no_daemon', action='store_true', | ||
| help="Don't become a daemon") | ||
| args = parser.parse_args() | ||
|
|
||
| if args.version: | ||
| print("cinnamon-screensaver %s" % (config.VERSION)) | ||
| quit() | ||
|
|
||
| if args.no_daemon: | ||
| print("FIX ME no daemon") | ||
| quit() | ||
|
|
||
| service = ScreensaverService() | ||
| Gtk.main() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| DBusGMainLoop(set_as_default=True) | ||
|
|
||
| main = Main() | ||
|
|
||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #! /bin/sh | ||
|
|
||
| exec @datadir@/cinnamon-screensaver/pam-helper-service.py "$@" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #! /bin/sh | ||
|
|
||
| exec @datadir@/cinnamon-screensaver/cinnamon-screensaver-main.py "$@" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| #! /usr/bin/python3 | ||
|
|
||
| from gi.repository import CinnamonDesktop, GLib, Gtk, Gio, GObject | ||
| import utils | ||
| import random | ||
| from baseWindow import BaseWindow | ||
| import trackers | ||
|
|
||
| CLOCK_POSITIONING_TIMEOUT = 5 | ||
| ALIGNMENTS = [int(Gtk.Align.START), int(Gtk.Align.END), int(Gtk.Align.CENTER)] | ||
|
|
||
| class ClockWidget(BaseWindow): | ||
| def __init__(self, away_message=None, initial_monitor=0): | ||
| super(ClockWidget, self).__init__() | ||
|
|
||
| self.set_halign(Gtk.Align.CENTER) | ||
| self.set_valign(Gtk.Align.CENTER) | ||
|
|
||
| self.set_margin_start(200) | ||
| self.set_margin_end(200) | ||
| self.set_margin_top(100) | ||
| self.set_margin_bottom(100) | ||
|
|
||
| self.current_monitor = initial_monitor | ||
|
|
||
| self.away_message = away_message | ||
|
|
||
| self.label = Gtk.Label() | ||
| self.label.show() | ||
| self.add(self.label) | ||
|
|
||
| self.clock_tracker = CinnamonDesktop.WallClock() | ||
| self.ss_settings = Gio.Settings("org.cinnamon.desktop.screensaver") | ||
| self.iface_settings = Gio.Settings("org.cinnamon.desktop.interface") | ||
|
|
||
| trackers.con_tracker_get().connect(self.clock_tracker, | ||
| "notify::clock", | ||
| self.on_clock_changed) | ||
| trackers.con_tracker_get().connect(self.ss_settings, | ||
| "changed", | ||
| self.on_settings_changed) | ||
| trackers.con_tracker_get().connect(self.iface_settings, | ||
| "changed", | ||
| self.on_settings_changed) | ||
|
|
||
| tz = Gio.File.new_for_path(path="/etc/localtime") | ||
| self.tz_monitor = tz.monitor_file(0, None) | ||
|
|
||
| trackers.con_tracker_get().connect(self.tz_monitor, | ||
| "changed", | ||
| self.on_tz_changed) | ||
|
|
||
| self.settings = utils.Settings() | ||
| self.fetch_settings() | ||
| self.update_clock() | ||
|
|
||
| def on_clock_changed(self, clock, pspec): | ||
| self.update_clock() | ||
|
|
||
| def on_settings_changed(self, settings, key): | ||
| self.update_clock() | ||
|
|
||
| def on_tz_changed(self, monitor, file, other, event): | ||
| self.update_clock() | ||
|
|
||
| def get_clock_string(self): | ||
| date_value = "" | ||
| time_value = "" | ||
|
|
||
| now = GLib.DateTime.new_now_local() | ||
|
|
||
| if not self.settings.use_custom_format: | ||
| if self.settings.show_date: | ||
| date_value = now.format(_("%A, %B %e")) | ||
| else: | ||
| date_value = "" | ||
|
|
||
| if self.settings.use_24h: | ||
| time_value = now.format("%H:%M").lstrip() | ||
| else: | ||
| time_value = now.format("%l:%M %p").lstrip() | ||
| else: | ||
| date_value = now.format(self.settings.custom_date) | ||
| time_value = now.format(self.settings.custom_time) | ||
|
|
||
| clock_string = ('<b><span font_desc=\"%s\" foreground=\"#FFFFFF\">%s</span></b>\n' +\ | ||
| '<b><span font_desc=\"%s\" foreground=\"#FFFFFF\">%s</span></b>')\ | ||
| % (self.settings.font_time, time_value, self.settings.font_date, date_value) | ||
|
|
||
| return clock_string | ||
|
|
||
| def update_clock(self): | ||
| default_message = GLib.markup_escape_text (self.settings.default_message, -1) | ||
| font_message = self.settings.font_message | ||
|
|
||
| if self.away_message and self.away_message != "": | ||
| user_name = utils.get_user_display_name() | ||
| markup = ('%s\n\n<b><span font_desc=\"Ubuntu 14\" foreground=\"#CCCCCC\">%s</span></b>' +\ | ||
| '\n<b><span font_desc=\"Ubuntu 10\" foreground=\"#ACACAC\"> ~ %s</span></b>') %\ | ||
| (self.get_clock_string(), self.away_message, user_name) | ||
| else: | ||
| markup = '%s\n\n<b><span font_desc=\"%s\" foreground=\"#CCCCCC\">%s</span></b>' %\ | ||
| (self.get_clock_string(), font_message, default_message) | ||
|
|
||
| self.label.set_markup(markup) | ||
| self.label.set_line_wrap(True) | ||
| self.label.set_alignment(0.5, 0.5) | ||
|
|
||
| def fetch_settings(self): | ||
| self.settings.default_message = self.ss_settings.get_string("default-message") | ||
| self.settings.font_message = self.ss_settings.get_string("font-message") | ||
|
|
||
| self.settings.use_custom_format = self.ss_settings.get_boolean("use-custom-format") | ||
| self.settings.custom_time = self.ss_settings.get_string("time-format") | ||
| self.settings.custom_date = self.ss_settings.get_string("date-format") | ||
| self.settings.font_time = self.ss_settings.get_string("font-time") | ||
| self.settings.font_date = self.ss_settings.get_string("font-date") | ||
|
|
||
| self.settings.show_date = self.iface_settings.get_boolean("clock-show-date") | ||
| self.settings.use_24h = self.iface_settings.get_boolean("clock-use-24h") | ||
|
|
||
| def start_positioning(self): | ||
| trackers.timer_tracker_get().cancel("clock-positioning") | ||
| trackers.timer_tracker_get().start_seconds("clock-positioning", | ||
| CLOCK_POSITIONING_TIMEOUT, | ||
| self.positioning_callback) | ||
|
|
||
| def stop_positioning(self): | ||
| trackers.timer_tracker_get().cancel("clock-positioning") | ||
|
|
||
| def positioning_callback(self): | ||
| self.unreveal() | ||
| self.queue_draw() | ||
|
|
||
| trackers.timer_tracker_get().start("align-clock-timeout", | ||
| self.REVEALER_DURATION + 10, | ||
| self.align_clock) | ||
|
|
||
| return True | ||
|
|
||
| def align_clock(self): | ||
| current_halign = int(self.get_halign()) | ||
| horizontal = current_halign | ||
|
|
||
| current_valign = int(self.get_valign()) | ||
| vertical = current_valign | ||
|
|
||
| while horizontal == current_halign: | ||
| horizontal = ALIGNMENTS[random.randint(0, 2)] | ||
| while vertical == current_valign: | ||
| vertical = ALIGNMENTS[random.randint(0, 2)] | ||
|
|
||
| self.set_halign(Gtk.Align(horizontal)) | ||
| self.set_valign(Gtk.Align(vertical)) | ||
|
|
||
| self.queue_draw() | ||
|
|
||
| self.reveal() | ||
|
|
||
| trackers.timer_tracker_get().cancel("align-clock-timeout") | ||
|
|
||
| return False | ||
|
|
||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| prefix="@prefix@" | ||
| datadir="@datadir@" | ||
| localedir=datadir+"/locale" | ||
| pkgdatadir="@pkgdatadir@" | ||
| libdir="@libdir@" | ||
| libexecdir="@libexecdir@" | ||
| PACKAGE="@PACKAGE@" | ||
| VERSION="@VERSION@" | ||
| GETTEXT_PACKAGE="@GETTEXT_PACKAGE@" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
|
|
||
| # /* logind */ | ||
| LOGIND_SERVICE = "org.freedesktop.login1" | ||
| LOGIND_PATH = "/org/freedesktop/login1" | ||
| LOGIND_INTERFACE = "org.freedesktop.login1.Manager" | ||
|
|
||
| LOGIND_SESSION_INTERFACE = "org.freedesktop.login1.Session" | ||
| LOGIND_SESSION_PATH = "/org/freedesktop/login1/session" | ||
|
|
||
| # /* ConsoleKit */ | ||
| CK_SERVICE = "org.freedesktop.ConsoleKit" | ||
| CK_PATH = "/org/freedesktop/ConsoleKit" | ||
| CK_INTERFACE = "org.freedesktop.ConsoleKit" | ||
|
|
||
| CK_MANAGER_PATH = CK_PATH + "/Manager" | ||
| CK_MANAGER_INTERFACE = CK_INTERFACE + ".Manager" | ||
|
|
||
| CK_SESSION_PATH = CK_PATH + "/Session" | ||
| CK_SESSION_INTERFACE = CK_INTERFACE + ".Session" | ||
|
|
||
| # /* DBus */ | ||
| DBUS_SERVICE = "org.freedesktop.DBus" | ||
| DBUS_PATH = "/org/freedesktop/DBus" | ||
| DBUS_INTERFACE = "org.freedesktop.DBus" | ||
|
|
||
| # /* Cinnamon Screensaver */ | ||
| SS_SERVICE = "org.cinnamon.ScreenSaver" | ||
| SS_PATH = "/org/cinnamon/ScreenSaver" | ||
| SS_INTERFACE = "org.cinnamon.ScreenSaver" | ||
|
|
||
| # PAM Helper service | ||
| PAM_SERVICE = "org.cinnamon.ScreenSaver.PAMHelper" | ||
| PAM_PATH = "/org/cinnamon/ScreenSaver/PAMHelper" | ||
| PAM_INTERFACE = "org.cinnamon.ScreenSaver.PAMHelper" | ||
|
|
||
| # /* Gnome Session Manager */ | ||
| GSM_SERVICE = "org.gnome.SessionManager" | ||
| GSM_PATH = "/org/gnome/SessionManager" | ||
| GSM_INTERFACE = "org.gnome.SessionManager" | ||
|
|
||
| GSM_PRESENCE_PATH = GSM_PATH + "/Presence" | ||
| GSM_PRESENCE_INTERFACE = GSM_INTERFACE + ".Presence" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #! /usr/bin/python3 | ||
|
|
||
| from gi.repository import Gtk, Gdk, GObject | ||
| import utils | ||
|
|
||
| # FullscreenWindow is just a dummy OR window that takes care of putting | ||
| # us in fullscreen mode for all monitors. | ||
|
|
||
| class FullscreenWindow(Gtk.Window): | ||
| def __init__(self, screen, index): | ||
| super(FullscreenWindow, self).__init__(type=Gtk.WindowType.POPUP, | ||
| decorated=False, | ||
| skip_taskbar_hint=True, | ||
| skip_pager_hint=True) | ||
|
|
||
| self.screen = screen | ||
| self.monitor_index = index | ||
|
|
||
| c = self.get_style_context() | ||
| c.remove_class("background") | ||
|
|
||
| self.update_geometry() | ||
|
|
||
| self.connect("realize", self.on_realized) | ||
| self.connect("map", self.on_mapped) | ||
|
|
||
| self.show() | ||
|
|
||
| self.set_opacity(.1) | ||
|
|
||
| def do_get_preferred_height(self): | ||
| if self.get_realized(): | ||
| self.get_window().move(self.rect.x, self.rect.y) | ||
| return self.rect.height, self.rect.height | ||
| else: | ||
| return 0, 0 | ||
|
|
||
| def do_get_preferred_width(self): | ||
| if self.get_realized(): | ||
| self.get_window().move(self.rect.x, self.rect.y) | ||
| return self.rect.width, self.rect.width | ||
| else: | ||
| return 0, 0 | ||
|
|
||
| def on_realized(self, widget): | ||
| self.get_window().move_resize(self.rect.x, self.rect.y, self.rect.width, self.rect.height) | ||
| utils.override_user_time(self.get_window()) | ||
| self.fullscreen_on_monitor(self.screen, self.monitor_index) | ||
|
|
||
| def on_mapped(self, widget): | ||
| window = widget.get_window() | ||
| # window.fullscreen() | ||
| window.lower() | ||
|
|
||
| def update_geometry(self): | ||
| self.rect = rect = self.screen.get_monitor_geometry(self.monitor_index) | ||
| print(rect.x, rect.y, rect.width, rect.height) | ||
|
|