ui: Implement SetWindowDecorated and IsWindowDecorated

Fixes #430.
This commit is contained in:
Hajime Hoshi 2017-09-14 03:37:38 +09:00
parent ce4e00ff79
commit 526fbd3619
5 changed files with 120 additions and 13 deletions

View File

@ -18,6 +18,8 @@ package main
import (
"bytes"
"errors"
"flag"
"fmt"
"image"
"image/color"
@ -33,6 +35,10 @@ import (
"github.com/hajimehoshi/ebiten/inpututil"
)
var (
windowDecorated = flag.Bool("windowdecorated", true, "whether the window is decorated")
)
func init() {
rand.Seed(time.Now().UnixNano())
}
@ -67,7 +73,13 @@ func createRandomIconImage() image.Image {
return img
}
var terminated = errors.New("terminated")
func update(screen *ebiten.Image) error {
if inpututil.IsKeyJustPressed(ebiten.KeyQ) {
return terminated
}
screenScale := ebiten.ScreenScale()
d := int(32 / screenScale)
screenWidth, screenHeight := screen.Size()
@ -145,6 +157,7 @@ Press F key to switch the fullscreen state
Press B key to switch the run-in-background state
Press C key to switch the cursor visibility
Press I key to change the window icon
Press Q key to quit
Cursor: (%d, %d)
FPS: %0.2f`, x, y, ebiten.CurrentFPS())
ebitenutil.DebugPrint(screen, msg)
@ -152,6 +165,8 @@ FPS: %0.2f`, x, y, ebiten.CurrentFPS())
}
func main() {
flag.Parse()
fmt.Printf("Device scale factor: %0.2f\n", ebiten.DeviceScaleFactor())
// Decode image from a byte slice instead of a file so that
@ -171,7 +186,9 @@ func main() {
ebiten.SetWindowIcon([]image.Image{createRandomIconImage()})
if err := ebiten.Run(update, initScreenWidth, initScreenHeight, initScreenScale, "Window Size (Ebiten Demo)"); err != nil {
ebiten.SetWindowDecorated(*windowDecorated)
if err := ebiten.Run(update, initScreenWidth, initScreenHeight, initScreenScale, "Window Size (Ebiten Demo)"); err != nil && err != terminated {
log.Fatal(err)
}
}

View File

@ -48,9 +48,10 @@ type userInterface struct {
origPosY int
runnableInBackground bool
initFullscreen bool
initCursorVisible bool
initIconImages []image.Image
initFullscreen bool
initCursorVisible bool
initWindowDecorated bool
initIconImages []image.Image
funcs chan func()
@ -59,10 +60,10 @@ type userInterface struct {
var (
currentUI = &userInterface{
toChangeSize: true,
origPosX: -1,
origPosY: -1,
initCursorVisible: true,
origPosX: -1,
origPosY: -1,
initCursorVisible: true,
initWindowDecorated: true,
}
currentUIInitialized = make(chan struct{})
)
@ -80,6 +81,12 @@ func initialize() error {
glfw.WindowHint(glfw.ContextVersionMajor, 2)
glfw.WindowHint(glfw.ContextVersionMinor, 1)
decorated := glfw.False
if currentUI.isInitWindowDecorated() {
decorated = glfw.True
}
glfw.WindowHint(glfw.Decorated, decorated)
// As start, create an window with temporary size to create OpenGL context thread.
window, err := glfw.CreateWindow(16, 16, "", nil, nil)
if err != nil {
@ -99,6 +106,7 @@ func initialize() error {
currentUI.window.SetIcon(i)
}
currentUI.window.SetInputMode(glfw.CursorMode, mode)
currentUI.window.SetInputMode(glfw.StickyMouseButtonsMode, glfw.True)
currentUI.window.SetInputMode(glfw.StickyKeysMode, glfw.True)
return nil
@ -167,6 +175,19 @@ func (u *userInterface) setInitCursorVisible(visible bool) {
u.m.Unlock()
}
func (u *userInterface) isInitWindowDecorated() bool {
u.m.Lock()
v := u.initWindowDecorated
u.m.Unlock()
return v
}
func (u *userInterface) setInitWindowDecorated(decorated bool) {
u.m.Lock()
u.initWindowDecorated = decorated
u.m.Unlock()
}
func (u *userInterface) isRunnableInBackground() bool {
u.m.Lock()
v := u.runnableInBackground
@ -369,6 +390,40 @@ func SetCursorVisible(visible bool) {
})
}
func IsWindowDecorated() bool {
u := currentUI
if !u.isRunning() {
return u.isInitWindowDecorated()
}
v := false
_ = currentUI.runOnMainThread(func() error {
v = currentUI.window.GetAttrib(glfw.Decorated) == glfw.True
return nil
})
return v
}
func SetWindowDecorated(decorated bool) {
u := currentUI
if !u.isRunning() {
u.setInitWindowDecorated(decorated)
return
}
panic("ui: SetWindowDecorated can't be called after Run so far.")
// TODO: Now SetAttrib doesn't exist on GLFW 3.2. Revisit later.
// If SetAttrib exists, the implementation would be:
//
// _ = currentUI.runOnMainThread(func() error {
// v := glfw.False
// if decorated {
// v = glfw.True
// }
// currentUI.window.SetAttrib(glfw.Decorated, v)
// return nil
}
func Run(width, height int, scale float64, title string, g GraphicsContext) error {
<-currentUIInitialized

View File

@ -98,6 +98,14 @@ func SetWindowIcon(iconImages []image.Image) {
// Do nothing
}
func IsWindowDecorated() bool {
return false
}
func SetWindowDecorated(decorated bool) {
// Do nothing
}
func (u *userInterface) getScale() float64 {
if !u.fullscreen {
return u.scale

View File

@ -172,12 +172,15 @@ func SetCursorVisible(visible bool) {
// Do nothing
}
func IsFullscreen() bool {
return false
}
func SetFullscreen(fullscreen bool) {
// Do nothing
}
func IsFullscreen() bool {
// Do nothing
func IsRunnableInBackground() bool {
return false
}
@ -185,12 +188,15 @@ func SetRunnableInBackground(runnableInBackground bool) {
// Do nothing
}
func IsRunnableInBackground() bool {
func SetWindowIcon(iconImages []image.Image) {
// Do nothing
}
func IsWindowDecorated() bool {
return false
}
func SetWindowIcon(iconImages []image.Image) {
func SetWindowDecorated(decorated bool) {
// Do nothing
}

23
run.go
View File

@ -246,13 +246,34 @@ func SetFullscreen(fullscreen bool) {
ui.SetFullscreen(fullscreen)
}
// IsRunnableInBackground returns a boolean value indicating whether the game runs even in background.
// IsRunnableInBackground returns a boolean value indicating whether
// the game runs even in background.
//
// This function is concurrent-safe.
func IsRunnableInBackground() bool {
return ui.IsRunnableInBackground()
}
// SetWindowDecorated sets the state if the window is decorated.
//
// SetWindowDecorated works only on desktops.
// SetWindowDecorated does nothing on other platforms.
//
// SetWindowDecorated panics if SetWindowDecorated is called after Run.
//
// This function is concurrent-safe.
func SetWindowDecorated(decorated bool) {
ui.SetWindowDecorated(decorated)
}
// IsWindowDecorated returns a boolean value indicating whether
// the window is decorated.
//
// This function is concurrent-safe.
func IsWindowDecorated() bool {
return ui.IsWindowDecorated()
}
// SetRunnableInBackground sets the state if the game runs even in background.
//
// If the given value is true, the game runs in background e.g. when losing focus.