Repository: vispy/vispy

Issue:
GLFW crashes if fullscreen=<int> on OSX
On OSX, I get at crash and a cryptic "Bus error: 10" when requesting full screen.  I managed to get a callstack manually, it crashes calling `_glfw.glfwGetVideoModes(monitor)` here:

```
Traceback (most recent call last):
  File "vispy/scene/canvas.py", line 91, in __init__
    app.Canvas.__init__(self, *args, **kwargs)
  File "vispy/app/canvas.py", line 171, in __init__
    self.create_native()
  File "vispy/app/canvas.py", line 185, in create_native
    self._app.backend_module.CanvasBackend(self, **self._backend_kwargs)
  File "vispy/app/backends/_glfw.py", line 250, in __init__
    use_size = glfw.glfwGetVideoMode(monitor)[:2]
```

Upgrading to the latest PyGLFW from @rougier 's repository prevents the crash, but it's missing some code:

```
  File "/Users/alexjc/Development/ProjectTrains/vispy/vispy/ext/glfw.py", line 575, in glfwGetVideoMode
    return (c_mode.width,
AttributeError: 'LP_GLFWvidmode' object has no attribute 'width'
```

What's the status of this dependency?  Do you have any recommendations for upgrading it, selectively copying things?



Discussion:
Selectively copying things would probably be easiest. I'm not sure how many of the changes have gone either direction at this point :(


Resolving patch:
diff --git a/vispy/app/backends/_glfw.py b/vispy/app/backends/_glfw.py
--- a/vispy/app/backends/_glfw.py
+++ b/vispy/app/backends/_glfw.py
@@ -249,9 +249,9 @@ def __init__(self, *args, **kwargs):
                                      % len(monitor))
                 monitor = monitor[fs]
             use_size = glfw.glfwGetVideoMode(monitor)[:2]
-            if use_size != size:
-                logger.warning('Requested size %s, will be ignored to '
-                               'use fullscreen mode %s' % (size, use_size))
+            if use_size != tuple(size):
+                logger.debug('Requested size %s, will be ignored to '
+                             'use fullscreen mode %s' % (size, use_size))
             size = use_size
         else:
             self._fullscreen = False
diff --git a/vispy/ext/glfw.py b/vispy/ext/glfw.py
--- a/vispy/ext/glfw.py
+++ b/vispy/ext/glfw.py
@@ -73,7 +73,7 @@ def glfwGetVersion():
 
 if version[0] != 3:
     version = '.'.join([str(v) for v in version])
-    raise OSError('Need GLFW v3, found %s' % version)
+    raise OSError('Need GLFW library version 3, found version %s' % version)
 
 
 # --- Version -----------------------------------------------------------------
@@ -462,6 +462,7 @@ class GLFWmonitor(Structure): pass
 glfwGetProcAddress             = _glfw.glfwGetProcAddress
 
 
+
 # --- Pythonizer --------------------------------------------------------------
 
 # This keeps track of current windows
@@ -471,14 +472,13 @@ class GLFWmonitor(Structure): pass
 # This is to prevent garbage collection on callbacks
 __c_callbacks__ = {}
 __py_callbacks__ = {}
-
+__c_error_callback__ = None
 
 def glfwCreateWindow(width=640, height=480, title="GLFW Window",
                      monitor=None, share=None):
     _glfw.glfwCreateWindow.restype = POINTER(GLFWwindow)
     window = _glfw.glfwCreateWindow(int(width), int(height),
-                                    title.encode('ASCII'), monitor, share)
-    assert window not in __windows__
+                                    title.encode('utf-8'), monitor, share)
     __windows__.append(window)
     __destroyed__.append(False)
     index = __windows__.index(window)
@@ -504,12 +504,12 @@ def glfwCreateWindow(width=640, height=480, title="GLFW Window",
 def glfwDestroyWindow(window):
     index = __windows__.index(window)
     if not __destroyed__[index]:
-        __destroyed__[index] = True
         # We do not delete window from the list (or it would impact numbering)
         __windows__[index] = None
         _glfw.glfwDestroyWindow(window)
         del __c_callbacks__[index]
         del __py_callbacks__[index]
+    __destroyed__[index] = True
 
 
 def glfwGetWindowPos(window):
@@ -572,13 +572,13 @@ def glfwGetMonitorPhysicalSize(monitor):
 
 def glfwGetVideoMode(monitor):
     _glfw.glfwGetVideoMode.restype = POINTER(GLFWvidmode)
-    c_modes = _glfw.glfwGetVideoModes(monitor)
-    return (c_modes.width,
-            c_modes.height,
-            c_modes.redBits,
-            c_modes.blueBits,
-            c_modes.greenBits,
-            c_modes.refreshRate )
+    c_mode = _glfw.glfwGetVideoMode(monitor).contents
+    return (c_mode.width,
+            c_mode.height,
+            c_mode.redBits,
+            c_mode.blueBits,
+            c_mode.greenBits,
+            c_mode.refreshRate )
 
 
 def GetGammaRamp(monitor):
@@ -625,7 +625,6 @@ def %(callback)s(window, callback = None):
     return old_callback""" % {'callback': callback, 'fun': fun}
     return code
 
-exec(__callback__('Error'))
 exec(__callback__('Monitor'))
 exec(__callback__('WindowPos'))
 exec(__callback__('WindowSize'))
@@ -639,3 +638,10 @@ def %(callback)s(window, callback = None):
 exec(__callback__('MouseButton'))
 exec(__callback__('CursorPos'))
 exec(__callback__('Scroll'))
+
+
+# Error callback does not take window parameter
+def glfwSetErrorCallback(callback = None):
+    global __c_error_callback__
+    __c_error_callback__ = errorfun(callback)
+    _glfw.glfwSetErrorCallback(__c_error_callback__)
\ No newline at end of file


Test patch: