You are not logged in.

#1 2017-09-18 04:28:15

KrunchTime
Member
Registered: 2015-09-29
Posts: 857

[Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

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

#2 2017-09-18 06:07:50

Head_on_a_Stick
Member
From: London
Registered: 2015-09-29
Posts: 9,093
Website

Re: [Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

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

#3 2017-09-18 18:57:54

KrunchTime
Member
Registered: 2015-09-29
Posts: 857

Re: [Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

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

#4 2017-09-18 19:09:07

Head_on_a_Stick
Member
From: London
Registered: 2015-09-29
Posts: 9,093
Website

Re: [Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

KrunchTime wrote:

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

#5 2017-09-18 19:12:19

KrunchTime
Member
Registered: 2015-09-29
Posts: 857

Re: [Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

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

#6 2017-09-18 19:14:48

Head_on_a_Stick
Member
From: London
Registered: 2015-09-29
Posts: 9,093
Website

Re: [Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

KrunchTime wrote:

When I suspend my system, I don't want to be logged out.

https://forums.bunsenlabs.org/viewtopic.php?id=2080

Offline

#7 2017-09-18 19:19:41

Head_on_a_Stick
Member
From: London
Registered: 2015-09-29
Posts: 9,093
Website

Re: [Helium-Dev (sort of)] Quirky Behavior Coming Out of Suspend

I've moved this to Help & Support (Other) because the system configuration is sufficiently different from the proposed release state (ie, NOTABUG).

Offline

Board footer

Powered by FluxBB