Hello all, I'm looking into making an object oriented toolkit and have ran into a bit of a snag with glut's idle function callback. The problem is that I can't seem to attach a dedicated idle function callback on a per-window basis. Is there any way to make glut accept idle functions on a per-window basis? Thanks for any help.

Below is what I have mocked together so far (It's a bit long, but cannot be further compressed for a SSCCE, sorry):
(Note: The code is in C++11, only Clang is supported, though GCC *might* work)

Code :
#ifndef BOOTSTRAP_HPP
#define BOOTSTRAP_HPP
 
#include <iostream>
#include <map>
 
#include "Platform.hpp"
 
namespace detail
{
    struct VirtualBootstrap
    {
      protected:
        static thread_local bool glew_initialized;
      public:
        virtual void idle() = 0;
        virtual void tick() = 0;
        virtual void render() = 0;
        virtual ~VirtualBootstrap() = default;
    };
 
    thread_local bool VirtualBootstrap::glew_initialized = false;
 
    thread_local std::map<int, VirtualBootstrap*> bootstraps;
 
    template<int N>
    void register_this(VirtualBootstrap* bootstrap) noexcept
    {
        bootstraps.insert(std::make_pair(N, bootstrap));
    }
 
    template<int N>
    void unregister_this() noexcept
    {
        bootstraps.erase(N);
    }
 
    template<int N>
    void glutDisplayFuncDelegate()
    {
        std::cout << N << " rendering" << std::endl;
        bootstraps[N]->render();
    }
 
    template<int N>
    void glutIdleFuncDelegate()
    {
        std::cout << N << " idling" << std::endl;
        bootstraps[N]->idle();
    }
}
 
template<int N>
class Bootstrap : public detail::VirtualBootstrap
{
  public:
 
    Bootstrap(int windowWidth, int windowHeight)
    {
        glutInitWindowSize(windowWidth, windowHeight);
        glutInitWindowPosition(100, 100);
        glutCreateWindow((std::string("Bootstrap Test (") + std::to_string(N) + ")").c_str());
        if(!glew_initialized)
        {
            glewInit();
            glew_initialized = true;
        }
        glutDisplayFunc(detail::glutDisplayFuncDelegate<N>);
        glutIdleFunc(detail::glutIdleFuncDelegate<N>);
        detail::register_this<N>(this);
    }
 
    virtual ~Bootstrap()
    {
        detail::unregister_this<N>();
    }
};
 
template<int N>
class TestBootstrap : public Bootstrap<N>
{
  public:
    TestBootstrap(int w, int h) : Bootstrap<N>(w, h) {}
    virtual void idle() { /** update some uniforms... */ glutPostRedisplay();}
    virtual void tick() {}
    virtual void render() { /** Render something impressive */}
};
 
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
    TestBootstrap<0> bootstrap0(300, 300);
    TestBootstrap<1> bootstrap1(300, 300);
    glutMainLoop();
}
 
#endif