Setting a window icon


#1

Hi,

I want to set up the window icon for a DocumentWindow, at the moment it's always showing some default icon. The window is using a native title bar. Calling window->setIcon(img) doesn't have any effect in this case (it just repaint the title bar drawn by JUCE if present), so I would call window->getPeer()->setIcon(img).

But this call doesn't have any effect either. I can call setIcon before or after the window is visible. It just doesn't work. The only way I can make it work is by inserting a call to setIcon() with some hard coded image just before the call to XMapWindow in LinuxComponentPeer::setVisible(). So maybe X11 requires the icon to be set before mapping the window?

--
Roeland


#2

Here is the code I have...including the comment I wrote about a year ago when I first started playing with this on linux:

setUsingNativeTitleBar( true );
// setting the icon has to be done after setUsingNativeTitleBar() otherwise it doesn't work
setIcon( foobar::logo() );
ComponentPeer *peer = getPeer();
if ( peer )
{
    peer->setIcon( foobar::logo() );
}

I'm not sure how much of this code is still necessary.  But the fact that you're asking about it would indicate some sort of trick is still necessary.


#3

You're correct, it has to be done after calling setUsingNativeTitleBar(), and also after calling setResizable(). And the rest of this code is definitely still necessary.

Jules, I think on both Windows and Mac all windows are getting the application icon by default. Do you think it would be possible to have this on Linux as well?

--
Roeland


#4

+1 - StephaneCharette's code A-OK on LXDE


noticing the cautious validation of getPeer() raises the question "what could be the worst case if getPeer() returned null here?" (presumably in the MainWindow constructor) would that not be a total disaster for the entire application regardless of this icon business ?

the docs say:

This may return nullptr if there isn't a desktop component.

in which cicumstance might that be true - like a raw X environment ?

so just how naughty would this be anyway (in the MainWindow constructor)?

getPeer()->setIcon(icon_image) ;

 


#5

@jules @fabian -

i am still curious why getPeer() may ever return null - the implication seems to be that there is no X window for JUCE to draw on - i assume this should be true for a newly created component that is not itself or has no ancestor that is attached to the desktop - but in the context of adding a window icon in the init MainWindow constructor would this be more reasonable way to handle a null ComponentPeer?

if ( getPeer() ) getPeer()->setIcon( foobar::logo() );
else             quit();

or perhaps ths is the intended use case for isValidPeer()?

ComponentPeer::isValidPeer( getPeer() )

#6

If you create a component but don’t add it to a parent or put it on the desktop, then it’s simply an object in memory, with no peer.


#7

ok i assumed so much - but my concern is that in the context of the mainWindow constructor addToDesktop() is done by default in a superclass ResizableWindow::initialise() - so a null ComponentPeer in the mainWindow constructor would be an unrecoverable error yes? so the only sensible thing to do would be to terminate the program

  class MainWindow : public DocumentWindow
  {
    MainWindow() : DocumentWindow( ... )
    {
      if ( getPeer() != nullptr ) getPeer()->setIcon( ... );
      else                        quit(); // or throw exception
    }
  }

#8

Well, you should just make sure you don’t create the icon until your window has been added to the desktop, right…? Can’t really see the issue here… The constructor’s not a particularly great place to set an icon, you should maybe do it in the window’s parentHierarchyChanged callback or some other time after you know the window has been shown.

…and guys, your code examples above hurt my eyes! Do yourselves a favour and get into the habit of always using this pattern when testing and using a pointer:

if (auto peer = getPeer())
    peer->etc