Display (with Nexdock / ext display) configuration

Poor man’s kanshi:

  • make a udev rule that matches the display / any external display
  • run a script run from that rule that sets the configuration for the display that had been connected

I tried it a while a ago and didn’t get it working completely. Lost focus on that, but it has been fun to learn some udev stuff.

2 Likes

Is there info about how to use kanshi?
I simply wrote

profile default {
        output DP-1 enable scale 1.5
}

But I don’t think that is correct because running kanshi just mentions no profile matched
BTW I ran:

purism@pureos:~$ for p in /sys/class/drm/*/status; do con=${p%/status}; echo -n "${con#*/card?-}: "; cat $p; done
DSI-1: connected
DP-1: connected

I’ve also tried XWAYLAND<num> instead of DP-1

Trying to make this work but it’s not really working.
I’ve tried rule to be something like:
SUBSYSTEM=="drm", ACTION=="add", RUN+="/bin/add_nexdock.sh"

Script itself is:

#!/usr/bin/bash
echo "Start Nexdock added at $(date)" >>/tmp/scripts.log 
export DISPLAY=:0.0 
xrandr --output DP-1 --mode 1280x720 --rate 60 
echo "Done Nexdock added at $(date)" >>/tmp/scripts.log

But /tmp/scripts.log itself is not generated so I guess rule is not triggered., maybe I need more details to rule?

Also I should mention: I don’ t think xrandr is correct way of changing resolution in this case

purism@pureos:~$ xrandr --output DP-1
warning: output DP-1 not found; ignoring
purism@pureos:~$ xrandr --output XWAYLAND10

xrandr responds to XWAYLAND<num> but this value changes upon every hot-plug. And xrandr can never find mode which is not current (see below)

purism@pureos:~$ xrandr --output XWAYLAND10 --mode 1280x720
purism@pureos:~$ xrandr --output XWAYLAND10 --mode 1920x1080
xrandr: cannot find mode 1920x1080
1 Like

I haven’t tried kanshi yet (I plan to, in the coming week), but their page says that a profile is matched based on the presence of all outputs described in a profile.

So if a profile only has DP-1, it means that it will match only when you have DP-1 present — which will not happen since the L5 always has at the very least its internal display, in addition to DP-1…

So you would need a profile with both the DP-1 and the DSI-1 or whatever the internal display is called, and that would match the situation where you plug in an external display.

All the above with the caveat that I have yet to test it…

1 Like

I reviewed what I did:

  • for wayland it is wlr-randr which helps to configure the screens, e.g. wlr-randr --output DSI-1 --pos 1536,0 --output DP-1 --pos 0,0 --scale 1.25
  • I remember that my rules fired several times which led to a lot of problems. Tried to solve that by triggering a systemd .service from the udev rule. It didn’t work with the then actual version of systemd/udev. I used a version from backports which solved the problem. (250 I think).
  • in my latest attempt I used DEVPATH=="/devices/platform/soc@0/32c00000.bus/32e00000.display-controller/drm/card2/card2-DP-1", ACTION=="change", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="autowlrrandr.service" which as I beliefe enabled the autowlrrandr.service defined for my user.
  • the script I ran had to wait for the connection to settle - waiting is not allowed in udev, because a running script blocks any further processing of the udev rules. Another reason to use at (compatible with e.g. pmOS) or a systemd service
  • to debug udev rules it helped a lot to use logger to write to the journal like in RUN+="/usr/bin/logger -t 42-librem5-external-screen.rules status=$attr{card2-DP-1/status} enabled=$attr{card2-DP-1/enabled}",

If you’d like I’ll upload what I have to a repository.

Update: poor man’s kanshi

1 Like

This profile means “when there’s only DP-1 screen connected, enable it with scale 1.5”. That’s unlikely what you want to do, because you can’t disconnect the internal DSI-1 screen.

1 Like

I see, thanks
Following worked:

purism@pureos:~$ cat .config/kanshi/config 
profile default { 
	output DSI-1 enable 
	output DP-1 enable scale 1.5
}
1 Like

Thanks going to try this as well (gonna be lazy for few days cause kanshi worked but I’ll report back)

ok here’s what I did so far. I created my kanshi config:

profile nexdock {
 output DSI-1 
 output DP-1 mode 1920x1080@60Hz scale 1.1
}

profile default {
 output DSI-1
}

Then a systemd user unit file located at ~/.config/systemd/user/kanshi.service

[Unit]
Description=Kanshi display daemon

[Service]
ExecStart=/usr/bin/kanshi
Type=simple

[Install]
WantedBy=multi-user.target

then:

systemctl --user daemon-reload
systemctl --user enable --now kanshi

so now kanshi loads when I login (or when the system starts? whenever systemd user units are loaded anyway), no fiddling with udev rules. No idea how this will behave when I connect it to another display that is NOT my nexdock, either…

1 Like

this works nicely
Thanks

1 Like

I followed your steps, but kanshi does not work unless I activate it manually with a terminal command or a .desktop file that executes /usr/bin/kanshi. The only thing that I did differently was to set the kanshi config file to turn off my Librem 5 display when connected to an external display. I also ended up setting the scale to 1.5 (150%) and not specifying the refresh rate.

This is what my ~/.config/kanshi/config looks like:

profile docked {
        output DSI-1 disable
        output DP-1 mode 1920x1080 scale 1.5
}

profile default {
        output DSI-1 enable
}

So I have to click my .desktop file that executes /usr/bin/kanshi before I plug in my Librem 5 to an external monitor, in order for kanshi to work and apply my config file. I also have to click the .desktop file before disconnecting my Librem 5 from an external display, otherwise Phosh restarts (not a reboot).

I tested this, and it works with the NexDock and the Hoyoki USB-C Hub from the Purism shop, and it also works with the PinePhone USB-C Docking Bar that came with the PinePhone Convergence Package. I tested the USB-C hubs with my 55 inch 4k LG TV (WebOS), and I think that 150% scaling is good for both the TV and the NexDock. I decided not to specify the refresh rate in the kanshi config file so that the devices could set the proper refresh rate themselves, since the TV supports 120Hz.

Any idea why it doesn’t automatically work for me, requiring the manual activation?

I use OpenSnitch (v1.5.2) on my Librem 5. Could that be interferring somehow?

Honestly I’m not sure. I tried again today and noticed that my kanshi service was dead, so I had to restart it… Then it worked fine as I described.

I also tried to disable DSI-1 when I connect my Nexdock, but this has the unfortunate effect of making the on-screen keyboard not trigger, after I disconnect the phone from the dock, requiring a phosh restart. I had one time only like you described, I disconnected it and needed to ssh in to the phone to restart phosh.

So it’s not quite entirely stable I suppose… more testing/experimentation required.

User doesn’t have access to multi-user.target . It needs to be default.target
If you edit service then just reload daemon and enable again.
However this is still not complete because service fails on startup.
We need to add Restart=on-failure, but I’m yet to figure out proper way to add delay for restart

thanks for the heads up @librem5!

I’ve also updated my kanshi config to handle profiles with 2 different external monitors. Turns out you can provide the full name (as seen in wlr-randr) rather than just “DP-1”, so I got now:

profile dell {
 output DSI-1
 output "Dell Inc. DELL U3421WE JBNN653 (DP-1)" mode 2560x1080@60Hz scale 1.0
}
profile nexdock {
 output DSI-1
 output DP-1 mode 1920x1080@60Hz scale 1.5
}

profile default {
 output DSI-1
}

and for good measure, my kanshi.service now looks like:

[Unit]
Description=Kanshi display daemon

[Service]
ExecStart=/usr/bin/kanshi
Type=simple
Restart=on-failure

[Install]
WantedBy=default.target

Still not sure I should leave my L5 display on or off while connected to an external monitor, since it may or may not negatively affect Phosh when disconnecting… I’ll play around some more with that.

I got it working with kanshi using @patrix example, thanks!

Theres one thing still missing though from the original post:

This does not seem to be possible using kanshi. I know that in xrandr it is possible to set primary display, but neither kanshi or wlr-randr seems to have an option to set that?

I still have my kanshi config set to disable Librem 5 display when connected to an external display and enable Librem 5 display when disconnected from an external display. I have found that if I use the systemd kanshi.service, disconnecting my Librem 5 from an external display results in Phosh restarting 100% of the time.

Instead, I created a .desktop file that starts the kanshi service (not the systemd kanshi.service) with Exec=/usr/bin/kanshi. However, since kanshi seems to just stop working after a certain amount of time, I click the icon for the .desktop file whenever I am about to connect or disconnect my Librem 5 to/from an external display. This works 100% of the time and never results in Phosh restarting.

This is mildly inconvenient, but much better than having to open the settings app to manually set the display settings each time I want to connect to a display.

@dos, do you have any idea why kanshi stops working like this and needs to be restarted? Or why the systemd kanshi.service causes the Phosh restart when disconnecting Librem 5 from external display?

2 Likes

Can you use this setup to trigger any event? What I’m thinking is I’d like to disable screen blanking on the phone when plugged into the nexdock but then enable screen blanking when disconnected, is this possible with kanshi?

I think you can add that to systemctl service (not kanshi itself). I’ll try to read up more about services as of now I don’t know what needs to be added to prevent screen blanking

1 Like

Does this work reliably for anyone? I have the user Systemd kanshi.service but I disable the L5 display when the Nexdock gets connected. After a restart, IF it works, it works only the first time. Powering down the Nexdock and starting it up again invariable leads to a very unstable experience, to the point where I have to restart again.

Did anybody get any experience with a method that does reliably work? Clicking through GNOME settings does, obviously, but is not very convenient.

1 Like

It looks like kanshi fails because it tries to apply its config too quickly. The only thing that seems to work 80% of the time is this kludge:

~/.config/kanshi/config

profile alone {
	exec /home/purism/.config/kanshi/on-alone
	output DSI-1 enable scale 2
}

profile nexdock {
	exec /home/purism/.config/kanshi/on-nexdock
	output "Unknown NexDock 8R33926O00Q (DP-1)" enable
	output DSI-1
}

~/.config/kanshi/on-alone

#!/usr/bin/env bash

/usr/bin/wlr-randr --output DSI-1 --on
exec pkill -f -- '--app-id nexdock'

~/.config/kanshi/on-nexdock

#!/usr/bin/env bash

/usr/bin/gnome-session-inhibit --inhibit suspend:idle --inhibit-only --app-id nexdock --reason 'Nexdock session' &
sleep 3
exec /usr/bin/wlr-randr --output DSI-1 --off

So I’m basically just using wlr-randr instead of kanshi now: I only need it so I don’t have to write udev rules myself :person_shrugging:

3 Likes