ui: Add SetWindowFloating / IsWindowFloating

Fixes #880
This commit is contained in:
Hajime Hoshi 2020-03-20 21:46:23 +09:00
parent bcf2d409ef
commit 4ef3b3e804
6 changed files with 90 additions and 10 deletions

View File

@ -58,6 +58,7 @@ var (
flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)")
flagScreenTransparent = flag.Bool("screentransparent", false, "screen transparent")
flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting")
flagFloating = flag.Bool("floating", false, "make the window floating")
)
func init() {
@ -137,6 +138,7 @@ func (g *game) Update(screen *ebiten.Image) error {
decorated := ebiten.IsWindowDecorated()
positionX, positionY := ebiten.WindowPosition()
transparent := ebiten.IsScreenTransparent()
floating := ebiten.IsWindowFloating()
resizable := ebiten.IsWindowResizable()
const d = 16
@ -218,6 +220,9 @@ func (g *game) Update(screen *ebiten.Image) error {
if inpututil.IsKeyJustPressed(ebiten.KeyD) {
decorated = !decorated
}
if inpututil.IsKeyJustPressed(ebiten.KeyL) {
floating = !floating
}
if inpututil.IsKeyJustPressed(ebiten.KeyR) {
resizable = !resizable
}
@ -239,6 +244,7 @@ func (g *game) Update(screen *ebiten.Image) error {
ebiten.SetMaxTPS(tps)
ebiten.SetWindowDecorated(decorated)
ebiten.SetWindowPosition(positionX, positionY)
ebiten.SetWindowFloating(floating)
if !*flagLegacy {
// A resizable window is available only with RunGame.
ebiten.SetWindowResizable(resizable)
@ -294,6 +300,7 @@ Press I key to change the window icon (only for desktops)
Press V key to switch vsync
Press T key to switch TPS (ticks per second)
Press D key to switch the window decoration (only for desktops)
Press L key to switch the window floating state (only for desktops)
%s
IsForeground?: %s
Windows Position: (%d, %d)
@ -363,6 +370,9 @@ func main() {
if *flagFullscreen {
ebiten.SetFullscreen(true)
}
if *flagFloating {
ebiten.SetWindowFloating(true)
}
if *flagAutoAdjusting {
if *flagLegacy {
log.Println("-autoadjusting flag cannot work with -legacy flag")

View File

@ -68,6 +68,9 @@ type Window interface {
Size() (int, int)
SetSize(width, height int)
IsFloating() bool
SetFloating(floating bool)
SetIcon(iconImages []image.Image)
SetTitle(title string)
}

View File

@ -77,6 +77,7 @@ const (
ContextVersionMajor = Hint(0x00022002)
ContextVersionMinor = Hint(0x00022003)
Decorated = Hint(0x00020005)
Floating = Hint(0x00020007)
Focused = Hint(0x00020001)
Resizable = Hint(0x00020003)
TransparentFramebuffer = Hint(0x0002000A)

View File

@ -66,6 +66,7 @@ type UserInterface struct {
initWindowPositionYInDP int
initWindowWidthInDP int
initWindowHeightInDP int
initWindowFloating bool
initScreenTransparent bool
initIconImages []image.Image
@ -334,6 +335,19 @@ func (u *UserInterface) setInitWindowSize(width, height int) {
u.m.Unlock()
}
func (u *UserInterface) isInitWindowFloating() bool {
u.m.Lock()
f := u.initWindowFloating
u.m.Unlock()
return f
}
func (u *UserInterface) setInitWindowFloating(floating bool) {
u.m.Lock()
u.initWindowFloating = floating
u.m.Unlock()
}
// toDeviceIndependentPixel must be called from the main thread.
func (u *UserInterface) toDeviceIndependentPixel(x float64) float64 {
return x / u.glfwScale()
@ -628,6 +642,12 @@ func (u *UserInterface) run(context driver.UIContext) error {
}
glfw.WindowHint(glfw.Resizable, resizable)
floating := glfw.False
if u.isInitWindowFloating() {
floating = glfw.True
}
glfw.WindowHint(glfw.Floating, floating)
// Set the window visible explicitly or the application freezes on Wayland (#974).
if os.Getenv("WAYLAND_DISPLAY") != "" {
glfw.WindowHint(glfw.Visible, glfw.True)

View File

@ -89,6 +89,33 @@ func (w *window) SetResizable(resizable bool) {
})
}
func (w *window) IsFloating() bool {
if !w.ui.isRunning() {
return w.ui.isInitWindowFloating()
}
var v bool
_ = w.ui.t.Call(func() error {
v = w.ui.window.GetAttrib(glfw.Floating) == glfw.True
return nil
})
return v
}
func (w *window) SetFloating(floating bool) {
if !w.ui.isRunning() {
w.ui.setInitWindowFloating(floating)
return
}
_ = w.ui.t.Call(func() error {
v := glfw.False
if floating {
v = glfw.True
}
w.ui.window.SetAttrib(glfw.Floating, v)
return nil
})
}
func (w *window) Position() (int, int) {
if !w.ui.isRunning() {
panic("glfw: WindowPosition can't be called before the main loop starts")

View File

@ -25,6 +25,16 @@ const (
invalidPos = minInt
)
// IsWindowDecorated reports whether the window is decorated.
//
// IsWindowDecorated is concurrent-safe.
func IsWindowDecorated() bool {
if w := uiDriver().Window(); w != nil {
return w.IsDecorated()
}
return false
}
// SetWindowDecorated sets the state if the window is decorated.
//
// The window is decorated by default.
@ -39,16 +49,6 @@ func SetWindowDecorated(decorated bool) {
}
}
// IsWindowDecorated reports whether the window is decorated.
//
// IsWindowDecorated is concurrent-safe.
func IsWindowDecorated() bool {
if w := uiDriver().Window(); w != nil {
return w.IsDecorated()
}
return false
}
// IsWindowResizable reports whether the window is resizable by the user's dragging on desktops.
// On the other environments, IsWindowResizable always returns false.
//
@ -233,3 +233,22 @@ func SetWindowSize(width, height int) {
w.SetSize(width, height)
}
}
// IsWindowFloating reports whether the window is always shown above all the other windows.
//
// IsWindowFloating is concurrent-safe.
func IsWindowFloating() bool {
if w := uiDriver().Window(); w != nil {
return w.IsFloating()
}
return false
}
// SetWindowFloating sets the state whether the window is always shown above all the other windows.
//
// SetWindowFloating is concurrent-safe.
func SetWindowFloating(float bool) {
if w := uiDriver().Window(); w != nil {
w.SetFloating(float)
}
}