Force `xscreensaver` to show itself on specific display

Is there a way to force xscreensaver to show itself during unlocking on some specific display (main) or at least on all displays at once.

Current behavior of xscreensaver seems to be showing itself only on display that had mouse when the lock happened. It is the only screen locker that I know which has this behavior and it is not what I want at all.

I searched for options in its settings and configs, but nothing came up. Also xscreensaver does not allow mouse to leave its window frame for some reason so I do not even see a work-around for typing password on main display/

I believe not.
(I’m assuming that you mean "show the password entry field ", rather than “show
xscreensaver”).

Unfortunate.
You have not actually said why you want this.
Your options are:

  • Move the mouse to the display you want to use prior to screen locking.
  • Remove xscreensaver and replace with some other option - most I am
    aware of do not provide the same security.
I never presume to speak for the Qubes team. When I comment in the Forum or in the mailing lists I speak for myself.
1 Like

There are several reasons not to move mouse manually:

  • I do not want to spend time moving mouse every single time I lock OS (I tried to write automatic script but I failed to set it as a screensaver and to be called by the system in case of timeout).
  • The locking sometimes happens by timeout, so there is nobody to move mouse before that.
  • It is ridiculous, to keep mouse cursor on one screen because screensaver application is that bad.

You could move the mouse via a script.
The tool is: xdotool mousemove 200 200 and is already installed in dom0.
Some search / test is needed to know how it works with multiple screens.

from man xscreensaver-command

For example, suppose you want to run a program that turns down the volume on your
machine when the screen blanks, and turns it back up when the screen un-blanks.
You could do that by running a Perl program like the following in the background.
The following program tracks the output of the -watch command and reacts
accordingly:

#!/usr/bin/perl

my $blanked = 0;
open (IN, "xscreensaver-command -watch |");
while (<IN>) {
    if (m/^(BLANK|LOCK)/) {
        if (!$blanked) {
            system "sound-off";
            $blanked = 1;
        }
    } elsif (m/^UNBLANK/) {
        system "sound-on";
        $blanked = 0;
    }
}

The same tricks can be done to, by example, reset the keyboard layout.
Of course, bash can be used.

There is also xscreensaver-command [-display host:display.screen] and xscreensaver [-display host:display.screen]

-display host:display.screen
The X display to use. For displays with multiple screens, XScreenSaver will manage all screens on the display simultaniously.

Not sure if it does what you want, probably not, worth a try…

I don’t have a second screen to test any of these method.

2 Likes

Thanks a lot for this information.

That exactly what I tried to do: I wrote a wrapper-script (on Bash) to change keyboard layout to en, change mouse position to the first physical display, and finally start xscreensaver from script.

And mouse movement though xdotool works for multiple display configuration - I checked it back in the day.

The problem with all this hacks that stopped me: I was not able to replace xscreensaver with this script. I don’t remember reasons, but either xscreensaver was not acting properly being called like that, or system was not calling this script in case of system idle timeout as I would want. Something like that. So I decided not to use this script due to these issues. Calling the script manually was working, so the code inside was functioning.

And about -display flag - it is not what is needed, in Qubes OS user have 1 display in these terms, but with total maximum dimensions of all physical displays configured. So, I also checked this and it was not working too.

Maybe somebody has a positive experience with hack like that?

You do not want to replace xscreensaver with your script.

You want to run a script in the background to listen xscreensaver event.

Use $HOME/.config/autostart, systemd, session and startup or whatever to run
your script that will listen the xscreensaver event and reacts accordingly.

I didn’t try, but I will if your fail to do so.
I’m pretty sure you will success. :slight_smile:

2 Likes

Thanks a lot! It actually works, and now I like xscreensaver a bit more :slight_smile:

I will publish the resulting bash script a bit later.
Maybe even guide for that change should be added to wiki.

2 interesting things about the solution:

  1. There is not way to run something BEFORE lock, because xscreensaver has no such event. So we are kind of lucky that it works. Even if xdotool moves cursor after lock - the target screen for password prompt changes.
  2. After xdotool moves cursor - the password prompt immediately pops up. But if the script calls xscreensaver-command -activate after xdotool mousemove - it looks like the prompt does not appear after all.

These 2 details allow the solution to work, just by pure luck. If wished xscreensaver was more technically advanced, adding pre-lock event would not affect security.

The event is BLANK.
If you have the Lock Screen After set to 0. They (BLANK & LOCK) happens almost at the same time.
Therefore when you enter in the if (m/^(BLANK)/) condition, the screen is already locked.

[user@dom0 ~]$ cat x.pl 
#!/usr/bin/perl

my $blanked = 0;
my $locked = 0;
open (IN, "xscreensaver-command -watch |");
while (<IN>) {
    if (m/^(BLANK)/) {
        if (!$blanked) {
            system 'xdotool mousemove 200 200';
            system 'xscreensaver-command -activate';
            $blanked = 1;
        }
    } elsif (m/^LOCK/) {
        if (!$locked) {
            $locked = 1;
        }
    } elsif (m/^UNBLANK/) {
        $blanked = 0;
        $locked = 0;
    }
}

In this example, the unlock prompt will keep showing up, for the reason mentioned above ( Lock Screen After is set to 0).

[user@dom0 ~]$ ./x.pl 
xscreensaver-command: ClientMessage ignored while authentication dialog is active

The ClientMessage ignored is: xscreensaver-command -activate

To do somethings before the screen lock, just set the Lock Screen After to 1 minute.

[user@dom0 ~]$ ./x.pl 
xscreensaver-command: activating.

xscreensaver-command: already active.

the message xscreensaver-command: already active. happens because we have manually
enable the xscreensaver and I guess it got the message twice (our command and the ‘normal’ idle thing).
It’s ok, and the unlock prompt will not be showed.
In fact, the screen will blank, unblank (when the mouse get moved), and then blank again.
And after 1 minute, the screen will be locked.

You can also disable Lock Screen After and use xscreensaver-command -lock instead
of -activate in your script.
(I do not recommend, if the script fail to start, the screen will not be locked).

It is expected behaviour, xscreensaver detect an user activity (the mouse movement).

Don’t know why the unlock prompt showing up is an issue for you, it will disapear after 30s.

This is not luck, it’s how it works.

To do more test, run your script in a terminal (not in the background, to see the output).

1 Like

Because it changes the expected behavior. Instead of “Goes blank->Locks” we get “Goes blank->Goes bright and locks->blanks again”. I like to keep the original behavior.

Well, the Blank is a different thing, between blank and lock there can be a lot of seconds as I understand. And during this time window the lock process can even be canceled (prevented). So the proper way to do it would be fire another event, like PRE-LOCK, that happens just moments before lock. Still not a perfect way due to the lack of feedback from the event listeners.

But it will not be “before lock”, it will be “1 minute before lock”. Do I get it right?
And in case user does something in this minute - the lock will be cancelled and script would be in fact run not “before lock” at all.
Right?

Showing the unlock prompt when you move the mouse (manually or with xdotool) is the expected behaviour.
I you just use xdotool, it does what you want (showing the unclock on specific display).
To me, trying to hide the unlock prompt is a non-issue.

What are you trying to do ?
mousemove works when locked.
I guess keyboard layout switch also works when locked.

When xscreensaver activate, you suppose to not be there ?
If you activate it manually, you suppose to go somewhere else ?

But I do not want to move the mouse.
I want xscreensaver to show password message always on one specific display, not kind of random one based on mouse pointer position before lock (I consider it to be ridiculous and unconvinent). But xscreensaver do not have such option in config, so I have to move the mouse to the specific display before or just after lock to emulate this feature. But I do not want to see any artifacts due to this work-around, the behavior of screensaver should stay the same.

There are 2 cases:

  1. I press Lock shortcut. I do not want to see lock screen, just everything blank, like what I have by default without xdotool hack.
  2. I am not in front of the PC, but even in this case the screen should not get bright after being dark, because undesired password prompt is bright.

Probably, and I want the screen to immediately go black as it happens for all other users.

OK.
Here is my current solution made in Bash xscreensaver_prelock_fixes.sh:

#!/bin/bash

function run_prelock_fixes() {

    # Move to the first display, to force xscreensaver show unlock screen only there
    # I prefer the position mouse to the center of the Q logo on the lock screen
    # But you may want to use display center or even top-left corner (0; 0)
    xdotool mousemove '960' '540'
    # Top-left corner (0; 0)
    # xdotool mousemove '0' '0'

    # Set us layout before lock
    xkb-switch -s us
}

process_watcher() {
    while read -r str; do
        case "${str}" in
            LOCK*)

                # Run pre-lock fixes
                run_prelock_fixes

                # We have to manually blank again because mouse movement un-blanks
                # I think unfortunately it does not work this way
                # /usr/bin/xscreensaver-command -activate
            ;;
        esac
    done
}

/usr/bin/xscreensaver-command -watch | process_watcher

I start this xscreensaver_prelock_fixes.sh on login using simple ~/.config/autostart/*.desktop file that can be automatically generated in XFCE via Settings ManagerSession and StartupApplication AutoStart.

1 Like

@balko
I fear that what you want cannot be provided by Xscreensaver.
You know there is no configuration option for this.
There is a simple work round - move the mouse.
@szz9pza showed you how to move the mouse automatically.
That has a consequence you do not like.

At this stage you have 4 options - (2 more than the last time I
commented) -
a. Move the mouse to the display you want to use before screen locking.
b. Use @szz9pza type script to automate moving the mouse.
c. Patch Xscreensaver to provide the option you want.
d. Remove Xscreensaver and replace with some other option - most I am
aware of do not provide the same security.

Other options may be available.

1 Like

I already solved the issue by implementing own script in bash (I do not use Perl), check out the script above.
Also I solved the issue caused by xdotool mousemove the way I explained in the script.

Another advantage of having this script - you do not have to worry about selected keyboard layout, because xscreensaver is probably the only locker that has no layout indicator for password prompt. This script changes layout to us. Note, that installation of xkb-switch in dom0 is required: sudo qubes-dom0-update xkb-switch.

<This paragraph was probably wrong, so I removed it>.

Nice - good work.

1 Like

Thank you, unman.


About the /usr/bin/xscreensaver-command -activate in the script, I think I was wrong. It is probably ignored. But when I press lock keyboard shortcut (using my script above), sometimes I see password prompt and sometimes I do not.
I think it can be because of a race condition - sometimes xdotool moves the mouse cursor before xscreensaver starts monitoring cursor movement and sometimes after. That is why behavior of xscreensaver changes kind of randomly. I mistakenly thought that it changed due to this re-activate call from the script.