You are not logged in.
Often when my wife hits a keyboard command to launch a program she is either impatient and hits it too much or holds the key down - this can lead to multimple instances of a program launching.
Now I have altered my keyboard shortcuts to be like this
~/mybin/start-one-instance-of firefox
~/mybin/start-one-instance-of chromium
~/mybin/start-one-instance-of gimp
~/mybin/start-one-instance-of skype
~/mybin/start-one-instance-of abiword
(noted this does not work for Chromium seemingly because each tab is an instance)
etc so that all programs are launched via a script where the program name is passed to the script as a variable.
the script (requires zenity for user feedback but can be reworked to xmessage or even no feedback at all)
#!/bin/bash
# script is called with scriptname programname and program name becomes $1
# we then use the variable name myprog to refer to this value in the script
myprog=$1
# sleep time before checking, can be 0 (zero)
mytime="0"
###
# program starts here
###
echo "Looking for multiple instances of $myprog ..."
# Snooze here to let system settle if required
sleep $mytime
mypid="$(pidof $myprog)"
echo "$mypid"
if [ $mypid -ge "1" ]
then
# one $myprog - we have a genuine pid
# expr fails with multiple pids or no pid at all
echo "one $myprog loaded, all good"
zenity --title="Launch $myprog" --warning --text="$myprog is already running" --timeout="3"
else
## optionally completely kill the program
## no need to do this in most cases
#echo "killing $myprog"
#killall $myprog
#sleep 1s
echo "loading one instance of $myprog"
# load just one instance of program (in the background (&))
$myprog &
fi
exit
Last edited by tawan (2011-01-30 07:14:55)
Offline
I think the StumpWM way is better. It has a nice run-or-raise function, that uses WM_CLASS etc, so it also works for Chromium etc. C-t e does that for Emacs by default, and you can create your own commands, like so:
(defcommand chromium () ()
(run-or-raise "chromium" '(:class "Chromium")))
(define-key *root-map* (kbd "b") "chromium")
Awesome can also do this IIRC.
Offline
Well, you can switch WM, or implement run-or-raise as a standalone program.
Offline
Now requiring wmctrl the script will call a program to focus if it already running, even switch you to the relevant desktop.
added
# try to bring it to focus
wmctrl -a "$myprog"
#!/bin/bash
# edit as you need
# name of program you want one instance of
myprog=$1
# sleep time before checking, can be 0 (zero)
mytime="0"
###
# program starts here
###
echo "Looking for multiple instances of $myprog ..."
# Snooze here to let system settle if required
sleep $mytime
mypid="$(pidof $myprog)"
echo "$mypid"
if [ $mypid -ge "1" ]
then
# one $myprog - we have a genuine pid
# expr fails with multiple pids or no pid at all
echo "one $myprog loaded, all good"
# try to bring it to focus
wmctrl -a "$myprog"
zenity --title="Launch $myprog" --warning --text="$myprog is already running" --timeout="3"
else
## optionally completely kill the program
## no need to do this in most cases
#echo "killing $myprog"
#killall $myprog
#sleep 1s
echo "loading one instance of $myprog"
# load just one instance of program (in the background (&))
$myprog &
fi
exit
Offline
Hey.
There's a teensy problem with that approach. wmctrl -a won't work if it's an ncurses program that doesn't set the terminal title for example or if it runs inside screen but isn't focussed.
Looking into that i found you can get the xid as well by looking into /proc/$pid/environ. It's a binary file that usually contains XINDOWID=$xwindowid.
Just my 2 cents
ADD:
I've found the following a nice way around it
sed -n 's|.*WINDOWID=\([0-9]*\).*|\1|p' /proc/$(pgrep cmus)/environ
As an example
hacked away and it's fugly not formatted, happy for any pointers to improve it.
you'd put it in your menu or keys file in fluxbox e.g. with myscript.sh $APPNAME and urxvt -e if it's a terminal app, e.g.:
myscript.sh mocp urxvt -e
That will either start it in new Terminal then which you'd have to edit inside the script to whatever you use, or use wmctrl -a to raise and focus. also can deal with stuff like mocp that spawns multiple processes. Well here it is:
#!/bin/sh
if ! [ $1 ] ; then exit ; fi
if [ -z "$(pgrep $1)" ] ; then ${@:2} $1 ; exit ; fi
for i in $(pgrep $1); do if (( $(cut -d " " -f 7 /proc/${i}/stat) )) ;then wmctrl -i -a $(sed -n 's|.*WINDOWID=\([0-9]*\).*|\1|p' /proc/${i}/environ ) ;fi;done
Last edited by demonicmaniac (2011-02-27 15:28:58)
Offline