Stop X11 app from bouncing dock icon indefinitely

Alec Jacobson

September 30, 2013

weblog/

Freeglut (unfortunately) uses X11 as a windowing system. This means ugly, non-native windowing on mac os x, but also seems to mean that it doesn't play nicely with .app bundling. Bundled X11 apps create two dock icons. One for the individual app and then one for X11 (if it's not already there). Upon appearing, the applications icon bounces indefinitely even though the X11 windows have opened and are working properly. It seems the only way to fix this is to trigger some event that's caught by the Carbon or Cocoa API of Mac OS X.

So here's an example of my hacky solution.

#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>

#include <CoreFoundation/CoreFoundation.h>
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include <iostream>
// Stop bouncing dock icon.
// 
static inline void cocoa_says_stop_bouncing()
{
  id app = NULL;
  id pool = objc_getClass("NSAutoreleasePool");
  if (!pool)
  {
      std::cerr << "Unable to get NSAutoreleasePool!\nAborting\n";
      return;
  }
  pool = objc_msgSend(pool, sel_registerName("alloc"));
  if (!pool)
  {
      std::cerr << "Unable to create NSAutoreleasePool...\nAborting...\n";
      return;
  }
  pool = objc_msgSend(pool, sel_registerName("init"));
  app = objc_msgSend(objc_getClass("NSApplication"),
    sel_registerName("sharedApplication"));
  id req = objc_msgSend(app,sel_getUid("requestUserAttention:"),0);
  objc_msgSend(app,sel_getUid("cancelUserAttentionRequest:"),req);
  objc_msgSend(pool, sel_registerName("release"));
}

void display()
{
  glClearColor(1,0.8,0.8,1);
  glClear(GL_COLOR_BUFFER_BIT);
  glutSwapBuffers();
  glutPostRedisplay();
}

int main(int argc, char** argv)
{
  glutInit(&argc,argv);
  glutCreateWindow("test");
  // Must come after glutCreateWindow
  cocoa_says_stop_bouncing();
  glutDisplayFunc(display);
  glutMainLoop();
  return 0;
}

Assuming you install freeglut with macports, then compile with:

g++ -framework Cocoa -o test test1.cpp -L/opt/local/lib -lglut -framework OpenGL

Then bundle into a test.app directory using

build_app test

and then double-click on your app and stand back, relieved that the bouncing has ceased.

Source, Other