Lets start by saying that there are lots and lots of ways.
You normally setup a token/identifier when the program starts, so later instances can look for the existence of that token.
I will describe one way which uses dbus.
Overview:
When starting a program, it can register itself on the session dbus under a unique name (e.g. "org.nicklemaire.myprogram"). Further instances of the program can check if such an accesspoint is already registered, and if so, tell the program what to do via this dbus access point (e.g. get focus, open a website, play a song). The last part is probably necessary when you want behaviour similar to "firefox askubuntu.com", which opens this page in a new tab in an already running instance.
Code:
#!/usr/bin/env python
import sys
import gtk
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
from multiprocessing import Process
class MyDBUSService(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName('org.nicklemaire.myprogram', bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, '/org/nicklemaire/myprogram')
@dbus.service.method('org.nicklemaire.myprogram', in_signature='s')
def startup(self, arg):
print "got the following parameter from another instance:", arg
def call_instance():
try:
bus = dbus.SessionBus()
programinstance = bus.get_object('org.nicklemaire.myprogram', '/org/nicklemaire/myprogram')
bus = dbus.SessionBus()
programinstance = bus.get_object('org.nicklemaire.myprogram', '/org/nicklemaire/myprogram')
startup = programinstance.get_dbus_method('startup', 'org.nicklemaire.myprogram')
try:
arg = sys.argv[1]
except IndexError:
arg = ""
startup(arg)
print "Another instance was running and notified."
except dbus.exceptions.DBusException:
exit(-1) # process had an error
if __name__ == "__main__":
p = Process(target=call_instance)
p.start()
p.join()
if p.exitcode > 0: # process had an error
DBusGMainLoop(set_as_default=True)
myservice = MyDBUSService()
gtk.main()
Test:
Open a terminal and run the program: myprogram.py
. It will not terminate because we currently want to have it running and waiting for a second instance to start.
Now do this: open another terminal and run the program again, this time with an additional argument myprogram.py askubuntu.com
.
It should print: "Another instance was running and notified."
While in the first terminal, you should get an output similar to this: "got the following parameter from another instance: askubuntu.com"
The other part of your question: raising a program is described here: https://stackoverflow.com/questions/9054462/how-do-i-raise-a-window-that-is-minimized-or-covered-with-pygobject
Basically, you have to call mywindow.present()
in the startup
method.
Super + D doesn't work starting with Ubuntu 13.10. Use Ctrl + Super + D instead, I tested it and it works.
How to change the keys:
Open the Dash and type keyboard
. There should be an app called Keyboard. Click on it and then go to the Shortcuts tab. Click on the Navigation list entry and scroll down until you see Hide all normal windows, click on it and create a new shortcut, for example:
Super + D
And that's it, you're done.
Best Answer
The Keybinder library does exactly this. If you check pull requests there are requests in for examples using pygi, one of which is me for py3k.