The .desktop file has to be installed in the location where the bamf
library knows about it.
You should be able to test by copying the built .desktop file (which should be created from the .desktop.in), into your ~/.local/share/applications
folder, and running update-desktop-database ~/.local/share/applications
, though running this command may not be needed if your application does not handle any MIME types.
The difference between the .desktop and .desktop.in is that the .desktop.in is set up for being translated, and is processed by intltool during build, to have the translations inserted, creating the .desktop file from the .desktop.in file.
Also I just noticed a typo in your code:
self.launcher = Unity.LauncherEntry.get_for_desktop_id("test.destkop")
Notice the "destkop" vs. "desktop" that it should be. Perhaps this is it, if it's not a re-typing error. Assuming your code is actually being run, this is a problem. If it isn't run, then that's the problem. You can add a print('Integrating with launcher')
to the add_launcher_integration function to see. It should appear on the terminal when run.
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.
Best Answer
First, make sure you have a good reason to do this. People expect applications to work as you describe in your post. Even though you personally might not like it.
But, to answer your question, one of the easiest ways to do it is by making a file (for example in the configuration directory) at startup, which you remove when your application exits. Before starting the application, you check in your code if another instance is already active, and if so, you exit directly. If you also want to focus the active application, you need a way to do inter process communication. For example via a socket. See http://docs.python.org/library/ipc.html for more info.