zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

window.go (40887B)


      1 package glfw
      2 
      3 //#include <stdlib.h>
      4 //#define GLFW_INCLUDE_NONE
      5 //#include "glfw/include/GLFW/glfw3.h"
      6 //void glfwSetWindowPosCallbackCB(GLFWwindow *window);
      7 //void glfwSetWindowSizeCallbackCB(GLFWwindow *window);
      8 //void glfwSetFramebufferSizeCallbackCB(GLFWwindow *window);
      9 //void glfwSetWindowCloseCallbackCB(GLFWwindow *window);
     10 //void glfwSetWindowRefreshCallbackCB(GLFWwindow *window);
     11 //void glfwSetWindowFocusCallbackCB(GLFWwindow *window);
     12 //void glfwSetWindowIconifyCallbackCB(GLFWwindow *window);
     13 //void glfwSetWindowMaximizeCallbackCB(GLFWwindow *window);
     14 //void glfwSetWindowContentScaleCallbackCB(GLFWwindow *window);
     15 import "C"
     16 
     17 import (
     18 	"image"
     19 	"image/draw"
     20 	"sync"
     21 	"unsafe"
     22 )
     23 
     24 // Internal window list stuff
     25 type windowList struct {
     26 	l sync.Mutex
     27 	m map[*C.GLFWwindow]*Window
     28 }
     29 
     30 var windows = windowList{m: map[*C.GLFWwindow]*Window{}}
     31 
     32 func (w *windowList) put(wnd *Window) {
     33 	w.l.Lock()
     34 	defer w.l.Unlock()
     35 	w.m[wnd.data] = wnd
     36 }
     37 
     38 func (w *windowList) remove(wnd *C.GLFWwindow) {
     39 	w.l.Lock()
     40 	defer w.l.Unlock()
     41 	delete(w.m, wnd)
     42 }
     43 
     44 func (w *windowList) get(wnd *C.GLFWwindow) *Window {
     45 	w.l.Lock()
     46 	defer w.l.Unlock()
     47 	return w.m[wnd]
     48 }
     49 
     50 // Hint corresponds to hints that can be set before creating a window.
     51 //
     52 // Hint also corresponds to the attributes of the window that can be get after
     53 // its creation.
     54 type Hint int
     55 
     56 // Init related hints. (Use with glfw.InitHint)
     57 const (
     58 	JoystickHatButtons  Hint = C.GLFW_JOYSTICK_HAT_BUTTONS  // Specifies whether to also expose joystick hats as buttons, for compatibility with earlier versions of GLFW that did not have glfwGetJoystickHats.
     59 	CocoaChdirResources Hint = C.GLFW_COCOA_CHDIR_RESOURCES // Specifies whether to set the current directory to the application to the Contents/Resources subdirectory of the application's bundle, if present.
     60 	CocoaMenubar        Hint = C.GLFW_COCOA_MENUBAR         // Specifies whether to create a basic menu bar, either from a nib or manually, when the first window is created, which is when AppKit is initialized.
     61 )
     62 
     63 // Window related hints/attributes.
     64 const (
     65 	Focused                Hint = C.GLFW_FOCUSED                 // Specifies whether the window will be given input focus when created. This hint is ignored for full screen and initially hidden windows.
     66 	Iconified              Hint = C.GLFW_ICONIFIED               // Specifies whether the window will be minimized.
     67 	Maximized              Hint = C.GLFW_MAXIMIZED               // Specifies whether the window is maximized.
     68 	Visible                Hint = C.GLFW_VISIBLE                 // Specifies whether the window will be initially visible.
     69 	Hovered                Hint = C.GLFW_HOVERED                 // Specifies whether the cursor is currently directly over the content area of the window, with no other windows between. See Cursor enter/leave events for details.
     70 	Resizable              Hint = C.GLFW_RESIZABLE               // Specifies whether the window will be resizable by the user.
     71 	Decorated              Hint = C.GLFW_DECORATED               // Specifies whether the window will have window decorations such as a border, a close widget, etc.
     72 	Floating               Hint = C.GLFW_FLOATING                // Specifies whether the window will be always-on-top.
     73 	AutoIconify            Hint = C.GLFW_AUTO_ICONIFY            // Specifies whether fullscreen windows automatically iconify (and restore the previous video mode) on focus loss.
     74 	CenterCursor           Hint = C.GLFW_CENTER_CURSOR           // Specifies whether the cursor should be centered over newly created full screen windows. This hint is ignored for windowed mode windows.
     75 	TransparentFramebuffer Hint = C.GLFW_TRANSPARENT_FRAMEBUFFER // Specifies whether the framebuffer should be transparent.
     76 	FocusOnShow            Hint = C.GLFW_FOCUS_ON_SHOW           // Specifies whether the window will be given input focus when glfwShowWindow is called.
     77 	ScaleToMonitor         Hint = C.GLFW_SCALE_TO_MONITOR        // Specified whether the window content area should be resized based on the monitor content scale of any monitor it is placed on. This includes the initial placement when the window is created.
     78 )
     79 
     80 // Context related hints.
     81 const (
     82 	ClientAPI               Hint = C.GLFW_CLIENT_API               // Specifies which client API to create the context for. Hard constraint.
     83 	ContextVersionMajor     Hint = C.GLFW_CONTEXT_VERSION_MAJOR    // Specifies the client API version that the created context must be compatible with.
     84 	ContextVersionMinor     Hint = C.GLFW_CONTEXT_VERSION_MINOR    // Specifies the client API version that the created context must be compatible with.
     85 	ContextRobustness       Hint = C.GLFW_CONTEXT_ROBUSTNESS       // Specifies the robustness strategy to be used by the context.
     86 	ContextReleaseBehavior  Hint = C.GLFW_CONTEXT_RELEASE_BEHAVIOR // Specifies the release behavior to be used by the context.
     87 	OpenGLForwardCompatible Hint = C.GLFW_OPENGL_FORWARD_COMPAT    // Specifies whether the OpenGL context should be forward-compatible. Hard constraint.
     88 	OpenGLDebugContext      Hint = C.GLFW_OPENGL_DEBUG_CONTEXT     // Specifies whether to create a debug OpenGL context, which may have additional error and performance issue reporting functionality. If OpenGL ES is requested, this hint is ignored.
     89 	OpenGLProfile           Hint = C.GLFW_OPENGL_PROFILE           // Specifies which OpenGL profile to create the context for. Hard constraint.
     90 	ContextCreationAPI      Hint = C.GLFW_CONTEXT_CREATION_API     // Specifies which context creation API to use to create the context.
     91 )
     92 
     93 // Framebuffer related hints.
     94 const (
     95 	ContextRevision        Hint = C.GLFW_CONTEXT_REVISION
     96 	RedBits                Hint = C.GLFW_RED_BITS                 // Specifies the desired bit depth of the default framebuffer.
     97 	GreenBits              Hint = C.GLFW_GREEN_BITS               // Specifies the desired bit depth of the default framebuffer.
     98 	BlueBits               Hint = C.GLFW_BLUE_BITS                // Specifies the desired bit depth of the default framebuffer.
     99 	AlphaBits              Hint = C.GLFW_ALPHA_BITS               // Specifies the desired bit depth of the default framebuffer.
    100 	DepthBits              Hint = C.GLFW_DEPTH_BITS               // Specifies the desired bit depth of the default framebuffer.
    101 	StencilBits            Hint = C.GLFW_STENCIL_BITS             // Specifies the desired bit depth of the default framebuffer.
    102 	AccumRedBits           Hint = C.GLFW_ACCUM_RED_BITS           // Specifies the desired bit depth of the accumulation buffer.
    103 	AccumGreenBits         Hint = C.GLFW_ACCUM_GREEN_BITS         // Specifies the desired bit depth of the accumulation buffer.
    104 	AccumBlueBits          Hint = C.GLFW_ACCUM_BLUE_BITS          // Specifies the desired bit depth of the accumulation buffer.
    105 	AccumAlphaBits         Hint = C.GLFW_ACCUM_ALPHA_BITS         // Specifies the desired bit depth of the accumulation buffer.
    106 	AuxBuffers             Hint = C.GLFW_AUX_BUFFERS              // Specifies the desired number of auxiliary buffers.
    107 	Stereo                 Hint = C.GLFW_STEREO                   // Specifies whether to use stereoscopic rendering. Hard constraint.
    108 	Samples                Hint = C.GLFW_SAMPLES                  // Specifies the desired number of samples to use for multisampling. Zero disables multisampling.
    109 	SRGBCapable            Hint = C.GLFW_SRGB_CAPABLE             // Specifies whether the framebuffer should be sRGB capable.
    110 	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.
    111 	DoubleBuffer           Hint = C.GLFW_DOUBLEBUFFER             // Specifies whether the framebuffer should be double buffered. You nearly always want to use double buffering. This is a hard constraint.
    112 	CocoaGraphicsSwitching Hint = C.GLFW_COCOA_GRAPHICS_SWITCHING // Specifies whether to in Automatic Graphics Switching, i.e. to allow the system to choose the integrated GPU for the OpenGL context and move it between GPUs if necessary or whether to force it to always run on the discrete GPU.
    113 	CocoaRetinaFramebuffer Hint = C.GLFW_COCOA_RETINA_FRAMEBUFFER // Specifies whether to use full resolution framebuffers on Retina displays.
    114 )
    115 
    116 // Naming related hints. (Use with glfw.WindowHintString)
    117 const (
    118 	CocoaFrameNAME  Hint = C.GLFW_COCOA_FRAME_NAME  // Specifies the UTF-8 encoded name to use for autosaving the window frame, or if empty disables frame autosaving for the window.
    119 	X11ClassName    Hint = C.GLFW_X11_CLASS_NAME    // Specifies the desired ASCII encoded class parts of the ICCCM WM_CLASS window property.nd instance parts of the ICCCM WM_CLASS window property.
    120 	X11InstanceName Hint = C.GLFW_X11_INSTANCE_NAME // Specifies the desired ASCII encoded instance parts of the ICCCM WM_CLASS window property.nd instance parts of the ICCCM WM_CLASS window property.
    121 )
    122 
    123 // Values for the ClientAPI hint.
    124 const (
    125 	OpenGLAPI   int = C.GLFW_OPENGL_API
    126 	OpenGLESAPI int = C.GLFW_OPENGL_ES_API
    127 	NoAPI       int = C.GLFW_NO_API
    128 )
    129 
    130 // Values for ContextCreationAPI hint.
    131 const (
    132 	NativeContextAPI int = C.GLFW_NATIVE_CONTEXT_API
    133 	EGLContextAPI    int = C.GLFW_EGL_CONTEXT_API
    134 	OSMesaContextAPI int = C.GLFW_OSMESA_CONTEXT_API
    135 )
    136 
    137 // Values for the ContextRobustness hint.
    138 const (
    139 	NoRobustness        int = C.GLFW_NO_ROBUSTNESS
    140 	NoResetNotification int = C.GLFW_NO_RESET_NOTIFICATION
    141 	LoseContextOnReset  int = C.GLFW_LOSE_CONTEXT_ON_RESET
    142 )
    143 
    144 // Values for ContextReleaseBehavior hint.
    145 const (
    146 	AnyReleaseBehavior   int = C.GLFW_ANY_RELEASE_BEHAVIOR
    147 	ReleaseBehaviorFlush int = C.GLFW_RELEASE_BEHAVIOR_FLUSH
    148 	ReleaseBehaviorNone  int = C.GLFW_RELEASE_BEHAVIOR_NONE
    149 )
    150 
    151 // Values for the OpenGLProfile hint.
    152 const (
    153 	OpenGLAnyProfile    int = C.GLFW_OPENGL_ANY_PROFILE
    154 	OpenGLCoreProfile   int = C.GLFW_OPENGL_CORE_PROFILE
    155 	OpenGLCompatProfile int = C.GLFW_OPENGL_COMPAT_PROFILE
    156 )
    157 
    158 // Other values.
    159 const (
    160 	True     int = 1 // GL_TRUE
    161 	False    int = 0 // GL_FALSE
    162 	DontCare int = C.GLFW_DONT_CARE
    163 )
    164 
    165 // Window represents a window.
    166 type Window struct {
    167 	data *C.GLFWwindow
    168 
    169 	// Window.
    170 	fPosHolder             func(w *Window, xpos int, ypos int)
    171 	fSizeHolder            func(w *Window, width int, height int)
    172 	fFramebufferSizeHolder func(w *Window, width int, height int)
    173 	fCloseHolder           func(w *Window)
    174 	fMaximizeHolder        func(w *Window, iconified bool)
    175 	fContentScaleHolder    func(w *Window, x float32, y float32)
    176 	fRefreshHolder         func(w *Window)
    177 	fFocusHolder           func(w *Window, focused bool)
    178 	fIconifyHolder         func(w *Window, iconified bool)
    179 
    180 	// Input.
    181 	fMouseButtonHolder func(w *Window, button MouseButton, action Action, mod ModifierKey)
    182 	fCursorPosHolder   func(w *Window, xpos float64, ypos float64)
    183 	fCursorEnterHolder func(w *Window, entered bool)
    184 	fScrollHolder      func(w *Window, xoff float64, yoff float64)
    185 	fKeyHolder         func(w *Window, key Key, scancode int, action Action, mods ModifierKey)
    186 	fCharHolder        func(w *Window, char rune)
    187 	fCharModsHolder    func(w *Window, char rune, mods ModifierKey)
    188 	fDropHolder        func(w *Window, names []string)
    189 }
    190 
    191 // Handle returns a *C.GLFWwindow reference (i.e. the GLFW window itself).
    192 // This can be used for passing the GLFW window handle to external libraries
    193 // like vulkan-go.
    194 func (w *Window) Handle() unsafe.Pointer {
    195 	return unsafe.Pointer(w.data)
    196 }
    197 
    198 // GoWindow creates a Window from a *C.GLFWwindow reference.
    199 // Used when an external C library is calling your Go handlers.
    200 func GoWindow(window unsafe.Pointer) *Window {
    201 	return &Window{data: (*C.GLFWwindow)(window)}
    202 }
    203 
    204 //export goWindowPosCB
    205 func goWindowPosCB(window unsafe.Pointer, xpos, ypos C.int) {
    206 	w := windows.get((*C.GLFWwindow)(window))
    207 	w.fPosHolder(w, int(xpos), int(ypos))
    208 }
    209 
    210 //export goWindowSizeCB
    211 func goWindowSizeCB(window unsafe.Pointer, width, height C.int) {
    212 	w := windows.get((*C.GLFWwindow)(window))
    213 	w.fSizeHolder(w, int(width), int(height))
    214 }
    215 
    216 //export goFramebufferSizeCB
    217 func goFramebufferSizeCB(window unsafe.Pointer, width, height C.int) {
    218 	w := windows.get((*C.GLFWwindow)(window))
    219 	w.fFramebufferSizeHolder(w, int(width), int(height))
    220 }
    221 
    222 //export goWindowCloseCB
    223 func goWindowCloseCB(window unsafe.Pointer) {
    224 	w := windows.get((*C.GLFWwindow)(window))
    225 	w.fCloseHolder(w)
    226 }
    227 
    228 //export goWindowMaximizeCB
    229 func goWindowMaximizeCB(window unsafe.Pointer, iconified C.int) {
    230 	w := windows.get((*C.GLFWwindow)(window))
    231 	w.fMaximizeHolder(w, glfwbool(iconified))
    232 }
    233 
    234 //export goWindowRefreshCB
    235 func goWindowRefreshCB(window unsafe.Pointer) {
    236 	w := windows.get((*C.GLFWwindow)(window))
    237 	w.fRefreshHolder(w)
    238 }
    239 
    240 //export goWindowFocusCB
    241 func goWindowFocusCB(window unsafe.Pointer, focused C.int) {
    242 	w := windows.get((*C.GLFWwindow)(window))
    243 	isFocused := glfwbool(focused)
    244 	w.fFocusHolder(w, isFocused)
    245 }
    246 
    247 //export goWindowIconifyCB
    248 func goWindowIconifyCB(window unsafe.Pointer, iconified C.int) {
    249 	isIconified := glfwbool(iconified)
    250 	w := windows.get((*C.GLFWwindow)(window))
    251 	w.fIconifyHolder(w, isIconified)
    252 }
    253 
    254 //export goWindowContentScaleCB
    255 func goWindowContentScaleCB(window unsafe.Pointer, x C.float, y C.float) {
    256 	w := windows.get((*C.GLFWwindow)(window))
    257 	w.fContentScaleHolder(w, float32(x), float32(y))
    258 }
    259 
    260 // DefaultWindowHints resets all window hints to their default values.
    261 //
    262 // This function may only be called from the main thread.
    263 func DefaultWindowHints() {
    264 	C.glfwDefaultWindowHints()
    265 	panicError()
    266 }
    267 
    268 // WindowHint sets hints for the next call to CreateWindow. The hints,
    269 // once set, retain their values until changed by a call to WindowHint or
    270 // DefaultWindowHints, or until the library is terminated with Terminate.
    271 //
    272 // This function may only be called from the main thread.
    273 func WindowHint(target Hint, hint int) {
    274 	C.glfwWindowHint(C.int(target), C.int(hint))
    275 	panicError()
    276 }
    277 
    278 // WindowHintString sets hints for the next call to CreateWindow. The hints,
    279 // once set, retain their values until changed by a call to this function or
    280 // DefaultWindowHints, or until the library is terminated.
    281 //
    282 // Only string type hints can be set with this function. Integer value hints are
    283 // set with WindowHint.
    284 //
    285 // This function does not check whether the specified hint values are valid. If
    286 // you set hints to invalid values this will instead be reported by the next
    287 // call to CreateWindow.
    288 //
    289 // Some hints are platform specific. These may be set on any platform but they
    290 // will only affect their specific platform. Other platforms will ignore them.
    291 // Setting these hints requires no platform specific headers or functions.
    292 //
    293 // This function must only be called from the main thread.
    294 func WindowHintString(hint Hint, value string) {
    295 	str := C.CString(value)
    296 	defer C.free(unsafe.Pointer(str))
    297 	C.glfwWindowHintString(C.int(hint), str)
    298 }
    299 
    300 // CreateWindow creates a window and its associated context. Most of the options
    301 // controlling how the window and its context should be created are specified
    302 // through Hint.
    303 //
    304 // Successful creation does not change which context is current. Before you can
    305 // use the newly created context, you need to make it current using
    306 // MakeContextCurrent.
    307 //
    308 // Note that the created window and context may differ from what you requested,
    309 // as not all parameters and hints are hard constraints. This includes the size
    310 // of the window, especially for full screen windows. To retrieve the actual
    311 // attributes of the created window and context, use queries like
    312 // GetWindowAttrib and GetWindowSize.
    313 //
    314 // To create the window at a specific position, make it initially invisible using
    315 // the Visible window hint, set its position and then show it.
    316 //
    317 // If a fullscreen window is active, the screensaver is prohibited from starting.
    318 //
    319 // Windows: If the executable has an icon resource named GLFW_ICON, it will be
    320 // set as the icon for the window. If no such icon is present, the IDI_WINLOGO
    321 // icon will be used instead.
    322 //
    323 // Mac OS X: The GLFW window has no icon, as it is not a document window, but the
    324 // dock icon will be the same as the application bundle's icon. Also, the first
    325 // time a window is opened the menu bar is populated with common commands like
    326 // Hide, Quit and About. The (minimal) about dialog uses information from the
    327 // application's bundle. For more information on bundles, see the Bundle
    328 // Programming Guide provided by Apple.
    329 //
    330 // This function may only be called from the main thread.
    331 func CreateWindow(width, height int, title string, monitor *Monitor, share *Window) (*Window, error) {
    332 	var (
    333 		m *C.GLFWmonitor
    334 		s *C.GLFWwindow
    335 	)
    336 
    337 	t := C.CString(title)
    338 	defer C.free(unsafe.Pointer(t))
    339 
    340 	if monitor != nil {
    341 		m = monitor.data
    342 	}
    343 
    344 	if share != nil {
    345 		s = share.data
    346 	}
    347 
    348 	w := C.glfwCreateWindow(C.int(width), C.int(height), t, m, s)
    349 	if w == nil {
    350 		return nil, acceptError(APIUnavailable, VersionUnavailable)
    351 	}
    352 
    353 	wnd := &Window{data: w}
    354 	windows.put(wnd)
    355 	return wnd, nil
    356 }
    357 
    358 // Destroy destroys the specified window and its context. On calling this
    359 // function, no further callbacks will be called for that window.
    360 //
    361 // This function may only be called from the main thread.
    362 func (w *Window) Destroy() {
    363 	windows.remove(w.data)
    364 	C.glfwDestroyWindow(w.data)
    365 	panicError()
    366 }
    367 
    368 // ShouldClose reports the value of the close flag of the specified window.
    369 func (w *Window) ShouldClose() bool {
    370 	ret := glfwbool(C.glfwWindowShouldClose(w.data))
    371 	panicError()
    372 	return ret
    373 }
    374 
    375 // SetShouldClose sets the value of the close flag of the window. This can be
    376 // used to override the user's attempt to close the window, or to signal that it
    377 // should be closed.
    378 func (w *Window) SetShouldClose(value bool) {
    379 	if !value {
    380 		C.glfwSetWindowShouldClose(w.data, C.int(False))
    381 	} else {
    382 		C.glfwSetWindowShouldClose(w.data, C.int(True))
    383 	}
    384 	panicError()
    385 }
    386 
    387 // SetTitle sets the window title, encoded as UTF-8, of the window.
    388 //
    389 // This function may only be called from the main thread.
    390 func (w *Window) SetTitle(title string) {
    391 	t := C.CString(title)
    392 	defer C.free(unsafe.Pointer(t))
    393 	C.glfwSetWindowTitle(w.data, t)
    394 	panicError()
    395 }
    396 
    397 // SetIcon sets the icon of the specified window. If passed an array of candidate images,
    398 // those of or closest to the sizes desired by the system are selected. If no images are
    399 // specified, the window reverts to its default icon.
    400 //
    401 // The image is ideally provided in the form of *image.NRGBA.
    402 // The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
    403 // bits per channel with the red channel first. They are arranged canonically
    404 // as packed sequential rows, starting from the top-left corner. If the image
    405 // type is not *image.NRGBA, it will be converted to it.
    406 //
    407 // The desired image sizes varies depending on platform and system settings. The selected
    408 // images will be rescaled as needed. Good sizes include 16x16, 32x32 and 48x48.
    409 func (w *Window) SetIcon(images []image.Image) {
    410 	count := len(images)
    411 	cimages := make([]C.GLFWimage, count)
    412 	freePixels := make([]func(), count)
    413 
    414 	for i, img := range images {
    415 		var pixels []uint8
    416 		b := img.Bounds()
    417 
    418 		switch img := img.(type) {
    419 		case *image.NRGBA:
    420 			pixels = img.Pix
    421 		default:
    422 			m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
    423 			draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
    424 			pixels = m.Pix
    425 		}
    426 
    427 		pix, free := bytes(pixels)
    428 		freePixels[i] = free
    429 
    430 		cimages[i].width = C.int(b.Dx())
    431 		cimages[i].height = C.int(b.Dy())
    432 		cimages[i].pixels = (*C.uchar)(pix)
    433 	}
    434 
    435 	var p *C.GLFWimage
    436 	if count > 0 {
    437 		p = &cimages[0]
    438 	}
    439 	C.glfwSetWindowIcon(w.data, C.int(count), p)
    440 
    441 	for _, v := range freePixels {
    442 		v()
    443 	}
    444 
    445 	panicError()
    446 }
    447 
    448 // GetPos returns the position, in screen coordinates, of the upper-left
    449 // corner of the client area of the window.
    450 func (w *Window) GetPos() (x, y int) {
    451 	var xpos, ypos C.int
    452 	C.glfwGetWindowPos(w.data, &xpos, &ypos)
    453 	panicError()
    454 	return int(xpos), int(ypos)
    455 }
    456 
    457 // SetPos sets the position, in screen coordinates, of the upper-left corner
    458 // of the client area of the window.
    459 //
    460 // If it is a full screen window, this function does nothing.
    461 //
    462 // If you wish to set an initial window position you should create a hidden
    463 // window (using Hint and Visible), set its position and then show it.
    464 //
    465 // It is very rarely a good idea to move an already visible window, as it will
    466 // confuse and annoy the user.
    467 //
    468 // The window manager may put limits on what positions are allowed.
    469 //
    470 // This function may only be called from the main thread.
    471 func (w *Window) SetPos(xpos, ypos int) {
    472 	C.glfwSetWindowPos(w.data, C.int(xpos), C.int(ypos))
    473 	panicError()
    474 }
    475 
    476 // GetSize returns the size, in screen coordinates, of the client area of the
    477 // specified window.
    478 func (w *Window) GetSize() (width, height int) {
    479 	var wi, h C.int
    480 	C.glfwGetWindowSize(w.data, &wi, &h)
    481 	panicError()
    482 	return int(wi), int(h)
    483 }
    484 
    485 // SetSize sets the size, in screen coordinates, of the client area of the
    486 // window.
    487 //
    488 // For full screen windows, this function selects and switches to the resolution
    489 // closest to the specified size, without affecting the window's context. As the
    490 // context is unaffected, the bit depths of the framebuffer remain unchanged.
    491 //
    492 // The window manager may put limits on what window sizes are allowed.
    493 //
    494 // This function may only be called from the main thread.
    495 func (w *Window) SetSize(width, height int) {
    496 	C.glfwSetWindowSize(w.data, C.int(width), C.int(height))
    497 	panicError()
    498 }
    499 
    500 // SetSizeLimits sets the size limits of the client area of the specified window.
    501 // If the window is full screen or not resizable, this function does nothing.
    502 //
    503 // The size limits are applied immediately and may cause the window to be resized.
    504 func (w *Window) SetSizeLimits(minw, minh, maxw, maxh int) {
    505 	C.glfwSetWindowSizeLimits(w.data, C.int(minw), C.int(minh), C.int(maxw), C.int(maxh))
    506 	panicError()
    507 }
    508 
    509 // SetAspectRatio sets the required aspect ratio of the client area of the specified window.
    510 // If the window is full screen or not resizable, this function does nothing.
    511 //
    512 // The aspect ratio is specified as a numerator and a denominator and both values must be greater
    513 // than zero. For example, the common 16:9 aspect ratio is specified as 16 and 9, respectively.
    514 //
    515 // If the numerator and denominator is set to glfw.DontCare then the aspect ratio limit is disabled.
    516 //
    517 // The aspect ratio is applied immediately and may cause the window to be resized.
    518 func (w *Window) SetAspectRatio(numer, denom int) {
    519 	C.glfwSetWindowAspectRatio(w.data, C.int(numer), C.int(denom))
    520 	panicError()
    521 }
    522 
    523 // GetFramebufferSize retrieves the size, in pixels, of the framebuffer of the
    524 // specified window.
    525 func (w *Window) GetFramebufferSize() (width, height int) {
    526 	var wi, h C.int
    527 	C.glfwGetFramebufferSize(w.data, &wi, &h)
    528 	panicError()
    529 	return int(wi), int(h)
    530 }
    531 
    532 // GetFrameSize retrieves the size, in screen coordinates, of each edge of the frame
    533 // of the specified window. This size includes the title bar, if the window has one.
    534 // The size of the frame may vary depending on the window-related hints used to create it.
    535 //
    536 // Because this function retrieves the size of each window frame edge and not the offset
    537 // along a particular coordinate axis, the retrieved values will always be zero or positive.
    538 func (w *Window) GetFrameSize() (left, top, right, bottom int) {
    539 	var l, t, r, b C.int
    540 	C.glfwGetWindowFrameSize(w.data, &l, &t, &r, &b)
    541 	panicError()
    542 	return int(l), int(t), int(r), int(b)
    543 }
    544 
    545 // GetContentScale function retrieves the content scale for the specified
    546 // window. The content scale is the ratio between the current DPI and the
    547 // platform's default DPI. If you scale all pixel dimensions by this scale then
    548 // your content should appear at an appropriate size. This is especially
    549 // important for text and any UI elements.
    550 //
    551 // This function may only be called from the main thread.
    552 func (w *Window) GetContentScale() (float32, float32) {
    553 	var x, y C.float
    554 	C.glfwGetWindowContentScale(w.data, &x, &y)
    555 	return float32(x), float32(y)
    556 }
    557 
    558 // GetOpacity function returns the opacity of the window, including any
    559 // decorations.
    560 //
    561 // The opacity (or alpha) value is a positive finite number between zero and
    562 // one, where zero is fully transparent and one is fully opaque. If the system
    563 // does not support whole window transparency, this function always returns one.
    564 //
    565 // The initial opacity value for newly created windows is one.
    566 //
    567 // This function may only be called from the main thread.
    568 func (w *Window) GetOpacity() float32 {
    569 	return float32(C.glfwGetWindowOpacity(w.data))
    570 }
    571 
    572 // SetOpacity function sets the opacity of the window, including any
    573 // decorations. The opacity (or alpha) value is a positive finite number between
    574 // zero and one, where zero is fully transparent and one is fully opaque.
    575 //
    576 // The initial opacity value for newly created windows is one.
    577 //
    578 // A window created with framebuffer transparency may not use whole window
    579 // transparency. The results of doing this are undefined.
    580 //
    581 // This function may only be called from the main thread.
    582 func (w *Window) SetOpacity(opacity float32) {
    583 	C.glfwSetWindowOpacity(w.data, C.float(opacity))
    584 }
    585 
    586 // RequestWindowAttention funciton requests user attention to the specified
    587 // window. On platforms where this is not supported, attention is requested to
    588 // the application as a whole.
    589 //
    590 // Once the user has given attention, usually by focusing the window or
    591 // application, the system will end the request automatically.
    592 //
    593 // This function must only be called from the main thread.
    594 func (w *Window) RequestAttention() {
    595 	C.glfwRequestWindowAttention(w.data)
    596 }
    597 
    598 // Focus brings the specified window to front and sets input focus.
    599 // The window should already be visible and not iconified.
    600 //
    601 // By default, both windowed and full screen mode windows are focused when initially created.
    602 // Set the glfw.Focused to disable this behavior.
    603 //
    604 // Do not use this function to steal focus from other applications unless you are certain that
    605 // is what the user wants. Focus stealing can be extremely disruptive.
    606 func (w *Window) Focus() {
    607 	C.glfwFocusWindow(w.data)
    608 }
    609 
    610 // Iconify iconifies/minimizes the window, if it was previously restored. If it
    611 // is a full screen window, the original monitor resolution is restored until the
    612 // window is restored. If the window is already iconified, this function does
    613 // nothing.
    614 //
    615 // This function may only be called from the main thread.
    616 func (w *Window) Iconify() {
    617 	C.glfwIconifyWindow(w.data)
    618 }
    619 
    620 // Maximize maximizes the specified window if it was previously not maximized.
    621 // If the window is already maximized, this function does nothing.
    622 //
    623 // If the specified window is a full screen window, this function does nothing.
    624 func (w *Window) Maximize() {
    625 	C.glfwMaximizeWindow(w.data)
    626 }
    627 
    628 // Restore restores the window, if it was previously iconified/minimized. If it
    629 // is a full screen window, the resolution chosen for the window is restored on
    630 // the selected monitor. If the window is already restored, this function does
    631 // nothing.
    632 //
    633 // This function may only be called from the main thread.
    634 func (w *Window) Restore() {
    635 	C.glfwRestoreWindow(w.data)
    636 }
    637 
    638 // Show makes the window visible, if it was previously hidden. If the window is
    639 // already visible or is in full screen mode, this function does nothing.
    640 //
    641 // This function may only be called from the main thread.
    642 func (w *Window) Show() {
    643 	C.glfwShowWindow(w.data)
    644 	panicError()
    645 }
    646 
    647 // Hide hides the window, if it was previously visible. If the window is already
    648 // hidden or is in full screen mode, this function does nothing.
    649 //
    650 // This function may only be called from the main thread.
    651 func (w *Window) Hide() {
    652 	C.glfwHideWindow(w.data)
    653 	panicError()
    654 }
    655 
    656 // GetMonitor returns the handle of the monitor that the window is in
    657 // fullscreen on.
    658 //
    659 // Returns nil if the window is in windowed mode.
    660 func (w *Window) GetMonitor() *Monitor {
    661 	m := C.glfwGetWindowMonitor(w.data)
    662 	panicError()
    663 	if m == nil {
    664 		return nil
    665 	}
    666 	return &Monitor{m}
    667 }
    668 
    669 // SetMonitor sets the monitor that the window uses for full screen mode or,
    670 // if the monitor is NULL, makes it windowed mode.
    671 //
    672 // When setting a monitor, this function updates the width, height and refresh
    673 // rate of the desired video mode and switches to the video mode closest to it.
    674 // The window position is ignored when setting a monitor.
    675 //
    676 // When the monitor is NULL, the position, width and height are used to place
    677 // the window client area. The refresh rate is ignored when no monitor is specified.
    678 // If you only wish to update the resolution of a full screen window or the size of
    679 // a windowed mode window, see window.SetSize.
    680 //
    681 // When a window transitions from full screen to windowed mode, this function
    682 // restores any previous window settings such as whether it is decorated, floating,
    683 // resizable, has size or aspect ratio limits, etc..
    684 func (w *Window) SetMonitor(monitor *Monitor, xpos, ypos, width, height, refreshRate int) {
    685 	var m *C.GLFWmonitor
    686 	if monitor == nil {
    687 		m = nil
    688 	} else {
    689 		m = monitor.data
    690 	}
    691 	C.glfwSetWindowMonitor(w.data, m, C.int(xpos), C.int(ypos), C.int(width), C.int(height), C.int(refreshRate))
    692 	panicError()
    693 }
    694 
    695 // GetAttrib returns an attribute of the window. There are many attributes,
    696 // some related to the window and others to its context.
    697 func (w *Window) GetAttrib(attrib Hint) int {
    698 	ret := int(C.glfwGetWindowAttrib(w.data, C.int(attrib)))
    699 	panicError()
    700 	return ret
    701 }
    702 
    703 // SetAttrib function sets the value of an attribute of the specified window.
    704 //
    705 // The supported attributes are Decorated, Resizeable, Floating and AutoIconify.
    706 //
    707 // Some of these attributes are ignored for full screen windows. The new value
    708 // will take effect if the window is later made windowed.
    709 //
    710 // Some of these attributes are ignored for windowed mode windows. The new value
    711 // will take effect if the window is later made full screen.
    712 //
    713 // This function may only be called from the main thread.
    714 func (w *Window) SetAttrib(attrib Hint, value int) {
    715 	C.glfwSetWindowAttrib(w.data, C.int(attrib), C.int(value))
    716 }
    717 
    718 // SetUserPointer sets the user-defined pointer of the window. The current value
    719 // is retained until the window is destroyed. The initial value is nil.
    720 func (w *Window) SetUserPointer(pointer unsafe.Pointer) {
    721 	C.glfwSetWindowUserPointer(w.data, pointer)
    722 	panicError()
    723 }
    724 
    725 // GetUserPointer returns the current value of the user-defined pointer of the
    726 // window. The initial value is nil.
    727 func (w *Window) GetUserPointer() unsafe.Pointer {
    728 	ret := C.glfwGetWindowUserPointer(w.data)
    729 	panicError()
    730 	return ret
    731 }
    732 
    733 // PosCallback is the window position callback.
    734 type PosCallback func(w *Window, xpos int, ypos int)
    735 
    736 // SetPosCallback sets the position callback of the window, which is called
    737 // when the window is moved. The callback is provided with the screen position
    738 // of the upper-left corner of the client area of the window.
    739 func (w *Window) SetPosCallback(cbfun PosCallback) (previous PosCallback) {
    740 	previous = w.fPosHolder
    741 	w.fPosHolder = cbfun
    742 	if cbfun == nil {
    743 		C.glfwSetWindowPosCallback(w.data, nil)
    744 	} else {
    745 		C.glfwSetWindowPosCallbackCB(w.data)
    746 	}
    747 	panicError()
    748 	return previous
    749 }
    750 
    751 // SizeCallback is the window size callback.
    752 type SizeCallback func(w *Window, width int, height int)
    753 
    754 // SetSizeCallback sets the size callback of the window, which is called when
    755 // the window is resized. The callback is provided with the size, in screen
    756 // coordinates, of the client area of the window.
    757 func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
    758 	previous = w.fSizeHolder
    759 	w.fSizeHolder = cbfun
    760 	if cbfun == nil {
    761 		C.glfwSetWindowSizeCallback(w.data, nil)
    762 	} else {
    763 		C.glfwSetWindowSizeCallbackCB(w.data)
    764 	}
    765 	panicError()
    766 	return previous
    767 }
    768 
    769 // FramebufferSizeCallback is the framebuffer size callback.
    770 type FramebufferSizeCallback func(w *Window, width int, height int)
    771 
    772 // SetFramebufferSizeCallback sets the framebuffer resize callback of the specified
    773 // window, which is called when the framebuffer of the specified window is resized.
    774 func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
    775 	previous = w.fFramebufferSizeHolder
    776 	w.fFramebufferSizeHolder = cbfun
    777 	if cbfun == nil {
    778 		C.glfwSetFramebufferSizeCallback(w.data, nil)
    779 	} else {
    780 		C.glfwSetFramebufferSizeCallbackCB(w.data)
    781 	}
    782 	panicError()
    783 	return previous
    784 }
    785 
    786 // CloseCallback is the window close callback.
    787 type CloseCallback func(w *Window)
    788 
    789 // SetCloseCallback sets the close callback of the window, which is called when
    790 // the user attempts to close the window, for example by clicking the close
    791 // widget in the title bar.
    792 //
    793 // The close flag is set before this callback is called, but you can modify it at
    794 // any time with SetShouldClose.
    795 //
    796 // Mac OS X: Selecting Quit from the application menu will trigger the close
    797 // callback for all windows.
    798 func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
    799 	previous = w.fCloseHolder
    800 	w.fCloseHolder = cbfun
    801 	if cbfun == nil {
    802 		C.glfwSetWindowCloseCallback(w.data, nil)
    803 	} else {
    804 		C.glfwSetWindowCloseCallbackCB(w.data)
    805 	}
    806 	panicError()
    807 	return previous
    808 }
    809 
    810 // MaximizeCallback is the function signature for window maximize callback
    811 // functions.
    812 type MaximizeCallback func(w *Window, iconified bool)
    813 
    814 // SetMaximizeCallback sets the maximization callback of the specified window,
    815 // which is called when the window is maximized or restored.
    816 //
    817 // This function must only be called from the main thread.
    818 func (w *Window) SetMaximizeCallback(cbfun MaximizeCallback) MaximizeCallback {
    819 	previous := w.fMaximizeHolder
    820 	w.fMaximizeHolder = cbfun
    821 	if cbfun == nil {
    822 		C.glfwSetWindowMaximizeCallback(w.data, nil)
    823 	} else {
    824 		C.glfwSetWindowMaximizeCallbackCB(w.data)
    825 	}
    826 	return previous
    827 }
    828 
    829 // ContentScaleCallback is the function signature for window content scale
    830 // callback functions.
    831 type ContentScaleCallback func(w *Window, x float32, y float32)
    832 
    833 // SetContentScaleCallback function sets the window content scale callback of
    834 // the specified window, which is called when the content scale of the specified
    835 // window changes.
    836 //
    837 // This function must only be called from the main thread.
    838 func (w *Window) SetContentScaleCallback(cbfun ContentScaleCallback) ContentScaleCallback {
    839 	previous := w.fContentScaleHolder
    840 	w.fContentScaleHolder = cbfun
    841 	if cbfun == nil {
    842 		C.glfwSetWindowContentScaleCallback(w.data, nil)
    843 	} else {
    844 		C.glfwSetWindowContentScaleCallbackCB(w.data)
    845 	}
    846 	return previous
    847 }
    848 
    849 // RefreshCallback is the window refresh callback.
    850 type RefreshCallback func(w *Window)
    851 
    852 // SetRefreshCallback sets the refresh callback of the window, which
    853 // is called when the client area of the window needs to be redrawn, for example
    854 // if the window has been exposed after having been covered by another window.
    855 //
    856 // On compositing window systems such as Aero, Compiz or Aqua, where the window
    857 // contents are saved off-screen, this callback may be called only very
    858 // infrequently or never at all.
    859 func (w *Window) SetRefreshCallback(cbfun RefreshCallback) (previous RefreshCallback) {
    860 	previous = w.fRefreshHolder
    861 	w.fRefreshHolder = cbfun
    862 	if cbfun == nil {
    863 		C.glfwSetWindowRefreshCallback(w.data, nil)
    864 	} else {
    865 		C.glfwSetWindowRefreshCallbackCB(w.data)
    866 	}
    867 	panicError()
    868 	return previous
    869 }
    870 
    871 // FocusCallback is the window focus callback.
    872 type FocusCallback func(w *Window, focused bool)
    873 
    874 // SetFocusCallback sets the focus callback of the window, which is called when
    875 // the window gains or loses focus.
    876 //
    877 // After the focus callback is called for a window that lost focus, synthetic key
    878 // and mouse button release events will be generated for all such that had been
    879 // pressed. For more information, see SetKeyCallback and SetMouseButtonCallback.
    880 func (w *Window) SetFocusCallback(cbfun FocusCallback) (previous FocusCallback) {
    881 	previous = w.fFocusHolder
    882 	w.fFocusHolder = cbfun
    883 	if cbfun == nil {
    884 		C.glfwSetWindowFocusCallback(w.data, nil)
    885 	} else {
    886 		C.glfwSetWindowFocusCallbackCB(w.data)
    887 	}
    888 	panicError()
    889 	return previous
    890 }
    891 
    892 // IconifyCallback is the window iconification callback.
    893 type IconifyCallback func(w *Window, iconified bool)
    894 
    895 // SetIconifyCallback sets the iconification callback of the window, which is
    896 // called when the window is iconified or restored.
    897 func (w *Window) SetIconifyCallback(cbfun IconifyCallback) (previous IconifyCallback) {
    898 	previous = w.fIconifyHolder
    899 	w.fIconifyHolder = cbfun
    900 	if cbfun == nil {
    901 		C.glfwSetWindowIconifyCallback(w.data, nil)
    902 	} else {
    903 		C.glfwSetWindowIconifyCallbackCB(w.data)
    904 	}
    905 	panicError()
    906 	return previous
    907 }
    908 
    909 // SetClipboardString sets the system clipboard to the specified UTF-8 encoded
    910 // string.
    911 //
    912 // Ownership to the Window is no longer necessary, see
    913 // glfw.SetClipboardString(string)
    914 //
    915 // This function may only be called from the main thread.
    916 func (w *Window) SetClipboardString(str string) {
    917 	cp := C.CString(str)
    918 	defer C.free(unsafe.Pointer(cp))
    919 	C.glfwSetClipboardString(w.data, cp)
    920 	panicError()
    921 }
    922 
    923 // GetClipboardString returns the contents of the system clipboard, if it
    924 // contains or is convertible to a UTF-8 encoded string.
    925 //
    926 // Ownership to the Window is no longer necessary, see
    927 // glfw.GetClipboardString()
    928 //
    929 // This function may only be called from the main thread.
    930 func (w *Window) GetClipboardString() string {
    931 	cs := C.glfwGetClipboardString(w.data)
    932 	if cs == nil {
    933 		acceptError(FormatUnavailable)
    934 		return ""
    935 	}
    936 	return C.GoString(cs)
    937 }
    938 
    939 // panicErrorExceptForInvalidValue is the same as panicError but ignores
    940 // invalidValue.
    941 func panicErrorExceptForInvalidValue() {
    942 	// invalidValue can happen when specific joysticks are used. This issue
    943 	// will be fixed in GLFW 3.3.5. As a temporary fix, ignore this error.
    944 	// See go-gl/glfw#292, go-gl/glfw#324, and glfw/glfw#1763.
    945 	err := acceptError(invalidValue)
    946 	if e, ok := err.(*Error); ok && e.Code == invalidValue {
    947 		return
    948 	}
    949 	if err != nil {
    950 		panic(err)
    951 	}
    952 }
    953 
    954 // PollEvents processes only those events that have already been received and
    955 // then returns immediately. Processing events will cause the window and input
    956 // callbacks associated with those events to be called.
    957 //
    958 // This function is not required for joystick input to work.
    959 //
    960 // This function may not be called from a callback.
    961 //
    962 // This function may only be called from the main thread.
    963 func PollEvents() {
    964 	C.glfwPollEvents()
    965 	panicErrorExceptForInvalidValue()
    966 }
    967 
    968 // WaitEvents puts the calling thread to sleep until at least one event has been
    969 // received. Once one or more events have been recevied, it behaves as if
    970 // PollEvents was called, i.e. the events are processed and the function then
    971 // returns immediately. Processing events will cause the window and input
    972 // callbacks associated with those events to be called.
    973 //
    974 // Since not all events are associated with callbacks, this function may return
    975 // without a callback having been called even if you are monitoring all
    976 // callbacks.
    977 //
    978 // This function may not be called from a callback.
    979 //
    980 // This function may only be called from the main thread.
    981 func WaitEvents() {
    982 	C.glfwWaitEvents()
    983 	panicErrorExceptForInvalidValue()
    984 }
    985 
    986 // WaitEventsTimeout puts the calling thread to sleep until at least one event is available in the
    987 // event queue, or until the specified timeout is reached. If one or more events are available,
    988 // it behaves exactly like PollEvents, i.e. the events in the queue are processed and the function
    989 // then returns immediately. Processing events will cause the window and input callbacks associated
    990 // with those events to be called.
    991 //
    992 // The timeout value must be a positive finite number.
    993 //
    994 // Since not all events are associated with callbacks, this function may return without a callback
    995 // having been called even if you are monitoring all callbacks.
    996 //
    997 // On some platforms, a window move, resize or menu operation will cause event processing to block.
    998 // This is due to how event processing is designed on those platforms. You can use the window
    999 // refresh callback to redraw the contents of your window when necessary during such operations.
   1000 //
   1001 // On some platforms, certain callbacks may be called outside of a call to one of the event
   1002 // processing functions.
   1003 //
   1004 // If no windows exist, this function returns immediately. For synchronization of threads in
   1005 // applications that do not create windows, use native Go primitives.
   1006 //
   1007 // Event processing is not required for joystick input to work.
   1008 func WaitEventsTimeout(timeout float64) {
   1009 	C.glfwWaitEventsTimeout(C.double(timeout))
   1010 	panicErrorExceptForInvalidValue()
   1011 }
   1012 
   1013 // PostEmptyEvent posts an empty event from the current thread to the main
   1014 // thread event queue, causing WaitEvents to return.
   1015 //
   1016 // If no windows exist, this function returns immediately. For synchronization of threads in
   1017 // applications that do not create windows, use native Go primitives.
   1018 //
   1019 // This function may be called from secondary threads.
   1020 func PostEmptyEvent() {
   1021 	C.glfwPostEmptyEvent()
   1022 	panicError()
   1023 }