2
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3
# Light Locker Settings - simple configuration tool for light-locker
4
# Copyright (C) 2014 Thomas Molloy <beetyrootey@gmail.com>
6
# This program is free software: you can redistribute it and/or modify it
7
# under the terms of the GNU General Public License version 3, as published
8
# by the Free Software Foundation.
10
# This program is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranties of
12
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13
# PURPOSE. See the GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License along
16
# with this program. If not, see <http://www.gnu.org/licenses/>.
19
gettext.textdomain('light-locker-settings')
21
from gettext import gettext as _
22
from gettext import ngettext
29
from gi.repository import Gtk, GLib
33
import light_locker_xfsync
35
''' Settings window for the light-locker '''
37
username = GLib.get_user_name()
40
class LightLockerSettings:
41
'''Light Locker Settings application class.'''
44
'''Initialize the Light Locker Settings application.'''
45
self.systemwide_desktop_file = \
46
"/etc/xdg/autostart/light-locker.desktop"
47
self.user_desktop_file = os.path.join(os.path.expanduser('~'),
50
'light-locker.desktop')
51
self.screenblank_timeout_desktop_file = os.path.join(
52
os.path.expanduser('~'),
55
'screensaver-settings.desktop')
57
self.builder = Gtk.Builder()
59
script_dir = os.path.dirname(os.path.abspath(__file__))
60
glade_file = os.path.join(script_dir, "light-locker-settings.glade")
61
self.builder.add_from_file(glade_file)
62
self.builder.connect_signals(self)
64
self.window = self.builder.get_object("light_locker_settings_window")
65
self.window.set_title(_("Light Locker Settings"))
68
''' Set background-color of frame to base-color to make it resemble the
69
XfceHeading widget '''
70
self.xfce_header = self.builder.get_object("xfce_header")
71
entry = Gtk.Entry.new()
72
style = entry.get_style_context()
73
base_color = style.lookup_color("theme_base_color")
74
self.xfce_header.override_background_color(0, base_color[1])
75
fg_color = style.lookup_color("theme_fg_color")
76
self.xfce_header.override_color(0, fg_color[1])
78
self.use_lightlocker = self.builder.get_object("use_lightlocker")
79
self.session_lock_combo = self.builder.get_object("session_lock_combo")
80
self.lock_on_suspend = self.builder.get_object("lock_on_suspend")
82
self.apply = self.builder.get_object("apply")
85
self.screenblank_timeout = self.builder.get_object(
86
"screenblank_timeout")
87
self.screenblank_timeout.add_mark(1, 3, None)
88
self.screenoff_timeout = self.builder.get_object("screenoff_timeout")
89
self.screenoff_timeout.add_mark(1, 3, None)
90
self.lock_delay = self.builder.get_object("lock_delay")
91
self.lock_delay.add_mark(0, 3, None)
92
for i in range(1, 13):
93
self.screenblank_timeout.add_mark(i * 10, 3, None)
94
self.screenoff_timeout.add_mark(i * 10, 3, None)
95
self.lock_delay.add_mark(i * 10, 3, None)
99
''' Monitor changes to the settings '''
100
self.apply.set_sensitive(False)
101
self.locksettings_changed = False
102
self.screenblank_timeout.connect(
103
"value-changed", self.screenblank_value_changed_cb)
104
self.screenoff_timeout.connect(
105
"value-changed", self.screenoff_value_changed_cb)
106
self.lock_delay.connect(
107
"value-changed", self.lock_delay_value_changed_cb)
109
# Application Callbacks
110
def screenblank_value_changed_cb(self, gparam):
111
'''Sync screenblank and screenoff settings when values are modified.'''
112
self.apply.set_sensitive(True)
114
blank_timeout = int(self.screenblank_timeout.get_value())
115
off_timeout = int(self.screenoff_timeout.get_value())
117
''' screenoff can never be shorter than screenblank-timeout '''
118
if (blank_timeout >= off_timeout) and (off_timeout != 0):
119
self.screenoff_timeout.set_value(blank_timeout)
121
def screenoff_value_changed_cb(self, gparam):
122
'''Sync screenblank and screenoff settings when values are modified.'''
123
self.apply.set_sensitive(True)
125
blank_timeout = int(self.screenblank_timeout.get_value())
126
off_timeout = int(self.screenoff_timeout.get_value())
128
''' screenoff can never be shorter than screenblank-timeout '''
129
if off_timeout <= blank_timeout:
130
self.screenblank_timeout.set_value(off_timeout)
132
def use_lightlocker_cb(self, switch, gparam):
133
'''Update the displayed lock controls when light-locker is enabled or
135
''' if on then allow for the timeout to be set '''
136
self.locksettings_changed = True
137
self.apply.set_sensitive(True)
138
if switch.get_active():
139
self.lock_delay.set_sensitive(False)
140
self.session_lock_combo.set_sensitive(False)
141
self.lock_on_suspend.set_sensitive(False)
143
self.session_lock_combo.set_sensitive(True)
144
self.lock_on_suspend.set_sensitive(True)
145
if self.session_lock_combo.get_active() != 2:
146
self.lock_delay.set_sensitive(True)
148
def on_session_lock_combo_changed(self, widget):
149
'''Update the displayed screen blanking controls when locking is
150
enabled or disabled.'''
151
self.locksettings_changed = True
152
self.apply.set_sensitive(True)
154
# Check the session lock combo:
155
# 0. lock when screensaver is activated
156
# 1. lock when screensaver is deactivated
158
active = widget.get_active()
159
self.lock_delay.set_sensitive(active != 2)
161
def lock_delay_value_changed_cb(self, gparam):
162
'''Enable saving of lock setting when the delay has been modified.'''
163
self.locksettings_changed = True
164
self.apply.set_sensitive(True)
166
def lock_on_suspend_cb(self, widget, gparam):
167
'''Enable saving when locking on suspend is changed.'''
168
self.locksettings_changed = True
169
self.apply.set_sensitive(True)
171
def apply_cb(self, button, data=None):
172
'''Apply changes and update the relevant setting files.'''
173
''' Check whether the autostart-directory exists and if not
175
autostart_dir = os.path.dirname(self.user_desktop_file)
176
if not os.path.exists(autostart_dir):
177
os.makedirs(autostart_dir)
179
self.apply_settings()
180
self.apply.set_sensitive(False)
182
def on_window_destroy(self, *args):
183
'''Exit the application when the window is closed.'''
186
def on_close_clicked(self, *args):
187
'''Exit the application when the window is closed.'''
191
def check_running_process(self, process_name):
192
"""Return True if the specified process is active."""
193
# Find the process...
194
for pid in psutil.get_pid_list():
195
p = psutil.Process(pid)
196
if p.username == username:
197
# When found, end the light-locker process.
199
if os.path.basename(p.exe) == process_name:
201
except psutil._error.AccessDenied:
205
def stop_light_locker(self):
206
"""Safely stop the light-locker process."""
207
# Find the process...
208
for pid in psutil.get_pid_list():
209
p = psutil.Process(pid)
210
if p.username == username:
211
# When found, end the light-locker process.
213
if os.path.basename(p.exe) == 'light-locker':
215
except psutil._error.AccessDenied:
218
def run_command(self, cmd, check_output=False):
219
'''Run a shell command, return its output.'''
223
output = subprocess.check_output(cmd, shell=True)
226
subprocess.Popen(cmd.split(" "))
230
def init_settings(self):
231
# Get the Settings, first from light-locker, then override as needed
232
''' if there is a file exists in ~/.config/autostart/ parse that
233
for current settings picked by the user else load in the
235
if os.path.isfile(self.user_desktop_file):
236
desktop_file = self.user_desktop_file
238
desktop_file = self.systemwide_desktop_file
239
settings = self.read_in_desktop(desktop_file)
240
use_light_locker = settings['light-locker-enabled']
241
lock_after_screensaver = settings['lock-after-screensaver']
242
late_locking = settings['late-locking']
243
lock_on_suspend = settings['lock-on-suspend']
244
lock_time = settings['lock-time']
245
screen_blank_timeout, screen_off_timeout = \
246
self.get_screen_blank_timeout()
248
# Replace settings with xfce4-session
249
if self.check_running_process("xfce4-session"):
250
session_sync = light_locker_xfsync.XfceSessionSync()
251
lock_on_suspend = session_sync.get_lock()
253
# Replace settings with xfce4-power-manager
254
if self.check_running_process("xfce4-power-manager"):
255
xfpm_sync = light_locker_xfsync.XfpmSync()
256
screen_blank_timeout, screen_off_timeout = xfpm_sync.get_dpms()
257
screen_blank_timeout = self.light_locker_time_down_scaler(
258
screen_blank_timeout)
259
screen_off_timeout = self.light_locker_time_down_scaler(
263
self.use_lightlocker.set_active(use_light_locker)
264
self.session_lock_combo.set_sensitive(use_light_locker)
265
self.lock_on_suspend.set_sensitive(use_light_locker)
267
self.lock_delay.set_value(lock_time)
269
if lock_after_screensaver:
270
self.lock_delay.set_sensitive(True)
272
self.session_lock_combo.set_active(1)
274
self.session_lock_combo.set_active(0)
276
self.lock_delay.set_sensitive(False)
277
self.session_lock_combo.set_active(2)
279
self.lock_on_suspend.set_active(lock_on_suspend)
281
blank = self.light_locker_time_down_scaler(screen_blank_timeout)
282
off = self.light_locker_time_down_scaler(screen_off_timeout)
283
self.screenblank_timeout.set_value(blank)
284
self.screenoff_timeout.set_value(off)
286
def read_in_desktop(self, filepath):
287
'''Parse the .desktop file for light-locker settings.'''
288
with open(filepath) as f:
289
self.content = f.readlines()
290
for line in self.content:
291
if line.startswith("Exec="):
292
return self.parse_options(line)
294
def parse_options(self, options_line):
295
'''Parse command-line arguments from the Exec line.'''
297
use_light_locker = False
298
lock_after_screensaver = False
300
lock_on_suspend = False
303
# Get the settings from the configuration file.
304
if "light-locker" in options_line:
305
use_light_locker = True
307
''' replace the = so we can parse it easily '''
308
options_line = options_line.replace("=", " ")
309
splitArgs = shlex.split(options_line)
311
parser = argparse.ArgumentParser(
312
description='Light Locker Settings')
313
parser.add_argument("--lock-after-screensaver")
314
parser.add_argument("--late-locking", action='store_true')
315
parser.add_argument("--lock-on-suspend", action='store_true')
316
(args, others) = parser.parse_known_args(splitArgs)
318
# Lock after screensaver
319
if args.lock_after_screensaver:
320
if int(args.lock_after_screensaver) != 0:
321
lock_after_screensaver = True
322
lock_time = self.light_locker_time_down_scaler(
323
int(args.lock_after_screensaver))
326
if args.late_locking:
330
if args.lock_on_suspend:
331
lock_on_suspend = True
334
settings['light-locker-enabled'] = use_light_locker
335
settings['lock-after-screensaver'] = lock_after_screensaver
336
settings['late-locking'] = late_locking
337
settings['lock-on-suspend'] = lock_on_suspend
338
settings['lock-time'] = lock_time
342
def get_screen_blank_timeout(self):
343
''' read in the X11 screensaver settings from bash '''
348
# Get the xset output to parse.
349
screensaver_output = self.run_command('xset q', check_output=True)
351
# Get the Screen-Blank timeout
352
screenblank_timeout_grep = re.search(
353
"timeout: *(\d+)", screensaver_output)
354
if screenblank_timeout_grep:
355
screenblank_timeout = re.findall(
356
'\d+', screenblank_timeout_grep.group(1))
357
screen_blank = int(screenblank_timeout[0]) / 60
359
# Get the Screen-Off timeout
360
screenoff_timeout_grep = re.search(
361
"Standby: *(\d+)", screensaver_output)
362
if screenoff_timeout_grep:
363
screenoff_timeout = re.findall(
364
'\d+', screenoff_timeout_grep.group(1))
365
screen_off = int(screenoff_timeout[0]) / 60
367
# Return the current timeout settings
368
return screen_blank, screen_off
371
def screensaver_label_formatter(self, screenblank_timeout, max_value):
372
'''Convert timeout values to a more friendly format.'''
373
value = int(screenblank_timeout.get_value())
377
return ngettext("%d minute", "%d minutes", value) % (value,)
379
def light_locker_label_formatter(self, light_locker_slider, max_value):
380
'''Convert timeout values to a more friendly format.'''
381
value = int(light_locker_slider.get_value())
383
formatted_string = _("Never")
385
value = self.light_locker_time_up_scaler(value)
386
formatted_string = self.secs_to_readable(value)
387
return formatted_string
389
def secs_to_readable(self, seconds):
390
'''Convert seconds to a more friendly format.'''
392
minutes = seconds / 60
393
return ngettext("%d minute", "%d minutes", minutes) % (minutes,)
395
return ngettext("%d second", "%d seconds", seconds) % (seconds,)
398
def light_locker_time_up_scaler(self, time):
399
'''Scale times up.'''
401
time = (time - 60) * 60
404
def light_locker_time_down_scaler(self, time):
405
'''Scale times down.'''
407
time = time / 60 + 60
411
def get_updated_settings(self):
412
"""Return a dictionary with the updated settings from the GUI."""
413
# Get the lock-after-screensaver timeout.
414
session_lock = self.session_lock_combo.get_active()
415
if session_lock == 2: # never lock with screensaver
419
if session_lock == 0: # lock when screensaver is activated
421
if session_lock == 1: # lock when screensaver is deactivated
423
lock_delay = self.light_locker_time_up_scaler(
424
int(self.lock_delay.get_value()))
427
lock_enabled = self.use_lightlocker.get_active()
429
# Get the suspend setting.
430
lock_on_suspend = self.lock_on_suspend.get_active()
432
# Get the screen-blank and screen-off timeout.
433
screenblank_timeout = \
434
int(self.screenblank_timeout.get_value()) * 60
435
screenoff_timeout = int(self.screenoff_timeout.get_value()) * 60
438
"lock-enabled": lock_enabled,
439
"late-locking": late_locking,
440
"lock-after-screensaver": lock_delay,
441
"lock-on-suspend": lock_on_suspend,
442
"screen-blank-timeout": screenblank_timeout,
443
"screen-off-timeout": screenoff_timeout
448
def apply_settings(self):
449
"""Apply updated settings."""
450
# Get the current settings from the GUI.
451
settings = self.get_updated_settings()
452
lock_on_suspend = settings['lock-on-suspend']
454
# If xfce4-sesssion is running, sync the lock-on-suspend setting.
455
if self.check_running_process("xfce4-session"):
456
session_sync = light_locker_xfsync.XfceSessionSync()
457
session_sync.set_lock(lock_on_suspend)
459
# If xfce4-session manages locking, disable it for light-locker.
460
settings['lock-on-suspend'] = False
462
# If xfce4-power-manager is running, sync the DPMS settings.
463
if self.check_running_process("xfce4-power-manager"):
464
xfpm_sync = light_locker_xfsync.XfpmSync()
465
screen_off = settings['screen-off-timeout'] / 60
466
screen_blank = settings['screen-blank-timeout'] / 60
467
xfpm_sync.set_dpms(screen_blank, screen_off)
468
xfpm_sync.set_lock(lock_on_suspend)
470
# If xfpm manages locking, disable it for light-locker.
471
settings['lock-on-suspend'] = False
473
# Apply the remaining settings to light-locker.
474
self.apply_light_locker_settings(settings)
475
self.apply_screen_blank_settings(settings)
477
def apply_light_locker_settings(self, settings):
478
'''Apply the light-locker settings'''
479
# Stop any running light-locker processes.
480
self.stop_light_locker()
482
lock_enabled = settings['lock-enabled']
483
late_locking = settings['late-locking']
484
lock_on_suspend = settings['lock-on-suspend']
485
lock_after_screensaver = settings['lock-after-screensaver']
488
late_locking = "--late-locking"
490
late_locking = "--no-late-locking"
493
lock_on_suspend = "--lock-on-suspend"
495
lock_on_suspend = "--no-lock-on-suspend"
497
lock_after_screensaver = "--lock-after-screensaver=%i" % \
498
lock_after_screensaver
500
# Build the light-locker command.
501
light_locker_exec = ""
503
light_locker_exec = \
504
"light-locker %s %s %s" % (lock_after_screensaver,
505
lock_on_suspend, late_locking)
507
# Save the light-locker autostart file.
508
self.write_light_locker_file(self.user_desktop_file, light_locker_exec)
510
# Execute the updated light-locker command.
511
self.run_command(light_locker_exec)
513
def apply_screen_blank_settings(self, settings):
514
'''Apply the screen blank settings.'''
515
screenblank_timeout = settings['screen-blank-timeout']
516
screenoff_timeout = settings['screen-off-timeout']
518
# Build the screen-blank/off command.
520
"xset s %i dpms %i 0 0" % (screenblank_timeout, screenoff_timeout)
522
# Execute the updated screensaver command.
523
self.run_command(screensaver_exec)
525
# Save the screensaver autostart file.
526
self.write_screensaver_file(
527
self.screenblank_timeout_desktop_file, screensaver_exec)
529
def write_light_locker_file(self, filepath, light_locker_command):
530
'''Write the updated light-locker settings to its .desktop file.'''
531
exec_str = "Exec=%s\n" % light_locker_command
532
with open(filepath, 'w') as f:
533
for line in self.content:
534
if line.startswith("Exec="):
539
def write_screensaver_file(self, filepath, screensaver_command):
540
'''Write the updated screensaver settings to its .desktop file.'''
541
with open(filepath, 'w') as f:
547
% (_("Screensaver"), _("Set screensaver timeouts"),
548
screensaver_command))
551
if __name__ == "__main__":
552
main = LightLockerSettings()