| package glfw |
| |
| //#include <stdlib.h> |
| //#define GLFW_INCLUDE_NONE |
| //#define GLFW_INCLUDE_NONE |
| //#include <GLFW/glfw3.h> |
| //void glfwSetWindowPosCallbackCB(GLFWwindow *window); |
| //void glfwSetWindowSizeCallbackCB(GLFWwindow *window); |
| //void glfwSetFramebufferSizeCallbackCB(GLFWwindow *window); |
| //void glfwSetWindowCloseCallbackCB(GLFWwindow *window); |
| //void glfwSetWindowRefreshCallbackCB(GLFWwindow *window); |
| //void glfwSetWindowFocusCallbackCB(GLFWwindow *window); |
| //void glfwSetWindowIconifyCallbackCB(GLFWwindow *window); |
| import "C" |
| |
| import ( |
| "errors" |
| "sync" |
| "unsafe" |
| ) |
| |
| // Internal window list stuff |
| type windowList struct { |
| l sync.Mutex |
| m map[*C.GLFWwindow]*Window |
| } |
| |
| var windows = windowList{m: map[*C.GLFWwindow]*Window{}} |
| |
| func (w *windowList) put(wnd *Window) { |
| w.l.Lock() |
| defer w.l.Unlock() |
| w.m[wnd.data] = wnd |
| } |
| |
| func (w *windowList) remove(wnd *C.GLFWwindow) { |
| w.l.Lock() |
| defer w.l.Unlock() |
| delete(w.m, wnd) |
| } |
| |
| func (w *windowList) get(wnd *C.GLFWwindow) *Window { |
| w.l.Lock() |
| defer w.l.Unlock() |
| return w.m[wnd] |
| } |
| |
| //Hint corresponds to hints that can be set before creating a window. |
| // |
| //Hint also corresponds to the attributes of the window that can be get after |
| //its creation. |
| type Hint int |
| |
| //Window related hints. |
| const ( |
| Focused Hint = C.GLFW_FOCUSED //Specifies whether the window will be focused. |
| Iconified Hint = C.GLFW_ICONIFIED //Specifies whether the window will be minimized. |
| Visible Hint = C.GLFW_VISIBLE //Specifies whether the window will be initially visible. |
| Resizable Hint = C.GLFW_RESIZABLE //Specifies whether the window will be resizable by the user. |
| Decorated Hint = C.GLFW_DECORATED //Specifies whether the window will have window decorations such as a border, a close widget, etc. |
| ) |
| |
| //Context related hints. |
| const ( |
| ClientApi Hint = C.GLFW_CLIENT_API //Specifies which client API to create the context for. Hard constraint. |
| ContextVersionMajor Hint = C.GLFW_CONTEXT_VERSION_MAJOR //Specifies the client API version that the created context must be compatible with. |
| ContextVersionMinor Hint = C.GLFW_CONTEXT_VERSION_MINOR //Specifies the client API version that the created context must be compatible with. |
| ContextRobustness Hint = C.GLFW_CONTEXT_ROBUSTNESS //Specifies the robustness strategy to be used by the context. |
| OpenglForwardCompatible Hint = C.GLFW_OPENGL_FORWARD_COMPAT //Specifies whether the OpenGL context should be forward-compatible. Hard constraint. |
| OpenglDebugContext Hint = C.GLFW_OPENGL_DEBUG_CONTEXT |
| OpenglProfile Hint = C.GLFW_OPENGL_PROFILE //Specifies which OpenGL profile to create the context for. Hard constraint. |
| ) |
| |
| //Framebuffer related hints. |
| const ( |
| ContextRevision Hint = C.GLFW_CONTEXT_REVISION |
| RedBits Hint = C.GLFW_RED_BITS //Specifies the desired bit depth of the default framebuffer. |
| GreenBits Hint = C.GLFW_GREEN_BITS //Specifies the desired bit depth of the default framebuffer. |
| BlueBits Hint = C.GLFW_BLUE_BITS //Specifies the desired bit depth of the default framebuffer. |
| AlphaBits Hint = C.GLFW_ALPHA_BITS //Specifies the desired bit depth of the default framebuffer. |
| DepthBits Hint = C.GLFW_DEPTH_BITS //Specifies the desired bit depth of the default framebuffer. |
| StencilBits Hint = C.GLFW_STENCIL_BITS //Specifies the desired bit depth of the default framebuffer. |
| AccumRedBits Hint = C.GLFW_ACCUM_RED_BITS //Specifies the desired bit depth of the accumulation buffer. |
| AccumGreenBits Hint = C.GLFW_ACCUM_GREEN_BITS //Specifies the desired bit depth of the accumulation buffer. |
| AccumBlueBits Hint = C.GLFW_ACCUM_BLUE_BITS //Specifies the desired bit depth of the accumulation buffer. |
| AccumAlphaBits Hint = C.GLFW_ACCUM_ALPHA_BITS //Specifies the desired bit depth of the accumulation buffer. |
| AuxBuffers Hint = C.GLFW_AUX_BUFFERS //Specifies the desired number of auxiliary buffers. |
| Stereo Hint = C.GLFW_STEREO //Specifies whether to use stereoscopic rendering. Hard constraint. |
| Samples Hint = C.GLFW_SAMPLES //Specifies the desired number of samples to use for multisampling. Zero disables multisampling. |
| SrgbCapable Hint = C.GLFW_SRGB_CAPABLE //Specifies whether the framebuffer should be sRGB capable. |
| RefreshRate Hint = C.GLFW_REFRESH_RATE //specifies the desired refresh rate for full screen windows. If set to zero, the highest available refresh rate will be used. This hint is ignored for windowed mode windows. |
| ) |
| |
| //Values for the ClientApi hint. |
| const ( |
| OpenglApi int = C.GLFW_OPENGL_API |
| OpenglEsApi int = C.GLFW_OPENGL_ES_API |
| ) |
| |
| //Values for the ContextRobustness hint. |
| const ( |
| NoRobustness int = C.GLFW_NO_ROBUSTNESS |
| NoResetNotification int = C.GLFW_NO_RESET_NOTIFICATION |
| LoseContextOnReset int = C.GLFW_LOSE_CONTEXT_ON_RESET |
| ) |
| |
| //Values for the OpenglProfile hint. |
| const ( |
| OpenglAnyProfile int = C.GLFW_OPENGL_ANY_PROFILE |
| OpenglCoreProfile int = C.GLFW_OPENGL_CORE_PROFILE |
| OpenglCompatProfile int = C.GLFW_OPENGL_COMPAT_PROFILE |
| ) |
| |
| //TRUE and FALSE values to use with hints. |
| const ( |
| True int = 1 /* GL_TRUE */ |
| False int = 0 /* GL_FALSE */ |
| ) |
| |
| type Window struct { |
| data *C.GLFWwindow |
| |
| // Window |
| fPosHolder func(w *Window, xpos int, ypos int) |
| fSizeHolder func(w *Window, width int, height int) |
| fFramebufferSizeHolder func(w *Window, width int, height int) |
| fCloseHolder func(w *Window) |
| fRefreshHolder func(w *Window) |
| fFocusHolder func(w *Window, focused bool) |
| fIconifyHolder func(w *Window, iconified bool) |
| |
| // Input |
| fMouseButtonHolder func(w *Window, button MouseButton, action Action, mod ModifierKey) |
| fCursorPosHolder func(w *Window, xpos float64, ypos float64) |
| fCursorEnterHolder func(w *Window, entered bool) |
| fScrollHolder func(w *Window, xoff float64, yoff float64) |
| fKeyHolder func(w *Window, key Key, scancode int, action Action, mods ModifierKey) |
| fCharHolder func(w *Window, char uint) |
| } |
| |
| //export goWindowPosCB |
| func goWindowPosCB(window unsafe.Pointer, xpos, ypos C.int) { |
| w := windows.get((*C.GLFWwindow)(window)) |
| w.fPosHolder(w, int(xpos), int(ypos)) |
| } |
| |
| //export goWindowSizeCB |
| func goWindowSizeCB(window unsafe.Pointer, width, height C.int) { |
| w := windows.get((*C.GLFWwindow)(window)) |
| w.fSizeHolder(w, int(width), int(height)) |
| } |
| |
| //export goFramebufferSizeCB |
| func goFramebufferSizeCB(window unsafe.Pointer, width, height C.int) { |
| w := windows.get((*C.GLFWwindow)(window)) |
| w.fFramebufferSizeHolder(w, int(width), int(height)) |
| } |
| |
| //export goWindowCloseCB |
| func goWindowCloseCB(window unsafe.Pointer) { |
| w := windows.get((*C.GLFWwindow)(window)) |
| w.fCloseHolder(w) |
| } |
| |
| //export goWindowRefreshCB |
| func goWindowRefreshCB(window unsafe.Pointer) { |
| w := windows.get((*C.GLFWwindow)(window)) |
| w.fRefreshHolder(w) |
| } |
| |
| //export goWindowFocusCB |
| func goWindowFocusCB(window unsafe.Pointer, focused C.int) { |
| w := windows.get((*C.GLFWwindow)(window)) |
| isFocused := glfwbool(focused) |
| w.fFocusHolder(w, isFocused) |
| } |
| |
| //export goWindowIconifyCB |
| func goWindowIconifyCB(window unsafe.Pointer, iconified C.int) { |
| isIconified := glfwbool(iconified) |
| w := windows.get((*C.GLFWwindow)(window)) |
| w.fIconifyHolder(w, isIconified) |
| } |
| |
| //DefaultHints resets all window hints to their default values. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func DefaultWindowHints() { |
| C.glfwDefaultWindowHints() |
| } |
| |
| //Hint function sets hints for the next call to CreateWindow. The hints, |
| //once set, retain their values until changed by a call to Hint or |
| //DefaultHints, or until the library is terminated with Terminate. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func WindowHint(target Hint, hint int) { |
| C.glfwWindowHint(C.int(target), C.int(hint)) |
| } |
| |
| //CreateWindow creates a window and its associated context. Most of the options |
| //controlling how the window and its context should be created are specified |
| //through Hint. |
| // |
| //Successful creation does not change which context is current. Before you can |
| //use the newly created context, you need to make it current using |
| //MakeContextCurrent. |
| // |
| //Note that the created window and context may differ from what you requested, |
| //as not all parameters and hints are hard constraints. This includes the size |
| //of the window, especially for full screen windows. To retrieve the actual |
| //attributes of the created window and context, use queries like |
| //GetWindowAttrib and GetWindowSize. |
| // |
| //To create the window at a specific position, make it initially invisible using |
| //the Visible window hint, set its position and then show it. |
| // |
| //If a fullscreen window is active, the screensaver is prohibited from starting. |
| // |
| //Windows: If the executable has an icon resource named GLFW_ICON, it will be |
| //set as the icon for the window. If no such icon is present, the IDI_WINLOGO |
| //icon will be used instead. |
| // |
| //Mac OS X: The GLFW window has no icon, as it is not a document window, but the |
| //dock icon will be the same as the application bundle's icon. Also, the first |
| //time a window is opened the menu bar is populated with common commands like |
| //Hide, Quit and About. The (minimal) about dialog uses information from the |
| //application's bundle. For more information on bundles, see the Bundle |
| //Programming Guide provided by Apple. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func CreateWindow(width, height int, title string, monitor *Monitor, share *Window) (*Window, error) { |
| var ( |
| m *C.GLFWmonitor |
| s *C.GLFWwindow |
| ) |
| |
| t := C.CString(title) |
| defer C.free(unsafe.Pointer(t)) |
| |
| if monitor != nil { |
| m = monitor.data |
| } |
| |
| if share != nil { |
| s = share.data |
| } |
| |
| w := C.glfwCreateWindow(C.int(width), C.int(height), t, m, s) |
| |
| if w == nil { |
| return nil, errors.New("Can't create window.") |
| } |
| wnd := &Window{data: w} |
| windows.put(wnd) |
| return wnd, nil |
| } |
| |
| //Destroy destroys the specified window and its context. On calling this |
| //function, no further callbacks will be called for that window. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) Destroy() { |
| windows.remove(w.data) |
| C.glfwDestroyWindow(w.data) |
| } |
| |
| //ShouldClose returns the value of the close flag of the specified window. |
| func (w *Window) ShouldClose() bool { |
| return glfwbool(C.glfwWindowShouldClose(w.data)) |
| } |
| |
| //SetShouldClose sets the value of the close flag of the window. This can be |
| //used to override the user's attempt to close the window, or to signal that it |
| //should be closed. |
| func (w *Window) SetShouldClose(value bool) { |
| if !value { |
| C.glfwSetWindowShouldClose(w.data, C.int(False)) |
| } else { |
| C.glfwSetWindowShouldClose(w.data, C.int(True)) |
| } |
| } |
| |
| //SetTitle sets the window title, encoded as UTF-8, of the window. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) SetTitle(title string) { |
| t := C.CString(title) |
| defer C.free(unsafe.Pointer(t)) |
| C.glfwSetWindowTitle(w.data, t) |
| } |
| |
| //GetPosition returns the position, in screen coordinates, of the upper-left |
| //corner of the client area of the window. |
| func (w *Window) GetPosition() (x, y int) { |
| var xpos, ypos C.int |
| |
| C.glfwGetWindowPos(w.data, &xpos, &ypos) |
| return int(xpos), int(ypos) |
| } |
| |
| //SetPosition sets the position, in screen coordinates, of the upper-left corner |
| //of the client area of the window. |
| // |
| //If it is a full screen window, this function does nothing. |
| // |
| //If you wish to set an initial window position you should create a hidden |
| //window (using Hint and Visible), set its position and then show it. |
| // |
| //It is very rarely a good idea to move an already visible window, as it will |
| //confuse and annoy the user. |
| // |
| //The window manager may put limits on what positions are allowed. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) SetPosition(xpos, ypos int) { |
| C.glfwSetWindowPos(w.data, C.int(xpos), C.int(ypos)) |
| } |
| |
| //GetSize returns the size, in screen coordinates, of the client area of the |
| //specified window. |
| func (w *Window) GetSize() (width, height int) { |
| var wi, h C.int |
| C.glfwGetWindowSize(w.data, &wi, &h) |
| return int(wi), int(h) |
| } |
| |
| //SetSize sets the size, in screen coordinates, of the client area of the |
| //window. |
| // |
| //For full screen windows, this function selects and switches to the resolution |
| //closest to the specified size, without affecting the window's context. As the |
| //context is unaffected, the bit depths of the framebuffer remain unchanged. |
| // |
| //The window manager may put limits on what window sizes are allowed. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) SetSize(width, height int) { |
| C.glfwSetWindowSize(w.data, C.int(width), C.int(height)) |
| } |
| |
| //GetFramebufferSize retrieves the size, in pixels, of the framebuffer of the |
| //specified window. |
| func (w *Window) GetFramebufferSize() (width, height int) { |
| var wi, h C.int |
| C.glfwGetFramebufferSize(w.data, &wi, &h) |
| return int(wi), int(h) |
| } |
| |
| //Iconfiy iconifies/minimizes the window, if it was previously restored. If it |
| //is a full screen window, the original monitor resolution is restored until the |
| //window is restored. If the window is already iconified, this function does |
| //nothing. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) Iconify() { |
| C.glfwIconifyWindow(w.data) |
| } |
| |
| //Restore restores the window, if it was previously iconified/minimized. If it |
| //is a full screen window, the resolution chosen for the window is restored on |
| //the selected monitor. If the window is already restored, this function does |
| //nothing. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) Restore() { |
| C.glfwRestoreWindow(w.data) |
| } |
| |
| //Show makes the window visible, if it was previously hidden. If the window is |
| //already visible or is in full screen mode, this function does nothing. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) Show() { |
| C.glfwShowWindow(w.data) |
| } |
| |
| //Hide hides the window, if it was previously visible. If the window is already |
| //hidden or is in full screen mode, this function does nothing. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func (w *Window) Hide() { |
| C.glfwHideWindow(w.data) |
| } |
| |
| //GetMonitor returns the handle of the monitor that the window is in |
| //fullscreen on. |
| func (w *Window) GetMonitor() (*Monitor, error) { |
| m := C.glfwGetWindowMonitor(w.data) |
| |
| if m == nil { |
| return nil, errors.New("Can't get the monitor.") |
| } |
| return &Monitor{m}, nil |
| } |
| |
| //GetAttribute returns an attribute of the window. There are many attributes, |
| //some related to the window and others to its context. |
| func (w *Window) GetAttribute(attrib Hint) int { |
| return int(C.glfwGetWindowAttrib(w.data, C.int(attrib))) |
| } |
| |
| //SetUserPointer sets the user-defined pointer of the window. The current value |
| //is retained until the window is destroyed. The initial value is nil. |
| func (w *Window) SetUserPointer(pointer unsafe.Pointer) { |
| C.glfwSetWindowUserPointer(w.data, pointer) |
| } |
| |
| //GetUserPointer returns the current value of the user-defined pointer of the |
| //window. The initial value is nil. |
| func (w *Window) GetUserPointer() unsafe.Pointer { |
| return C.glfwGetWindowUserPointer(w.data) |
| } |
| |
| //SetPositionCallback sets the position callback of the window, which is called |
| //when the window is moved. The callback is provided with the screen position |
| //of the upper-left corner of the client area of the window. |
| func (w *Window) SetPositionCallback(cbfun func(w *Window, xpos int, ypos int)) { |
| if cbfun == nil { |
| C.glfwSetWindowPosCallback(w.data, nil) |
| } else { |
| w.fPosHolder = cbfun |
| C.glfwSetWindowPosCallbackCB(w.data) |
| } |
| } |
| |
| //SetSizeCallback sets the size callback of the window, which is called when |
| //the window is resized. The callback is provided with the size, in screen |
| //coordinates, of the client area of the window. |
| func (w *Window) SetSizeCallback(cbfun func(w *Window, width int, height int)) { |
| if cbfun == nil { |
| C.glfwSetWindowSizeCallback(w.data, nil) |
| } else { |
| w.fSizeHolder = cbfun |
| C.glfwSetWindowSizeCallbackCB(w.data) |
| } |
| } |
| |
| //SetFramebufferSizeCallback sets the framebuffer resize callback of the specified |
| //window, which is called when the framebuffer of the specified window is resized. |
| func (w *Window) SetFramebufferSizeCallback(cbfun func(w *Window, width int, height int)) { |
| if cbfun == nil { |
| C.glfwSetFramebufferSizeCallback(w.data, nil) |
| } else { |
| w.fFramebufferSizeHolder = cbfun |
| C.glfwSetFramebufferSizeCallbackCB(w.data) |
| } |
| } |
| |
| //SetCloseCallback sets the close callback of the window, which is called when |
| //the user attempts to close the window, for example by clicking the close |
| //widget in the title bar. |
| // |
| //The close flag is set before this callback is called, but you can modify it at |
| //any time with SetShouldClose. |
| // |
| //Mac OS X: Selecting Quit from the application menu will trigger the close |
| //callback for all windows. |
| func (w *Window) SetCloseCallback(cbfun func(w *Window)) { |
| if cbfun == nil { |
| C.glfwSetWindowCloseCallback(w.data, nil) |
| } else { |
| w.fCloseHolder = cbfun |
| C.glfwSetWindowCloseCallbackCB(w.data) |
| } |
| } |
| |
| //SetRefreshCallback sets the refresh callback of the window, which |
| //is called when the client area of the window needs to be redrawn, for example |
| //if the window has been exposed after having been covered by another window. |
| // |
| //On compositing window systems such as Aero, Compiz or Aqua, where the window |
| //contents are saved off-screen, this callback may be called only very |
| //infrequently or never at all. |
| func (w *Window) SetRefreshCallback(cbfun func(w *Window)) { |
| if cbfun == nil { |
| C.glfwSetWindowRefreshCallback(w.data, nil) |
| } else { |
| w.fRefreshHolder = cbfun |
| C.glfwSetWindowRefreshCallbackCB(w.data) |
| } |
| } |
| |
| //SetFocusCallback sets the focus callback of the window, which is called when |
| //the window gains or loses focus. |
| // |
| //After the focus callback is called for a window that lost focus, synthetic key |
| //and mouse button release events will be generated for all such that had been |
| //pressed. For more information, see SetKeyCallback and SetMouseButtonCallback. |
| func (w *Window) SetFocusCallback(cbfun func(w *Window, focused bool)) { |
| if cbfun == nil { |
| C.glfwSetWindowFocusCallback(w.data, nil) |
| } else { |
| w.fFocusHolder = cbfun |
| C.glfwSetWindowFocusCallbackCB(w.data) |
| } |
| } |
| |
| //SetIconifyCallback sets the iconification callback of the window, which is |
| //called when the window is iconified or restored. |
| func (w *Window) SetIconifyCallback(cbfun func(w *Window, iconified bool)) { |
| if cbfun == nil { |
| C.glfwSetWindowIconifyCallback(w.data, nil) |
| } else { |
| w.fIconifyHolder = cbfun |
| C.glfwSetWindowIconifyCallbackCB(w.data) |
| } |
| } |
| |
| //PollEvents processes only those events that have already been received and |
| //then returns immediately. Processing events will cause the window and input |
| //callbacks associated with those events to be called. |
| // |
| //This function is not required for joystick input to work. |
| // |
| //This function may not be called from a callback. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func PollEvents() { |
| C.glfwPollEvents() |
| } |
| |
| //WaitEvents puts the calling thread to sleep until at least one event has been |
| //received. Once one or more events have been recevied, it behaves as if |
| //PollEvents was called, i.e. the events are processed and the function then |
| //returns immediately. Processing events will cause the window and input |
| //callbacks associated with those events to be called. |
| // |
| //Since not all events are associated with callbacks, this function may return |
| //without a callback having been called even if you are monitoring all |
| //callbacks. |
| // |
| //This function may not be called from a callback. |
| // |
| //This function may only be called from the main thread. See |
| //https://code.google.com/p/go-wiki/wiki/LockOSThread |
| func WaitEvents() { |
| C.glfwWaitEvents() |
| } |