You are not logged in.
I'm using a customized version of bl-exit and bl-lock along with xscreensaver instead of lightlocker. When I come out of suspend, the desktop shows momentarily, including the bl-exit GUI, and then xscreensaver kicks in with a prompt for my password (the last part is expected behavior).
I have a separate bl-exit and bl-lock under ~/bin so that my customizations do not get overwritten by an update.
My bl-exit script (lines 81-89 contain customized code provided by xaos52, or you can search for Suspend with lock function):
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# bl-exit: Bunsenlabs exit dialog, offering various exit options
# via both GUI and CLI
# Copyright (C) 2012 Philip Newborough <corenominal@corenominal.org>
# Copyright (C) 2016 xaos52 <xaos52@gmail.com>
# Copyright (C) 2017 damo <damo@bunsenlabs.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import os
display = os.environ.get('DISPLAY') is not None
import sys
import getpass
import subprocess
import dbus
import struct
import ConfigParser
__me__ = 'bl-exit'
__version__ = '2.2.1'
# Translate command-line option to method - command line only
actionToMethod = dict(
cancel='Cancel', c='Cancel',
logout='Logout', l='Logout',
suspend='Suspend', s='Suspend',
hybridsleep='HybridSleep', y='HybridSleep',
hibernate='Hibernate', i='Hibernate',
reboot='Reboot', b='Reboot',
poweroff='PowerOff', p='PowerOff'
)
class CanDoItError(Exception):
pass
class BlexitBase(object):
def __init__(self):
self.dbus_iface = None
def setup_dbus_connection(self):
try:
bus = dbus.SystemBus()
dbus_object = bus.get_object('org.freedesktop.login1',
'/org/freedesktop/login1')
self.dbus_iface = dbus.Interface(dbus_object,
'org.freedesktop.login1.Manager')
except bus.DBusException as e:
self.on_error(str(e))
def can_do_action(self, action):
# There is no 'CanLogout' method
if action == "Logout":
return "yes"
actionMethod = "Can{}".format(action)
response = self.send_dbus(actionMethod)
return str(response)
def do_action(self, action):
print_message("do_action: {}".format(action))
self.send_dbus(action)
"""Suspend with lock function. Not part of official code"""
def do_action(self, action):
print("do_action: {}".format(action), file=sys.stderr)
if action == "Suspend":
try:
subprocess.call("bl-lock")
except dbus.DBusException as e:
self.on_error(str(e))
self.send_dbus(action)
def send_dbus(self, method):
try:
if self.dbus_iface is None:
self.setup_dbus_connection()
if method[:3] == "Can":
command = "self.dbus_iface.{}()".format(method)
else:
command = "self.dbus_iface.{}(['True'])".format(method)
response = eval(command)
return str(response)
except dbus.DBusException as e:
self.on_error(str(e))
def on_error(self, string):
print_message("{} {}".format(__me__, string))
sys.exit(1)
def on_warning(self, string):
print_message("{} {}".format(__me__, string))
def openbox_exit(self):
subprocess.check_output(["openbox", "--exit"])
def logout(self):
try:
self.openbox_exit()
except subprocess.CalledProcessError as e:
self.on_error(e.output)
def action_from_command_line(self, action):
try:
self.do_action(action)
except (subprocess.CalledProcessError, CanDoItError, KeyError) as e:
self.on_error(str(e))
def main(self):
opts = get_options()
if opts.logout:
self.logout()
else:
if opts.suspend:
action = "suspend"
elif opts.hibernate:
action = "hibernate"
elif opts.hybridsleep:
action = "hybridsleep"
elif opts.reboot:
action = "reboot"
elif opts.poweroff:
action = "poweroff"
self.setup_dbus_connection()
self.action_from_command_line(actionToMethod[action])
if display:
"""Testing for display here because we want to be able to run the script
in a non-graphical environment as well. Without the test, importing
gtk.Window in a non-graphical environment spits out some errors and crashes
the application."""
import pygtk
pygtk.require('2.0')
import gtk
from time import sleep
class Blexit(BlexitBase):
"""A dialog offering the user to log out, suspend, reboot or shut down.
"""
def __init__(self, cp, config_file):
BlexitBase.__init__(self)
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_name('blexit')
self.cp = cp
self.config_file = config_file
self.debug = False
self.selectedAction = None
self.window.set_decorated(True)
self.window.connect("delete_event", self.destroy)
self.window.connect("destroy_event", self.destroy)
self.window.set_resizable(False)
self.window.set_keep_above(True)
self.window.stick()
self.window.set_position(gtk.WIN_POS_CENTER)
windowicon = self.window.render_icon(gtk.STOCK_QUIT, gtk.ICON_SIZE_DIALOG)
self.window.set_icon(windowicon)
def configure(self):
if self.config_file:
try:
self.cp.read(self.config_file)
except ConfigParser.ParsingError as e:
print_message("{}: {}".format(__me__, str(e)))
sys.exit(1)
else:
# No config file present:
# self.cp.add_section("Default")
# NOTE: add_section raises value error when the section name
# evaluates to DEFAULT (or any of its case-insensitive
# variants)
for section in "hibernate", "hybridsleep":
self.cp.add_section(section)
self.cp.set(section, "show", "never")
for section in "cancel", "logout", "suspend", "reboot", "poweroff":
self.cp.add_section(section)
self.cp.set(section, "show", "always")
def set_custom_style(self):
try:
stylesdir = self.cp.get('style', 'dir')
rcfile = self.cp.get('style', 'rcfile')
stylerc = os.path.join(os.path.dirname(self.config_file), stylesdir, rcfile)
if not os.path.isfile(stylerc):
self.on_debug("custom style rc file does not exist")
return None
gtk.rc_parse(stylerc)
settings = gtk.settings_get_for_screen(self.window.get_screen())
gtk.rc_reset_styles(settings)
except:
self.on_debug("custom style not configured or parse error")
pass
def construct_ui(self):
self.window.set_title("Log out " + getpass.getuser() + "?")
self.window.height = 80
# Cancel key (Escape)
accelgroup = gtk.AccelGroup()
key, mod = gtk.accelerator_parse('Escape')
accelgroup.connect_group(key, mod, gtk.ACCEL_VISIBLE,
gtk.main_quit)
self.window.add_accel_group(accelgroup)
self.button_width = 100
self.button_height = 50
self.button_border_width = 4
self.window.set_border_width(10)
self.button_box = gtk.HButtonBox()
self.button_box.set_spacing(0)
self.button_box.set_layout(gtk.BUTTONBOX_SPREAD)
self.build_button_visibility_array()
visible_button_count = 0
for button in self.bva:
(action, label, actionfunc, method, show, onError) = button
if not show == 0:
visible_button_count += 1
self.add_button(show, actionfunc, label=label)
self.status = gtk.Label()
label_box = gtk.HBox()
label_box.pack_start(self.status)
# allow for username of about twenty characters: len(title) + 200
# approximation: counting characters, not size of rendered string
if visible_button_count == 0:
self.window.width = len(title) + 300
elif visible_button_count <= 2:
self.window.width = max (
(self.button_width + 10) * visible_button_count,
len(title) + 300)
else:
self.window.width = -1
self.window.set_size_request(self.window.width, self.window.height)
vbox = gtk.VBox()
vbox.pack_start(self.button_box)
vbox.pack_start(label_box)
self.window.add(vbox)
self.window.show_all()
def destroy(self, widget=None, event=None, data=None):
self.window.hide_all()
gtk.main_quit()
def build_button_visibility_array(self):
"""Determine button visibily using bl-exit configuration file.
Build self.bva, an array of tuples, one entry per button,
containing (action, label, actionfunction, actionMethod, show,
onerror)
"""
self.bva = []
bva = [
('cancel', '_Cancel', self.cancel_action),
('logout', '_Log out', self.logout_action),
('suspend', '_Suspend', self.suspend_action),
('hibernate', 'H_ibernate', self.hibernate_action),
('hybridsleep', 'H_ybrid sleep', self.hybridsleep_action),
('reboot', 'Re_boot', self.reboot_action),
('poweroff', '_Power off', self.shutdown_action)
]
show_values = dict(never=0, always=1, maybe=2)
"""Values that the 'show' keyword can take in the configuration
file."""
onerror_values = dict(novisual=0, visual=1)
"""Values that the 'onerror' keyword can take in the configuration
file."""
# Per button default settings
per_button_show_defaults = dict(
cancel='always',
logout='always',
suspend='always',
hibernate='never',
hybridsleep='never',
reboot='always',
poweroff='always'
)
for (action, label, actionfunction) in bva:
# Defaults.
show = show_values[per_button_show_defaults[action]]
onError = onerror_values['novisual']
for section in ['default', action]:
try:
try:
getshow = self.cp.get(section, 'show')
if getshow in show_values:
show = show_values[getshow]
if show == 2:
candoit = self.can_do_action(
actionToMethod[action])
if not candoit == 'yes':
show = 3
self.on_debug("config section {} show={}".format(section,show))
except ConfigParser.NoOptionError as e:
self.on_debug("config section {} no option show".format(section))
pass
try:
getonerror = self.cp.get(section, 'onerror')
if getonerror in onerror_values:
onError = onerror_values[getonerror]
self.on_debug("config section {} onerror={}".format(section,onError))
except ConfigParser.NoOptionError as e:
self.on_debug("config section {} no option onerror".format(section))
pass
except ConfigParser.NoSectionError as e:
self.on_debug("config section {} not present".format(section))
pass
self.bva.append(tuple([action, label, actionfunction,
actionToMethod[action], show,
onError]))
def main(self):
self.configure()
self.set_custom_style()
self.construct_ui()
gtk.main()
def add_button(self, show, action, label=None, stock=None):
if stock is not None:
button = gtk.Button(stock=stock)
else:
button = gtk.Button(label=label)
button.set_size_request(self.button_width, self.button_height)
if show == 3:
button.set_sensitive(False)
button.set_border_width(self.button_border_width)
button.connect("clicked", action)
self.button_box.pack_start(button)
def disable_buttons(self):
self.button_box.foreach(lambda button:
button.set_sensitive(False))
def cancel_action(self, button):
self.disable_buttons()
gtk.main_quit()
def get_onerror(self):
onerror = 0
if self.selectedAction is not None:
for item in self.bva:
(action, label, actionfunction, actionMethod, show,
onerror) = item
if action == self.selected_action:
return onerror
return onerror
def on_error(self, e):
onerror = self.get_onerror()
if onerror == 0:
print_message("{}: {}".format(__me__, str(e)))
sys.exit(1)
else:
emDialog = gtk.MessageDialog(parent=None, flags=0,
type=gtk.MESSAGE_INFO,
buttons=gtk.BUTTONS_OK,
message_format=None)
if emDialog:
emDialog.set_markup("{}".format(e))
emDialog.run()
def on_warning(self, e):
e = "{} {}".format(__me__, str(e))
if self.debug:
e = "DEBUG {}".format(e)
print_message(e)
def on_debug(self, e):
if self.debug:
self.on_warning(e)
def cancel_action(self, button):
self.destroy()
def logout_action(self, button):
self.disable_buttons()
self.selected_action = 'logout'
self.status.set_label("Exiting Openbox, please standby...")
self.openbox_exit()
self.destroy()
def suspend_action(self, button):
self.disable_buttons()
self.selected_action = 'suspend'
self.status.set_label("Suspending, please standby...")
self.do_action("Suspend")
self.destroy()
def hibernate_action(self, button):
self.disable_buttons()
self.selected_action = 'hibernate'
self.status.set_label("Hibernating, please standby...")
self.do_action("Hibernate")
self.destroy()
def hybridsleep_action(self, button):
self.disable_buttons()
self.selected_action = 'hybridsleep'
self.status.set_label("Hibernating + Sleeping, please standby...")
self.do_action("HybridSleep")
self.destroy()
def reboot_action(self, button):
self.disable_buttons()
self.selected_action = 'reboot'
self.status.set_label("Rebooting, please standby...")
self.do_action("Reboot")
self.destroy()
def shutdown_action(self, button):
self.disable_buttons()
self.selected_action = 'poweroff'
self.status.set_label("Shutting down, please standby...")
self.do_action("PowerOff")
self.destroy()
class BlexitThemeDetail():
"""
:param value
Value for the theme detail
:param required
When a theme detail is not configured for a theme, and the detail
is configured as being required, the default detail value is substituted.
When required is False, nothing is substituted and the detail is not set.
Sane defaults are used.
:param value_type
'int' and 'float' are recognized.
All else defaults to 'string
"""
def __init__(self, value, required, value_type):
self.value = value
self.required = required
self.value_type = value_type
default_theme_settings = dict(
name=BlexitThemeDetail('Dark Theme', False, 'string'),
author=BlexitThemeDetail('MerlinElMago', False, 'string'),
dialogHeight=BlexitThemeDetail(120, False, 'int'),
sleepDelay=BlexitThemeDetail(0.003, False, 'float'),
overallOpacity=BlexitThemeDetail(100, False, 'int'),
buttonSpacing=BlexitThemeDetail(10, False, 'int'),
iconpath=BlexitThemeDetail('/usr/share/images/bunsen/exit', True, 'string'),
buttonImageCancel=BlexitThemeDetail('cancel.png', False, 'string'),
buttonImagePowerOff=BlexitThemeDetail('poweroff.png', False, 'string'),
buttonImageReboot=BlexitThemeDetail('reboot.png', False, 'string'),
buttonImageSuspend=BlexitThemeDetail('sleep.png', False, 'string'),
buttonImageLogout=BlexitThemeDetail('logout.png', False, 'string'),
buttonImageHybridSleep=BlexitThemeDetail('hibernate.png', False, 'string'),
buttonImageHibernate=BlexitThemeDetail('hibernate.png', False, 'string'),
windowWidthAdjustment=BlexitThemeDetail(0, False, 'float')
)
class BlexitTheme():
def __init__(self, theme, settings, blexit):
self.theme = theme
self.settings = settings
self.blexit = blexit
def set_detail(self, key, value):
self.settings[key] = value
def set_details_from_config(self, cp, default_theme):
for key in default_theme_settings.iterkeys():
default_theme_detail = default_theme_settings[key]
try:
config_value = cp.get(self.theme, key)
except ConfigParser.NoOptionError as e:
self.blexit.on_debug("theme config option {} is not set for theme {}".format(key, self.theme))
config_value = None
pass
if config_value is not None:
if default_theme_detail.value_type == 'int':
try:
config_value = int(config_value)
except:
self.blexit.on_debug("theme config option {} is not an int".format(key, self.theme))
config_value = default_theme_detail.value
elif default_theme_detail.value_type == 'float':
try:
default_theme_detail.config_value =float(config_value)
except:
self.bl-exit.on_debug("theme config option {} is not a float".format(key, self.theme))
config_value = default_theme_detail.value
else:
if default_theme_detail.required:
config_value = default_theme_detail.value
if config_value is not None:
self.set_detail(key, config_value)
class BlexitMerlin(Blexit):
"""A dialog offering the user to log out, suspend, reboot or shut down.
With a graphical UI initially developed by MerlinElMago.
:param cp: ConfigParser instance
:param config_file: path to blexit config file
"""
def __init__(self, cp, config_file):
Blexit.__init__(self, cp, config_file)
self.window.set_decorated(False)
self.tooltips = gtk.Tooltips()
def configure(self):
Blexit.configure(self)
default_theme = BlexitTheme('dark', default_theme_settings, self)
self.configured_theme = BlexitTheme(self.cp.get('theme', 'theme'), dict(), self)
self.configured_theme.set_details_from_config(self.cp, default_theme)
print_message('Loading theme \'' + self.configured_theme.settings.get('name', self.configured_theme.theme) + '\' by ' +
self.configured_theme.settings.get('author', 'not set'))
def construct_ui(self):
# get width of the monitor where the cursor is
width = 800 # fallback width
try:
display=gtk.gdk.Display(gtk.gdk.get_display())
screen, x, y, flags=display.get_pointer()
curmon = screen.get_monitor_at_point(x, y)
_, _, screenwidth, _ = screen.get_monitor_geometry(curmon)
except:
self.bl_exit.on_error('Error in construct_ui: Not running under X')
finally:
del x, y, display, screen, curmon
try:
_width_adjustment = float(self.configured_theme.settings.get('windowWidthAdjustment', 0))
if _width_adjustment > 0:
width = int( screenwidth*_width_adjustment)
if width > screenwidth:
width = -1
except:
self.on_debug('Problem with windowWidthAdjustment')
# self.icon_heights is initialized here, and appended to in add_button
# Delay setting window dimensions until after building self.bva
try:
self.icon_heights = [int(self.configured_theme.settings.get('dialogHeight'))]
except:
self.on_debug("dialogHeight is not set or is not an int")
self.icon_heights = []
pass
self.icon_widths = []
# Cancel key (Escape)
accelgroup = gtk.AccelGroup()
key, mod = gtk.accelerator_parse('Escape')
accelgroup.connect_group(key, mod, gtk.ACCEL_VISIBLE, gtk.main_quit)
self.window.add_accel_group(accelgroup)
self.button_box = gtk.HBox()
self.button_box.set_spacing(0)
try:
self.button_box.set_size_request(-1, int(self.configured_theme.settings.get('dialogHeight', -1)))
except:
self.on_debug("dialogHeight is not set or is not an int")
pass
try:
self.button_box.set_spacing(int(self.configured_theme.settings.get('buttonSpacing', 0)))
except:
self.on_debug("dialogHeight is not set or is not an int")
pass
self.build_button_visibility_array()
for button in self.bva:
(action, label, actionfunc, method, show, onError) = button
if not show == 0:
icon_width = self.add_button(show, actionfunc, label=label, btype=actionToMethod[action])
#get list of returned icon widths
self.icon_widths.append(icon_width)
self.status = gtk.Label()
if len(self.icon_heights) > 0:
self.dialogHeight = max(self.icon_heights)
else:
self.dialogHeight = -1
# set minimum window width
icons_total_w = sum(self.icon_widths)
spaces = self.configured_theme.settings.get('buttonSpacing', 0)
spacing_total = int(len(self.icon_widths))*spaces*2
if sum(self.icon_widths) > width:
width = sum(self.icon_widths) + spacing_total
self.window.set_size_request(width, self.dialogHeight)
vbox = gtk.VBox()
vbox.pack_start(self.button_box)
self.window.add(vbox)
self.window.set_opacity(0)
self.window.show_all()
try:
for o in range(1, int(self.configured_theme.settings.get('overallOpacity'))):
sleep(float(self.configured_theme.settings.get('sleepDelay')))
while gtk.events_pending():
gtk.main_iteration(False)
self.window.set_opacity(float(o)/100.0)
except:
self.on_debug("Opacity is not fully configured")
pass
self.window.set_keep_above(True)
def main(self):
self.configure()
self.set_custom_style()
self.construct_ui()
gtk.main()
def add_button(self, show, action, label=None, btype=None):
def find_image_file_for_button():
_filename = self.configured_theme.settings.get('buttonImage' + str(btype), 'nonexistant')
if _filename is None:
return None
_iconpath = self.configured_theme.settings.get('iconpath')
if _iconpath is None:
return None
for _dir in _iconpath.split(os.pathsep):
_dir = os.path.expanduser(_dir)
if os.path.exists(os.path.join(_dir, _filename)):
return os.path.join(_dir, _filename)
button = gtk.Button()
button.set_relief(gtk.RELIEF_NONE)
image = gtk.Image()
_filename = find_image_file_for_button()
if _filename is not None:
image.set_from_file(_filename)
icon_w,icon_h = self.get_image_info(_filename)
self.icon_heights.append(icon_h)
else:
image.set_from_file('/usr/share/gtk-doc/html/pygtk/icons/stock_broken_image_24.png')
self.on_warning("image file for '{}' not found.".format(str(btype)))
button.set_image(image)
if show == 3:
button.set_sensitive(False)
button.set_border_width(0)
button.connect("clicked", action)
self.button_box.pack_start(button, expand=True, fill=True, padding=0)
self.tooltips.set_tip(button, str(btype))
return icon_w
def get_image_info(self, img_path):
'''Test if icon is png, and get icon width(px),icon height(px)'''
width = -1
height = -1
try:
with open(img_path, 'rb') as f:
data = f.read()
if data[:8] == '\211PNG\r\n\032\n' and (data[12:16] == 'IHDR'): # check if png
width, height = struct.unpack('>LL', data[16:24])
except:
self.on_warning("get_image_info failed for '{}'".format(img_path))
return width,height
def print_message(m):
print (str(m), file=sys.stderr)
def get_options():
result = None
import argparse
parser = argparse.ArgumentParser(description="Bunsenlabs exit")
if display:
parser.add_argument("-l", "--logout", help="Log out",
action="store_true")
parser.add_argument("-s", "--suspend", help="Suspend",
action="store_true")
parser.add_argument("-i", "--hibernate", help="Hibernate",
action="store_true")
parser.add_argument("-y", "--hybridsleep", help="Hybrid sleep",
action="store_true")
parser.add_argument("-b", "--reboot", help="Reboot",
action="store_true")
parser.add_argument("-p", "--poweroff", help="Power off",
action="store_true")
parser.parse_args(sys.argv[1:])
"""No check if more than one option was specified. Take the first option and
discard the other"""
result = parser.parse_args()
return result
def get_config_file():
"""Determine config directory: first try the environment variable
XDG_CONFIG_HOME according to XDG specification and as a fallback
use ~/.config/bl-exit. Use /etc/bl-exit/bl-exitrc as a last
resort."""
config_file = None
config_dirs = []
xdg_config_dir = os.getenv('XDG_CONFIG_HOME')
if xdg_config_dir:
config_dirs.append(xdg_config_dir)
user_config_dir = os.path.expanduser('~/.config')
try:
if not (xdg_config_dir and os.path.samefile(user_config_dir,
xdg_config_dir)):
config_dirs.append(user_config_dir)
except OSError as e:
print_message(e)
pass
config_dirs.append('/etc')
for config_dir in config_dirs:
config_dir = config_dir + '/bl-exit'
if os.path.isdir(config_dir):
maybe_config_file = config_dir + '/bl-exitrc'
if os.path.isfile(maybe_config_file):
config_file = maybe_config_file
break
return config_file
def get_config_theme_entry(section, item, cp):
"""Get 'theme' entry from [theme] section.
:param
section: String, config section
item: String, config item
cp: ConfigParser, instance
:out
string or None"""
if (cp.has_section(section)):
try:
_item = cp.get(section, item)
except ConfigParser.NoOptionError:
_item = None
return _item
else:
return None
def main():
'''
The script works both in a graphical and a non-graphical environment.
In a graphical environment, the BlExitWindow instance is only shown when
the script is launched without arguments. The user selects the action she
wants by clicking the right button.
WHen the script is launched In a non-graphical environment the requested
action should be one of the accepted arguments and the action is executed
without asking for confirmation - as if the script was launched from the
command line.
In a non-graphical environment, one of the accepted actions must be
specified as an argument.
'''
if display and len(sys.argv[1:]) == 0:
try:
# import ConfigParser
cp = ConfigParser.RawConfigParser()
config_file = get_config_file()
if config_file:
cp.read(config_file)
_theme = get_config_theme_entry('theme', 'theme', cp)
if (_theme is not None and
_theme != 'classic'):
blexit = BlexitMerlin(cp, config_file)
else:
blexit = Blexit(cp, config_file)
else:
blexit = Blexit(cp, config_file)
except ConfigParser.ParsingError as e:
print_message(str(e))
return 1
except ConfigParser.NoOptionError as e:
print_message(str(e))
blexit = Blexit(cp, config_file)
else:
blexit = BlexitBase()
return blexit.main()
if __name__ == "__main__":
sys.exit(main())
My bl-lock script:
#!/bin/bash
#
# bl-lock: a wrapper for the 'xscreensaver-command -l' command.
# If running in live mode, offer up a prompt detailing the live session password.
# Else, run light-locker-command -l.
# Copyright (C) 2012 Philip Newborough <corenominal@corenominal.org>
# Copyright (C) 2015-2016 John Crawley <john@bunsenlabs.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
LOCK_COMMAND=(xscreensaver-command -l)
HELP=" bl-lock a wrapper for the 'xscreensaver-command -l' command
Options:
-h --help show this message
No other options are supported.
"
# look for a help option somewhere
for i in "$@"
do
case "$i" in
-h|--help)
echo "$HELP"
exit 0
;;
esac
done
which ${LOCK_COMMAND[0]} >/dev/null 2>&1 || {
echo "$0: ${LOCK_COMMAND[0]} no such command." >&2
exit 1
}
"${LOCK_COMMAND[@]}"
exit 0
Last edited by Head_on_a_Stick (2017-09-18 19:20:20)
Offline
Can you reproduce this behaviour with the stock bl-exit/bl-lock/lightlocker combination?
What is your graphics hardware?
lspci -knn | grep -iA2 'vga\|3d'
EDIT: also, I don't think jwz (the author of xscreensaver) wants you to use his program because the Debian versions are too old and users annoy him with bug reports about stuff he's already fixed.
Last edited by Head_on_a_Stick (2017-09-18 06:11:10)
Offline
The very brief time I used the stock bl-exit/bl-lock/lightlocker combo, I didn't notice the issue.
Graphics hardware...I'll have to post back later as I'm not currently using my laptop.
I think I remember reading something here or in the #! forums about the author of xscreensaver and his frustrations with Debian. Thank you for refreshing my memory. I'll look up the site and see if I can install a newer version.
Death to all #ifdefs! ??
Last edited by KrunchTime (2017-09-18 18:58:24)
Offline
The very brief time I used the stock bl-exit/bl-lock/lightlocker combo, I didn't notice the issue.
Ah, good news indeed — looks like we made the right decisions then... 8)
Offline
When I suspend my system, I don't want to be logged out. That's why I don't, and never did, like the stock bl-exit/bl-lock/lightlocker combo.
Offline
When I suspend my system, I don't want to be logged out.
Offline
I've moved this to Help & Support (Other) because the system configuration is sufficiently different from the proposed release state (ie, NOTABUG).
Offline