bspwm workspaces not working after activating other monitor - window-managers

I'm using almost the default bspwmrcand sxhkdrc.
I'm working on a laptop and as far as I'm not connecting it to my monitor everything works just fine.
xrandr --output HDMI1 --mode 1920x1080 now breaks it. If I want to go to workspace one with Super+1 then nothing happens. Instead workspace one windows are now reachable on workspace two.
Thanks in advance!

You have to decide on xrandr output how many monitors are attached while you start BSPWM.
BSPWM is tiling window manager and it does its job very good.
start_from=1
monitors_connected=$(bspc query -M | wc -l)
per_monitor=$(( 10 / monitors_connected ))
for monitor in $(bspc query -M); do
bspc monitor $monitor -d $(seq $start_from $(( start_from + per_monitor - 1)))
start_from=$(( start_from + per_monitor ))
done
In your case, it will put first 5 workspaces on the first monitor and other 5 on external monitor.
The code above you can include inside your bspwmrc before you start some status bar program.
while pgrep -x polybar >/dev/null; do sleep 1; done
xrandr -q | awk '/ connected / {print $1}' | while read -r monitor _; do
polybar -r "$monitor" &
done
so polybar for every connected monitor will run. If there is only one monitor, nothing will happen.

Related

Keep attached screen session alive and waiting for more commands to enter from detached screens

I had this idea of a script that I was trying to make come to light. I want one main process that is running and keeping track of subprocesses running in the background. I decided to go with screen for my implementation, and I can run the main.sh in attached mode, with the subcommands all running in detached. I can also send text to the main.sh once each sub-process has hit their point. However, i want the main script to be running until all sub-processes finish (accomplished), but I want it to be updating what it is printing out to the user. I currently have the main process doing:
while screen -list | grep -q process-1 || screen -list | grep -q process-2 || screen -list | grep -q process-3; do
sleep 1
done
which works perfectly as the main loop, but any data i send to that process just prints out like text, not like a command. Is there a way I can keep a screen session alive and receiving more commands/variables?
I currently plan on sending data from the sub-process like screen -S main -X stuff "PROCESS_1=FINISHED" and the main will keep trying to grab the variable PROCESS_1 to get it's status.
I can't just get the result of the sub-process either, as for at least one of the commands i plan on it running continuously, but I want to let the main-process know when it has hit a certain point. I was also tinkering with the idea of using file descriptors but I had issues getting that working in detached mode.
Is this possible and I haven't just used/found the right command? Do i need to somehow use another screen as a like a data layer so that the main layer just prints out to the user?
For completeness, here is the current setup:
start.sh
#!/bin/bash
screen -S process-1 -dm ./process-1.sh
screen -S process-2 -dm ./process-2.sh
screen -S main -m ./main.sh
main.sh
#!/bin/bash
while screen -list | grep -q process-1 || screen -list | grep -q process-2; do
sleep 1
done
process-1.sh
#!/bin/bash
count=0
while [[ count -ne 5 ]]; do
((count+=1))
sleep 5
done
screen -S main -X stuff "PROCESS_1=FINISHED"
process-2.sh
#!/bin/bash
count=0
while [[ count -ne 3 ]]; do
((count+=1))
sleep 5
done
screen -S main -X stuff "PROCESS_2=FINISHED"
Thanks for any advice you can provide.
EDIT:
Something along these lines is the end goal, like Vue.js, a constant screen that updates whenever changes are made (or in this case processes end)

Graceful shutdown on Archlinux

Bringing this question straight from here.
I am running archlinux and I have a VM running often on it along with the system. Most of the time actually.
My goal is to produce the following behaviour:
A shutdown / poweroff / reboot / halt signal is sent to the system
No action other then trying to shut down the virtual machines gracefully
If the VMs are shut down gracefully after X seconds, proceeds with shutting down the host system too.
If not, execute a different command
Just give me a good idea on what to work on, because I don't even know from where to begin. I guess there is a call to the kernel that can be looked at.
Let me know.
My current code
At the moment I am using these scripts to gracefully shutdown my kvm virtual machines, and it works! But only as long as my user launches a shutdown or a reboot using his shell. Any other case wouldn't work.
These alias:
alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "
Are triggering this function:
#!/bin/bash
# This script checks for what is being passed to sudo.
# If the command passed is poweroff or reboot, it
# launches a custom script instead, that also looks
# fur currently running virtual machines and shuts them.
sudocheck() {
if [ $1 == "poweroff" ] || [ $1 == "reboot" ]; then
eval "sudo /home/damiano/.script/graceful $#"
else
eval "sudo $#"
fi
}
sudocheck $#
That launches this script if needed:
#!/bin/bash
i=0
e=0
## if virsh finds VMs running
virsh -c qemu:///system list | awk '{ print $3}' | \
if grep running > /dev/null ; then
virsh -c qemu:///system list --all | grep running | awk '{print "-c qemu:///system shutdown "$2}' | \
## shuts them dow gracefully
xargs -L1 virsh
## wait 30 seconds for them to go down
until (( i >= 30 || e == 1 )) ; do
## check every second for their status
virsh -c qemu:///system list --all | awk '{ print $3}' | \
if grep -E '(running|shutdown)' > /dev/null ; then
## keep waiting if still running
if (( i <= 30 )) ; then
sleep 1 && let i++ && echo $i
else
e=1 && notify-send 'Shutdown has been canceled' 'Please check the status of your virtual machines: seems like even though a stop signal has been sent, some are still running.' --urgency=critical
fi
else
## if no machine is running anymore, original power command can be executed
e=1 && eval $#
fi
done
fi
Systemd Unit
I also made the following draft, to manage the execution of my VM:
bootvm#.service
[Unit]
Description=This service manages the execution of the %i virtual machine
Documentation=https://libvirt.org/manpages/virsh.html
[Service]
ExecStartPre=virsh -c qemu:///system
ExecStart=virsh start %i
ExecStop=virsh -c qemu:///system
ExecStop=virsh shutdown %i
TimeoutStopSec=30
KillMode=none
[Install]
WantedBy=multi-user.target
But how can I tell the system to don't shut down the desktop environment, to stay as it is UNTIL the VM has been successfully shut down?
Because if the system can't shut down the vm, I want to do it while still in my DE. I don't want the computer to begin stopping all the services and remain hung until it just forces the shut down.

How to start up xmonad with apps on other workspaces

I'm trying to write an xmonad.hs which, at startup, launches some apps on some workspaces. Several of these apps (e.g., atop) will run within a terminal (urxvt being my preference).
This has been asked a few times before, e.g, here, here, and is obliquely touched on on the XMonad FAQ.
However, these rely on:
using spawnOn from XMonad.Actions.SpawnOn, which flat doesn't work (testing with urxvt, and also xclock as a simple example); it gets sent to the current workspace.
using spawn prog >> windows $ greedyView <workspace>, which kinda works, but has major timing issues - e.g., if you run two in succession, with different workspaces, both progs end up on the latter workspace. FWIW, I experimented with using threaddelay to assist; it didn't make any discernable difference, even with a 10s delay between spawns (I remembered that threadDelay is in microseconds, and so used 10000000).
rely on using general hooks for programs - meaning that whenever I start them up, they'll get sent to the given workspace. That's not what I want; I just want them placed there at startup.
Relatedly, it surprises me that the API doesn't let me start up an app and then give me a reference to that app/window (potentially with a timeout); so that I can confidently send that app/window to a workspace.
Any help would be greatly appreciated.
Install wmctrl
sudo apt install wmctrl
And create a script (in this example thunderbird on the second workspace (-t 1)):
#!/bin/sh
(thunderbird &) & sleep 5 &&
sh -c "wmctrl -i -r `wmctrl -l | grep Thunderbird` -t 1"
To know your application name on wmctrl you can view it by taping on your terminal :
wmctrl -l
And replace it with the correct name in the script.
Be carrefull with the capital letter ("Thunderbird" not "thunderbird") !!
Other example with firefox on the 3d workspace (-t 2):
#!/bin/sh
(firefox &) & sleep 5 &&
sh -c "wmctrl -i -r `wmctrl -l | grep Firefox` -t 2"
Bonus :
Here is the command to execute at start-up :
sh -c "thunderbird & sleep 5 && wmctrl -i -r `wmctrl -l | grep Thunderbird` -t 1"
Work on Debain 10 with Cinnamon. But should work for all
You can spawn the app via startupHook and then use a manageHook to handle window placement.
manageHook such as:
, className =? "deluge" --> doShift ( myWorkspaces !! 3 )
The above will actually spawn deluge on Workspace 4. In my startupHook I have
spawnOnce "deluge-gtk" to launch the app on start-up.
You would want to import XMonad.Util.SpawnOnce. doShift comes from the default XMonad.ManageHooks You could also take a look at XMonad.Actions.SpawnOn but I only use manageSpawn from that module.

Run a script on monitor connection/disconnection event

I read many threads about how to do this and yet it doesn't work for me.
What I want to achieve is:
When my laptop has 2 additional displays connected when I close its lid, I don't want it to go to sleep. However, if I disconnect the displays and the lid is closed, I want to put the laptop to sleep (this way, not forgetting it on).
Therefore, I created a BASH script that should be executed on VGA / HDMI connection events. The BASH script counts how many displays are connected and if there's only 1, it will put the laptop to sleep when the lid is closed.
I have Ubuntu 14.04 LTS. This is what I've done so far:
Created 2 files: displays_count_sleep.sh and on_hdmi_connected.rules
https://gist.github.com/nbtk123/9ffbf7541e47b9c0015f5c3e9f44b7c9
Put this on_hdmi_connected.rules into /etc/udev/rules.d to catch the event:
SUBSYSTEM=="drm", RUN+="/bin/bash /home/nir/dev/scripts/displays_count_sleep.sh"
Put the bash script I want to run, displays_count_sleep.sh, into /home/nir/dev/scripts:
#!/bin/bash
DISPLAYS_NUM=2
`touch test`
display_count=`xrandr -d :0 -q | grep ' connected' | wc -l`
echo "display count="$display_count
echo "display_num="$DISPLAYS_NUM
if [ "$display_count" -ge "$DISPLAYS_NUM" ]; then
echo "nothing"
`gsettings set org.gnome.settings-daemon.plugins.power lid-close-ac-action nothing`
`gsettings set org.gnome.settings-daemon.plugins.power lid-close-battery-action nothing`
else
echo "sleep"
`gsettings set org.gnome.settings-daemon.plugins.power lid-close-ac-action suspend`
`gsettings set org.gnome.settings-daemon.plugins.power lid-close-battery-action suspend`
fi
Both files have been created as root. When running "udevadm test", the output is as in the file 'udevadm_test_output' on the link.
I don't know if the event is catched, but on the real monitor (dis)connection, the script doesn't run. It works okay if I run it manually.

Shell script does not work when run as daemon

I got a simple script (to measure CPU overhead)
#!/bin/bash
WAIT=2
i=1
while :
do
# Obtain the cpu usage
top -n 1 > t.$i
i=$(($i+1))
sleep $WAIT
done
When I run it as
./Script.sh
It works as expected.
But when I run it as
./Script.sh&
it does nothing (files are not created). What am I missing here?
Change the line where you invoke top to be:
top -b -n 1 > t.$i
This enables batch mode - good call Karoly

Resources