Reputation: 10030
How do I change the application title in the Mac menu bar programmatically (after starting the application)?
I know that I can set it before running the program via CFBundleName in the Info.plist file. However, I need to change it after initializing the application. Manipulating my own Info.plist also won't work.
There is no official API to do so, but in this discussion someone hinted that there is a secret function call that changes the bundle name / menubar title:
"There is SPI you can use if you look hard enough around for it, but I'm not going to point anybody to it unless they can justify why they need to use it :-)"
I think Java uses something similar, too. So what's the secret API?
Upvotes: 3
Views: 975
Reputation: 10030
OK, I've found a way. This is the code in Python (taken from here). It could use some cleaning and some error handling, but it works. The key is the undocumented CPSSetProcessName from ApplicationServices.
def _osx_set_process_name(app_title):
""" Change OSX application title """
from ctypes import cdll, c_int, pointer, Structure
from ctypes.util import find_library
app_services = cdll.LoadLibrary(find_library("ApplicationServices"))
if app_services.CGMainDisplayID() == 0:
print "cannot run without OS X window manager"
else:
class ProcessSerialNumber(Structure):
_fields_ = [("highLongOfPSN", c_int),
("lowLongOfPSN", c_int)]
psn = ProcessSerialNumber()
psn_p = pointer(psn)
if ( (app_services.GetCurrentProcess(psn_p) < 0) or
(app_services.SetFrontProcess(psn_p) < 0) ):
print "cannot run without OS X gui process"
print "setting process name"
app_services.CPSSetProcessName(psn_p, app_title)
return False
If you call it right away, it changes the process name in the Activity Monitor. I had to call it after a small timeout for some reason to also change the Menubar name:
import gobject
gobject.timeout_add(100, _osx_set_process_name, "MyTitle")
Note that if you combine this with an .app package you can get a really nice system integration of a python app. While you can change the Icon, the Finder display name, ..., all methods I tried leave the CFBundleName (the one in the Menu bar) to "Python". (This answer for example only changes the long name (displayed over dock icons). There are plenty others that almost work.)
While this answer gives the intended result, it's not very elegant. I'd appreciate some insight into why I need the timeout... I think Python or pygtk changes the process name itself when I first import gtk or run the main loop.
Upvotes: 1