zorldo

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

glfw_windows.go (12678B)


      1 // Copyright 2018 The Ebiten Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package glfw
     16 
     17 import (
     18 	"image"
     19 	"image/draw"
     20 	"math/bits"
     21 	"reflect"
     22 	"runtime"
     23 	"sync"
     24 	"unsafe"
     25 
     26 	"golang.org/x/sys/windows"
     27 )
     28 
     29 type glfwImage struct {
     30 	width  int32
     31 	height int32
     32 	pixels uintptr
     33 }
     34 
     35 type glfwWindows map[uintptr]*Window
     36 
     37 var (
     38 	theGLFWWindows = glfwWindows{}
     39 	glfwWindowsM   sync.Mutex
     40 )
     41 
     42 func (w glfwWindows) add(win uintptr) *Window {
     43 	if win == 0 {
     44 		return nil
     45 	}
     46 	ww := &Window{w: win}
     47 	glfwWindowsM.Lock()
     48 	w[win] = ww
     49 	glfwWindowsM.Unlock()
     50 	return ww
     51 }
     52 
     53 func (w glfwWindows) remove(win uintptr) {
     54 	glfwWindowsM.Lock()
     55 	delete(w, win)
     56 	glfwWindowsM.Unlock()
     57 }
     58 
     59 func (w glfwWindows) get(win uintptr) *Window {
     60 	if win == 0 {
     61 		return nil
     62 	}
     63 	glfwWindowsM.Lock()
     64 	ww := w[win]
     65 	glfwWindowsM.Unlock()
     66 	return ww
     67 }
     68 
     69 type Cursor struct {
     70 	c uintptr
     71 }
     72 
     73 func CreateStandardCursor(shape StandardCursor) *Cursor {
     74 	c := glfwDLL.call("glfwCreateStandardCursor", uintptr(shape))
     75 	panicError()
     76 	return &Cursor{c: c}
     77 }
     78 
     79 type Monitor struct {
     80 	m uintptr
     81 }
     82 
     83 func (m *Monitor) GetContentScale() (float32, float32) {
     84 	var sx, sy float32
     85 	glfwDLL.call("glfwGetMonitorContentScale", m.m, uintptr(unsafe.Pointer(&sx)), uintptr(unsafe.Pointer(&sy)))
     86 	panicError()
     87 	return sx, sy
     88 }
     89 
     90 func (m *Monitor) GetPos() (int, int) {
     91 	var x, y int32
     92 	glfwDLL.call("glfwGetMonitorPos", m.m, uintptr(unsafe.Pointer(&x)), uintptr(unsafe.Pointer(&y)))
     93 	panicError()
     94 	return int(x), int(y)
     95 }
     96 
     97 func (m *Monitor) GetVideoMode() *VidMode {
     98 	v := glfwDLL.call("glfwGetVideoMode", m.m)
     99 	panicError()
    100 	var vals []int32
    101 	h := (*reflect.SliceHeader)(unsafe.Pointer(&vals))
    102 	h.Data = v
    103 	h.Len = 6
    104 	h.Cap = 6
    105 	return &VidMode{
    106 		Width:       int(vals[0]),
    107 		Height:      int(vals[1]),
    108 		RedBits:     int(vals[2]),
    109 		GreenBits:   int(vals[3]),
    110 		BlueBits:    int(vals[4]),
    111 		RefreshRate: int(vals[5]),
    112 	}
    113 }
    114 
    115 type Window struct {
    116 	w uintptr
    117 
    118 	prevSizeCallback SizeCallback
    119 }
    120 
    121 func (w *Window) Destroy() {
    122 	glfwDLL.call("glfwDestroyWindow", w.w)
    123 	panicError()
    124 	theGLFWWindows.remove(w.w)
    125 }
    126 
    127 func (w *Window) GetAttrib(attrib Hint) int {
    128 	r := glfwDLL.call("glfwGetWindowAttrib", w.w, uintptr(attrib))
    129 	panicError()
    130 	return int(r)
    131 }
    132 
    133 func (w *Window) SetAttrib(attrib Hint, value int) {
    134 	glfwDLL.call("glfwSetWindowAttrib", w.w, uintptr(attrib), uintptr(value))
    135 	panicError()
    136 }
    137 
    138 func (w *Window) GetCursorPos() (x, y float64) {
    139 	glfwDLL.call("glfwGetCursorPos", w.w, uintptr(unsafe.Pointer(&x)), uintptr(unsafe.Pointer(&y)))
    140 	panicError()
    141 	return
    142 }
    143 
    144 func (w *Window) GetInputMode(mode InputMode) int {
    145 	r := glfwDLL.call("glfwGetInputMode", w.w, uintptr(mode))
    146 	panicError()
    147 	return int(r)
    148 }
    149 
    150 func (w *Window) GetKey(key Key) Action {
    151 	r := glfwDLL.call("glfwGetKey", w.w, uintptr(key))
    152 	panicError()
    153 	return Action(r)
    154 }
    155 
    156 func (w *Window) GetMonitor() *Monitor {
    157 	m := glfwDLL.call("glfwGetWindowMonitor", w.w)
    158 	panicError()
    159 	if m == 0 {
    160 		return nil
    161 	}
    162 	return &Monitor{m}
    163 }
    164 
    165 func (w *Window) GetMouseButton(button MouseButton) Action {
    166 	r := glfwDLL.call("glfwGetMouseButton", w.w, uintptr(button))
    167 	panicError()
    168 	return Action(r)
    169 }
    170 
    171 func (w *Window) GetPos() (int, int) {
    172 	var x, y int32
    173 	glfwDLL.call("glfwGetWindowPos", w.w, uintptr(unsafe.Pointer(&x)), uintptr(unsafe.Pointer(&y)))
    174 	panicError()
    175 	return int(x), int(y)
    176 }
    177 
    178 func (w *Window) GetSize() (int, int) {
    179 	var width, height int32
    180 	glfwDLL.call("glfwGetWindowSize", w.w, uintptr(unsafe.Pointer(&width)), uintptr(unsafe.Pointer(&height)))
    181 	panicError()
    182 	return int(width), int(height)
    183 }
    184 
    185 func (w *Window) Hide() {
    186 	glfwDLL.call("glfwHideWindow", w.w)
    187 	panicError()
    188 }
    189 
    190 func (w *Window) Iconify() {
    191 	glfwDLL.call("glfwIconifyWindow", w.w)
    192 	panicError()
    193 }
    194 
    195 func (w *Window) MakeContextCurrent() {
    196 	glfwDLL.call("glfwMakeContextCurrent", w.w)
    197 	panicError()
    198 }
    199 
    200 func (w *Window) Maximize() {
    201 	glfwDLL.call("glfwMaximizeWindow", w.w)
    202 	panicError()
    203 }
    204 
    205 func (w *Window) Restore() {
    206 	glfwDLL.call("glfwRestoreWindow", w.w)
    207 	panicError()
    208 }
    209 
    210 func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
    211 	glfwDLL.call("glfwSetCharModsCallback", w.w, uintptr(cbfun))
    212 	panicError()
    213 	return ToCharModsCallback(nil) // TODO
    214 }
    215 
    216 func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
    217 	glfwDLL.call("glfwSetWindowCloseCallback", w.w, uintptr(cbfun))
    218 	panicError()
    219 	return ToCloseCallback(nil) // TODO
    220 }
    221 
    222 func (w *Window) SetCursor(cursor *Cursor) {
    223 	var c uintptr
    224 	if cursor != nil {
    225 		c = cursor.c
    226 	}
    227 	glfwDLL.call("glfwSetCursor", w.w, c)
    228 }
    229 
    230 func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
    231 	glfwDLL.call("glfwSetFramebufferSizeCallback", w.w, uintptr(cbfun))
    232 	panicError()
    233 	return ToFramebufferSizeCallback(nil) // TODO
    234 }
    235 
    236 func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
    237 	glfwDLL.call("glfwSetScrollCallback", w.w, uintptr(cbfun))
    238 	panicError()
    239 	return ToScrollCallback(nil) // TODO
    240 }
    241 
    242 func (w *Window) SetShouldClose(value bool) {
    243 	var v uintptr = False
    244 	if value {
    245 		v = True
    246 	}
    247 	glfwDLL.call("glfwSetWindowShouldClose", w.w, v)
    248 	panicError()
    249 }
    250 
    251 func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
    252 	glfwDLL.call("glfwSetWindowSizeCallback", w.w, uintptr(cbfun))
    253 	panicError()
    254 	prev := w.prevSizeCallback
    255 	w.prevSizeCallback = cbfun
    256 	return prev
    257 }
    258 
    259 func (w *Window) SetSizeLimits(minw, minh, maxw, maxh int) {
    260 	glfwDLL.call("glfwSetWindowSizeLimits", w.w, uintptr(minw), uintptr(minh), uintptr(maxw), uintptr(maxh))
    261 	panicError()
    262 }
    263 
    264 func (w *Window) SetIcon(images []image.Image) {
    265 	gimgs := make([]glfwImage, len(images))
    266 	defer runtime.KeepAlive(gimgs)
    267 
    268 	for i, img := range images {
    269 		b := img.Bounds()
    270 		m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
    271 		draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
    272 		gimgs[i].width = int32(b.Dx())
    273 		gimgs[i].height = int32(b.Dy())
    274 		gimgs[i].pixels = uintptr(unsafe.Pointer(&m.Pix[0]))
    275 	}
    276 
    277 	glfwDLL.call("glfwSetWindowIcon", w.w, uintptr(len(gimgs)), uintptr(unsafe.Pointer(&gimgs[0])))
    278 	panicError()
    279 }
    280 
    281 func (w *Window) SetInputMode(mode InputMode, value int) {
    282 	glfwDLL.call("glfwSetInputMode", w.w, uintptr(mode), uintptr(value))
    283 	panicError()
    284 }
    285 
    286 func (w *Window) SetMonitor(monitor *Monitor, xpos, ypos, width, height, refreshRate int) {
    287 	var m uintptr
    288 	if monitor != nil {
    289 		m = monitor.m
    290 	}
    291 	glfwDLL.call("glfwSetWindowMonitor", w.w, m, uintptr(xpos), uintptr(ypos), uintptr(width), uintptr(height), uintptr(refreshRate))
    292 	panicError()
    293 }
    294 
    295 func (w *Window) SetPos(xpos, ypos int) {
    296 	glfwDLL.call("glfwSetWindowPos", w.w, uintptr(xpos), uintptr(ypos))
    297 	panicError()
    298 }
    299 
    300 func (w *Window) SetSize(width, height int) {
    301 	glfwDLL.call("glfwSetWindowSize", w.w, uintptr(width), uintptr(height))
    302 	panicError()
    303 }
    304 
    305 func (w *Window) SetTitle(title string) {
    306 	s := []byte(title)
    307 	s = append(s, 0)
    308 	defer runtime.KeepAlive(s)
    309 	glfwDLL.call("glfwSetWindowTitle", w.w, uintptr(unsafe.Pointer(&s[0])))
    310 	panicError()
    311 }
    312 
    313 func (w *Window) ShouldClose() bool {
    314 	r := glfwDLL.call("glfwWindowShouldClose", w.w)
    315 	panicError()
    316 	return byte(r) == True
    317 }
    318 
    319 func (w *Window) Show() {
    320 	glfwDLL.call("glfwShowWindow", w.w)
    321 	panicError()
    322 }
    323 
    324 func (w *Window) SwapBuffers() {
    325 	glfwDLL.call("glfwSwapBuffers", w.w)
    326 	panicError()
    327 }
    328 
    329 func CreateWindow(width, height int, title string, monitor *Monitor, share *Window) (*Window, error) {
    330 	s := []byte(title)
    331 	s = append(s, 0)
    332 	defer runtime.KeepAlive(s)
    333 
    334 	var gm uintptr
    335 	if monitor != nil {
    336 		gm = monitor.m
    337 	}
    338 	var gw uintptr
    339 	if share != nil {
    340 		gw = share.w
    341 	}
    342 
    343 	w := glfwDLL.call("glfwCreateWindow", uintptr(width), uintptr(height), uintptr(unsafe.Pointer(&s[0])), gm, gw)
    344 	if w == 0 {
    345 		return nil, acceptError(APIUnavailable, VersionUnavailable)
    346 	}
    347 	return theGLFWWindows.add(w), nil
    348 }
    349 
    350 func (j Joystick) GetGUID() string {
    351 	ptr := glfwDLL.call("glfwGetJoystickGUID", uintptr(j))
    352 	panicError()
    353 
    354 	// ptr can be nil after disconnecting the joystick.
    355 	if ptr == 0 {
    356 		return ""
    357 	}
    358 
    359 	var backed [256]byte
    360 	as := backed[:0]
    361 	for i := int32(0); ; i++ {
    362 		b := *(*byte)(unsafe.Pointer(ptr))
    363 		ptr += unsafe.Sizeof(byte(0))
    364 		if b == 0 {
    365 			break
    366 		}
    367 		as = append(as, b)
    368 	}
    369 	r := string(as)
    370 	return r
    371 }
    372 
    373 func (j Joystick) GetName() string {
    374 	ptr := glfwDLL.call("glfwGetJoystickName", uintptr(j))
    375 	panicError()
    376 
    377 	// ptr can be nil after disconnecting the joystick.
    378 	if ptr == 0 {
    379 		return ""
    380 	}
    381 
    382 	var backed [256]byte
    383 	as := backed[:0]
    384 	for i := int32(0); ; i++ {
    385 		b := *(*byte)(unsafe.Pointer(ptr))
    386 		ptr += unsafe.Sizeof(byte(0))
    387 		if b == 0 {
    388 			break
    389 		}
    390 		as = append(as, b)
    391 	}
    392 	r := string(as)
    393 	return r
    394 }
    395 
    396 func (j Joystick) GetAxes() []float32 {
    397 	var l int32
    398 	ptr := glfwDLL.call("glfwGetJoystickAxes", uintptr(j), uintptr(unsafe.Pointer(&l)))
    399 	panicError()
    400 
    401 	// ptr can be nil after disconnecting the joystick.
    402 	if ptr == 0 {
    403 		return nil
    404 	}
    405 
    406 	as := make([]float32, l)
    407 	for i := int32(0); i < l; i++ {
    408 		as[i] = *(*float32)(unsafe.Pointer(ptr))
    409 		ptr += unsafe.Sizeof(float32(0))
    410 	}
    411 	return as
    412 }
    413 
    414 func (j Joystick) GetButtons() []byte {
    415 	var l int32
    416 	ptr := glfwDLL.call("glfwGetJoystickButtons", uintptr(j), uintptr(unsafe.Pointer(&l)))
    417 	panicError()
    418 
    419 	// ptr can be nil after disconnecting the joystick.
    420 	if ptr == 0 {
    421 		return nil
    422 	}
    423 
    424 	bs := make([]byte, l)
    425 	for i := int32(0); i < l; i++ {
    426 		bs[i] = *(*byte)(unsafe.Pointer(ptr))
    427 		ptr++
    428 	}
    429 	return bs
    430 }
    431 
    432 func (j Joystick) GetHats() []JoystickHatState {
    433 	var l int32
    434 	ptr := glfwDLL.call("glfwGetJoystickHats", uintptr(j), uintptr(unsafe.Pointer(&l)))
    435 	panicError()
    436 
    437 	// ptr can be nil after disconnecting the joystick.
    438 	if ptr == 0 {
    439 		return nil
    440 	}
    441 
    442 	hats := make([]JoystickHatState, l)
    443 	for i := int32(0); i < l; i++ {
    444 		hats[i] = *(*JoystickHatState)(unsafe.Pointer(ptr))
    445 		ptr++
    446 	}
    447 	return hats
    448 }
    449 
    450 func GetMonitors() []*Monitor {
    451 	var l int32
    452 	ptr := glfwDLL.call("glfwGetMonitors", uintptr(unsafe.Pointer(&l)))
    453 	panicError()
    454 	ms := make([]*Monitor, l)
    455 	for i := int32(0); i < l; i++ {
    456 		m := *(*unsafe.Pointer)(unsafe.Pointer(ptr))
    457 		if m != nil {
    458 			ms[i] = &Monitor{uintptr(m)}
    459 		}
    460 		ptr += bits.UintSize / 8
    461 	}
    462 	return ms
    463 }
    464 
    465 func GetPrimaryMonitor() *Monitor {
    466 	m := glfwDLL.call("glfwGetPrimaryMonitor")
    467 	panicError()
    468 	if m == 0 {
    469 		return nil
    470 	}
    471 	return &Monitor{m}
    472 }
    473 
    474 func Init() error {
    475 	glfwDLL.call("glfwInit")
    476 	// InvalidValue can happen when specific joysticks are used. This issue
    477 	// will be fixed in GLFW 3.3.5. As a temporary fix, ignore this error.
    478 	// See go-gl/glfw#292, go-gl/glfw#324, and glfw/glfw#1763
    479 	// (#1229).
    480 	err := acceptError(APIUnavailable, InvalidValue)
    481 	if e, ok := err.(*glfwError); ok && e.code == InvalidValue {
    482 		return nil
    483 	}
    484 	return err
    485 }
    486 
    487 func (j Joystick) Present() bool {
    488 	r := glfwDLL.call("glfwJoystickPresent", uintptr(j))
    489 	panicError()
    490 	return byte(r) == True
    491 }
    492 
    493 func panicErrorExceptForInvalidValue() {
    494 	// InvalidValue can happen when specific joysticks are used. This issue
    495 	// will be fixed in GLFW 3.3.5. As a temporary fix, ignore this error.
    496 	// See go-gl/glfw#292, go-gl/glfw#324, and glfw/glfw#1763
    497 	// (#1229).
    498 	err := acceptError(InvalidValue)
    499 	if e, ok := err.(*glfwError); ok && e.code == InvalidValue {
    500 		return
    501 	}
    502 	if err != nil {
    503 		panic(err)
    504 	}
    505 }
    506 
    507 func PollEvents() {
    508 	glfwDLL.call("glfwPollEvents")
    509 	// This should be used for WaitEvents and WaitEventsTimeout if needed.
    510 	panicErrorExceptForInvalidValue()
    511 }
    512 
    513 func PostEmptyEvent() {
    514 	glfwDLL.call("glfwPostEmptyEvent")
    515 	panicError()
    516 }
    517 
    518 func SetMonitorCallback(cbfun func(monitor *Monitor, event PeripheralEvent)) {
    519 	var gcb uintptr
    520 	if cbfun != nil {
    521 		gcb = windows.NewCallbackCDecl(func(monitor uintptr, event PeripheralEvent) uintptr {
    522 			var m *Monitor
    523 			if monitor != 0 {
    524 				m = &Monitor{monitor}
    525 			}
    526 			cbfun(m, event)
    527 			return 0
    528 		})
    529 	}
    530 	glfwDLL.call("glfwSetMonitorCallback", gcb)
    531 	panicError()
    532 }
    533 
    534 func SwapInterval(interval int) {
    535 	glfwDLL.call("glfwSwapInterval", uintptr(interval))
    536 	panicError()
    537 }
    538 
    539 func Terminate() {
    540 	flushErrors()
    541 	glfwDLL.call("glfwTerminate")
    542 	if err := glfwDLL.unload(); err != nil {
    543 		panic(err)
    544 	}
    545 }
    546 
    547 func WaitEvents() {
    548 	glfwDLL.call("glfwWaitEvents")
    549 	panicError()
    550 }
    551 
    552 func WindowHint(target Hint, hint int) {
    553 	glfwDLL.call("glfwWindowHint", uintptr(target), uintptr(hint))
    554 	panicError()
    555 }