Setting a ROOT TApplication Icon on macos

Dear all,

I am trying without success to define the icon of my TApplication program. On linux, this is very strait forward, I just have to use TGFrame::SetIconPixmap() and its working.

On mac this is not working. I tried to convert my icon to the macos icns format, and defining the the icon of a bundle application, but without success… The only icon that is shown is the ROOT logo, but if my mac is able to find the ROOT logo, it should be possible to find my own logo no ?

Thanks

Jérémie

Hello @dudouet,

let’s ask @couet for help here.

Cheers,
Marta

I would say yes … but I do not know how it is done. I am not the author of that code. I will need to search … give me some time.

I see SetIconPixmap has a Mac implementation:

graf2d/cocoa/inc/TGCocoa.h:   void      SetIconPixmap(Window_t wid, Pixmap_t pix) override;
graf2d/cocoa/src/TGCocoa.mm:void TGCocoa::SetIconPixmap(Window_t /*wid*/, Pixmap_t /*pix*/)

but it does nothing:

//______________________________________________________________________________
void TGCocoa::SetIconPixmap(Window_t /*wid*/, Pixmap_t /*pix*/)
{
   //Noop.
}

So I do not know how this is done.

What about SetApplicationIcon ?
It looks like the name of the function is exactly what you are looking for ?

If you look at the code of this function it seems it takes $ROOTSYS/icons/Root6Icon.png has application icons. I guess if you change this picture it will change the icon of your Application ?

Yes indeed, I was also looking at this part of the code when I saw your comment. I removed it and indeed it removed the ROOT logo from the mac icon.

Now I need to understand what is done in this code to try to change it from my application…

I would first try to change the image $ROOTSYS/icons/Root6Icon.png and see if it acts on your App icon.

Looks like SetIconPixmap sets an icon for a window, not an app (in case of macOS you have app icon in a doc which can differ from an icon for some particular window). Application icon can be set using NSApplicaion.sharedApplication and its property applicationIconImage.

For a window it’s less trivial it would appear and actually assumes a proper use of AppKit and following Apples HIG. But here is how it can be done (quote from SO):

NSButton *iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton];
iconButton.image = ...;

If I replace the icon $ROOTSYS/icons/Root6Icon.png by mine, it does exactly what I wanted to. But how can I do this in my code ? What is the programation language used in TGCocoa.mm and how to integrate it in my c++ program ?

Ok so I succeeded to fix the issue. This is the first time I see Objective-C++ so this is probably not the best way to do, but it works. I had to do a wrapper class:

in CocoaWrapper.mm:

#import <Cocoa/Cocoa.h>

#include "CocoaUtils.h"
#include "TSystem.h"

void setDockIcon(const char *iconPath) {
    NSString *cocoaStr = [NSString stringWithCString : iconPath encoding : NSASCIIStringEncoding];
    NSImage *image = [[[NSImage alloc] initWithContentsOfFile : cocoaStr] autorelease];
    [NSApp setApplicationIconImage : image];
}

In CocoaWrapper.h:

#ifndef COCOA_WRAPPER_H
#define COCOA_WRAPPER_H

void setDockIcon(const char *iconPath);

#endif // COCOA_WRAPPER_H

In my code:

setDockIcon("path/to/my_icon.png");

Important thing, this has to be done after the first graphical call to TGCocoa::SetApplicationIcon() to be taken into account or it will be ignored

Then to be able to compile, I had to add the following steps in my CMakelist.txt:

adding: CocoaWrapper.mm to the list of sources of my application
adding: “-framework Cocoa” to the library links

but now it works :smiley:

Thanks for your help. Let me know if you see a simpler way to do it. Even if the easiest would have been in root to define the icon as a variable and not hardcoded, that could be changed by the user.

Jérémie

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.