title: Drawing concurrently in multiple windows with GLUT
body: <p>When I create two windows and redraw them in two different threads (one per window), it seems like all drawing goes to first created window. It constantly switches between what should be displayed in both windows. And second one remains mostly black.</p>
  
  <p>The code was working well with only one window, and then I updated it - inserted <code>currentWindow $= Just glWindow</code> in the beginning of the functions which set callbacks and call rendering methods.</p>
  
  <p>What do you think is the cause of the problems?</p>
  
  <p>EDIT:</p>
  
  <p>Code skeleton:</p>
  
  <pre><code>module Chart.Window where
  
  import Graphics.UI.GLUT hiding (Window, postRedisplay, &lt;etc&gt;)
  import qualified Graphics.UI.GLUT as GLUT
  import qualified Graphics.Rendering.OpenGL as GL
  
  data Window = Window
    { glWindow :: GLUT.Window
    , viewListRef :: IORef [Line]
    }
  
  main = do
    forkOS start &lt;params1&gt;
    forkOS start &lt;params2&gt;
  
  start &lt;params&gt; = do
    win &lt;- new &lt;params&gt;
    run win
    mainLoop
  
  new :: Strict -&gt; (Int, Int) -&gt; (Int, Int) -&gt; IO Window
  new name (posx, posy) (w, h) = do
    initGLUT
    glWindow &lt;- createWindow name
    currentWindow $= Just glWindow
    windowSize $= Size (fromIntegral w) (fromIntegral h)
    windowPosition $= Position (fromIntegral posx) (fromIntegral posy)
    return Window {..}
  
  initGLUT :: IO ()
  initGLUT = do
    beenInit &lt;- get initState
    unless beenInit $ void getArgsAndInitialize 
    initialDisplayMode $= [WithDepthBuffer, DoubleBuffered, RGBAMode]
    initialWindowSize $= Size 100 100
    initialWindowPosition $= Position 100 100
    actionOnWindowClose $= ContinueExectuion
  
  run :: Window -&gt; IO ()
  run win@Window{..} = do
    -- this will fork (with forkIO) threads 
    -- which will call "repaint" when chart needs to be updated
    initListeners repaint 
    initCallbacks win
    where
    repaint :: [Line] -&gt; IO ()
    repaint viewList = do
      writeIORef viewListRef viewList
      postRedisplay win
  
  postRedisplay Window{..} = GLUT.postRedisplay $ Just glWindow
  
  initCallbacks win@Window{..} = do
    currentWindow $= Just glWindow
    GLUT.displayCallback $= display win
    GLUT.idleCallback $= Just (postRedisplay win)
  
  display Window{..} = do
    currentWindow $= Just glWindow
    Size w h &lt;- get windowSize
    viewList &lt;- readIORef viewListRef
    drawChart viewList otherOptions
  
  reshapeCallback :: Window -&gt; GLUT.ReshapeCallback
  reshapeCallback win@Window{..} size@(Size w h) = do
    currentWindow $= Just glWindow
    GL.viewport $= (Position 0 0, size)
    GL.matrixMode $= GL.Projection
    GL.loadIdentity
    GL.ortho2D 0 (fromIntegral w) 0 (fromIntegral h)
    GL.matrixMode $= GL.Modelview 0
    GL.loadIdentity
    ... -- send command for listener thread to change internal state and postRedisplay
  
  drawChart viewList otherOptions = do
    ...
    -- chart consists of several horizontal panels. Call this for each panel:
    glViewport 0 panelYPosition width winHeight
    glScissor 0 panelYPosition (fromIntegral width) (fromIntegral panelHeight)
    GL.clear [GL.ColorBuffer]
    ...
    -- and then for each line=(Vertex2 v1 v2) from viewList
    GL.renderPrimitive GL.Lines $ do
      GL.vertex v1
      GL.vertex v2
    ...
  </code></pre>
  
  <p>BTW, when I commented the line which sets reshapeCallback (and window is reshaped at the beginning) and launched charting with only one window, I got exactly the same effect as in multi-window launch. I mean, the (only) window was mostly empty as if it was secondly created.</p>