Repository: vispy/vispy

Issue:
Multiple OpenGL windows not working
Tested using the latest Github code from today.

The GL tutorial tests (e.g. fireworks.py, cube.py) work fine within a PyQT application. But if you attempt to display two of them simultaneously (two widgets in one app) then both of them break, either corrupted graphics or failure to repaint the widget. Should two GL widgets be possible with vispy?

Attached a simple test app "test.py" that shows the issue. Code is as follows and uses the standard fireworks.py, cube.py examples:

```
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import cube, fireworks
 
class Form(QWidget):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
 
        cube_canvas = cube.Canvas()
        fireworks_canvas = fireworks.Canvas()
        Layout1 = QVBoxLayout()
        Layout1.addWidget(fireworks_canvas.native)
        Layout1.addWidget(cube_canvas.native)
 
        mainLayout = QGridLayout()
        mainLayout.addLayout(Layout1, 0, 1)
        self.setLayout(mainLayout)
        self.setWindowTitle("Vispy")
 
 
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    screen = Form()
    screen.show()
    sys.exit(app.exec_())

```
[2glviews.tar.gz](https://github.com/vispy/vispy/files/685855/2glviews.tar.gz)



Discussion:
@kelvinlawson I'm not really sure, but this seems to be connected with the propagation of events.

This gist [here](https://gist.github.com/kmuehlbauer/c521e2b05f5383651d157d5c44344949) shows adaptions of this [fireworks](https://github.com/vispy/vispy/blob/master/examples/demo/gloo/fireworks.py) and this [rotating_cube](https://github.com/vispy/vispy/blob/master/examples/basics/gloo/rotate_cube.py) inside one QT5 Application side-by-side.

@rougier might shed some light, what would be needed to get the low level gl-stuff working instead.


@kelvinlawson Did you get along with it? A short notice will be sufficient.
The difficulty is to route the event to the right context anytime and I'm not sure how things are handled with glir. For glumpy, there is an explicit switch to one context or the other when necessary (see https://github.com/glumpy/glumpy/blob/master/examples/app-two-windows.py)
I'd also be curious if something like this works in PyQt4 since it is a more heavily tested backend. Or at least works better. The GLIR "CURRENT" command (`set_current`/`_vispy_set_current` in vispy) should direct the GL calls to the right context. Mouse, keyboard, and timer events are another story.
@kmuehlbauer Is your gist something that we should consider making an example? How much modifying needed to be done to get this to work?
@davidh-ssec I can try to set this up also for qt4. Is it what you meant with *modifying work*? Should be fairly easy 😬.
@kmuehlbauer You mentioned having to modify the example code a bit to get this to work. Would it be possible to just import the examples in *this* new example? Maybe modify the existing examples so they work better, but without stopping them from working independently.
@davidh-ssec I'll have a look into this, didn't thought about `importing` so far. Keep you posted!

Resolving patch:
diff --git a/examples/demo/gloo/two_qt_widgets.py b/examples/demo/gloo/two_qt_widgets.py
new file mode 100644
--- /dev/null
+++ b/examples/demo/gloo/two_qt_widgets.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vispy: testskip
+
+"""
+Example demonstrating the use of two GLCanvases in one QtApp.
+"""
+
+from PyQt4 import QtGui, QtCore
+import sys
+
+from fireworks import Canvas as FireCanvas
+from rain import Canvas as RainCanvas
+
+
+class MainWindow(QtGui.QMainWindow):
+    def __init__(self):
+        QtGui.QMainWindow.__init__(self)
+
+        self.resize(1000, 500)
+        self.setWindowTitle('vispy example ...')
+
+        self.splitter_h = QtGui.QSplitter(QtCore.Qt.Horizontal)
+
+        # Central Widget
+        splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal)
+
+        self.rain_canvas = RainCanvas()
+        self.rain_canvas.create_native()
+        self.rain_canvas.native.setParent(self)
+        self.fireworks_canvas = FireCanvas()
+        self.fireworks_canvas.create_native()
+        self.fireworks_canvas.native.setParent(self)
+
+        splitter1.addWidget(self.fireworks_canvas.native)
+        splitter1.addWidget(self.rain_canvas.native)
+
+        self.setCentralWidget(splitter1)
+
+
+if __name__ == '__main__':
+    appQt = QtGui.QApplication(sys.argv)
+    win = MainWindow()
+    win.show()
+    appQt.exec_()


Test patch: