How To: Refresh your status bar in response to a hotkey - Desktop Customization & Workflow
Users browsing this thread: 2 Guest(s)
|
|||
(This post tries to explain how every part works in some detail. If you're just interested in code to copy/paste, look at the end of the post.)
A lot of you are probably using status bars where the actual status bar process just essentially renders the text printed by a script. I know at least both swaybar and i3bar work like that. A simple status script would be this: Code: update() { That works well enough, it shows the current volume of your audio devices and shows the current date. However, it's not great; it only updates once every 5 seconds, which makes it annoying to use to adjust your volume. You could decrease the update interval, but it would be stupid to have a status script running every 100ms when nothing almost ever changes. One decent solution would be to make the status script update after your Code: pactl set-sink-volume @DEFAULT_SINK@ +10% A signal is basically one of the ways a Unix-like kernel (like Linux) can use to communicate with its processes. The kernel sends a SIGSEGV signal ("Segmentation Fault") when the application tries to access memory it's not supposed to, it sends a SIGWINCH signal when the terminal window's dimensions changes, it sends a SIGINT signal when you interrupt the process (such as by hitting ctrl-c in a terminal), it sends a SIGCHLD signal when a child process terminates. Processes can install signal handlers, which is code which is executed when the process receives a signal. Gracefully, the designers of Unix gave us two signals which don't have any semantic meaning in and of themselves; SIGUSR1 and SIGUSR2. The purpose of these signals is to trigger application-specific behavior. We can make the script call the update function again when it receives the SIGUSR1 signal: Code: update() { This does two things: it "traps" the SIGUSR1 signal (this gets rid of the default SIGUSR1 behavior, which is to exit the process), and it replaces the sleep 5 with sleep 5 & wait $!. The meaning of sleep 5 & wait $! is basically: "Spawn a new background child process (sleep 5), and wait for it to exit", but the crucial difference is that the "wait" command is aborted when a signal is received. (The $! variable always refers to the previous background process that was spawned, in this case the sleep process.) So now, when we send our script a SIGUSR1 signal, it will instantly print a new status line. Now we need to run Code: kill -USR1 <our script's process ID> Code: update() { The $$ variable always refers to the PID of the currently executing script. Now, everything that remains is to add Code: kill -USR1 "$(cat "/tmp/status-$USER.pid")" Code: pactl set-sink-volume @DEFAULT_SINK@ +10% && kill -USR1 "$(cat "/tmp/status-$USER.pid")" Here's my status script, which uses something like what's described here to update in response to my hotkeys: https://github.com/mortie/dots/blob/mast.../status.sh |
|||
|
|||
Hey mort,
Thanks for sharing, it's easy to forget how many moving parts there are when you want something that can feel 'simple' on these systems. I like the trap wrapper for just passing in "reload" to your script. For what it's worth I currently use i3block[1] as a statusbar manager, which has a configuration option for associating signals with 'blocks' to do a refresh -- I wonder how many of these "status bar managers" support interrupts like this [1] https://github.com/vivien/i3blocks |
|||
|
|||
Big thanks Mort for this write up. I will certainly be playing around with it so that my spectrwm baraction.sh script isn't calling wttr.in EVERY SECOND! lol. For real tho, I've disabled it for now and have pushed it back to reload every 10 seconds (I hardly adjust the volume anyway).
While I am a complete novice when it comes to writing scripts (or any code for that matter) I have been able to get by for several years just tinkering and tweaking scripts I find on the web and learning as I go. You've explained the functions well in this write up which makes me feel like I've learned something so cheers!
_____________________________________________________________________________________________
“Maybe you have some bird ideas... Maybe that's the best you can do.” - Terry A. Davis (R.I.P Terry & Percival) |
|||
|
|||
This is great. I'm not as smart as mort, but I've tried to combat this same problem using fifos. Something like:
Code: tail -n1 -F FIFO | while read vol; do Can't be worse than checking the volume every second right?? |
|||
|
|||
Ok, so I've tried but I cannot get this working. My config is below:
PHP Code: #!/bin/sh I've also added this to my .spectrwm.conf PHP Code: # Volume Keys
_____________________________________________________________________________________________
“Maybe you have some bird ideas... Maybe that's the best you can do.” - Terry A. Davis (R.I.P Terry & Percival) |
|||
|
|||
The version without a PID file:
Code: #!/bin/sh Let’s say, you saved this as "update_bar.sh". Your key binds would then look like this: Code: # Volume Keys Saves you the trouble of dealing with a PID file, which can contain a wrong PID. This version uses "pkill" to scan through all running processes and send the signal to the ones matching the pattern. (This still assumes that spectrwm runs key binds using "sh -c ...". Don’t know if that’s true.) |
|||
|
|||
Yeah, this actually makes sense to me. I will try this later tonight and let you know if it worked. Cheers
_____________________________________________________________________________________________
“Maybe you have some bird ideas... Maybe that's the best you can do.” - Terry A. Davis (R.I.P Terry & Percival) |
|||
|
|||
So it would appear that this does not work for me... Perhaps because the bar.sh is called by spectrwm itself and is only reloaded when the wm itself is reloaded? I'll try and find a way around it.
_____________________________________________________________________________________________
“Maybe you have some bird ideas... Maybe that's the best you can do.” - Terry A. Davis (R.I.P Terry & Percival) |
|||
|
|||
This is much more difficult than I expected. How would you update something like - current machine's IP, Weather, BTC price, your inbox from mutt etc? These things do not require frequent updates, but also have no shortcuts to bind them to... I want to hack something for lemonbar, but can't figure out how to make different delay for different functions.
|
|||
|
|||
(02-12-2020, 07:30 PM)stratex Wrote: These things do not require frequent updates, but also have no shortcuts to bind them to... The trick here is: Code: kill -USR1 "$(cat "/tmp/status-$USER.pid")" |
|||
|
|||
> This is much more difficult than I expected. How would you update something like - current machine's IP, Weather, BTC price, your inbox from mutt etc? These things do not require frequent updates, but also have no shortcuts to bind them to... I want to hack something for lemonbar, but can't figure out how to make different delay for different functions.
I personally cheat. I have a command cache_output[1] and I'll set the cache time to like 10 minutes for stuff like weather. That way, regardless of panel toggle status, I'm not doing "heavy" things. [1] https://github.com/neeasade/dotfiles/blo...che_output edit: see also: https://nixers.net/Thread-My-panel-scripts |
|||