diff --git a/examples/windowsize/main.go b/examples/windowsize/main.go index c2073e0cf..be130f4d7 100644 --- a/examples/windowsize/main.go +++ b/examples/windowsize/main.go @@ -475,6 +475,8 @@ func main() { } op.InitUnfocused = !*flagInitFocused op.ScreenTransparent = *flagTransparent + op.X11ClassName = "Window-Size" + op.X11InstanceName = "window-size" const title = "Window Size (Ebitengine Demo)" ww := int(float64(g.width) * initScreenScale) diff --git a/internal/glfw/const.go b/internal/glfw/const.go index 3f189a7b9..4db620800 100644 --- a/internal/glfw/const.go +++ b/internal/glfw/const.go @@ -110,6 +110,8 @@ const ( Stereo = Hint(0x0002100C) TransparentFramebuffer = Hint(0x0002000A) Visible = Hint(0x00020004) + X11ClassName = Hint(0x00024001) + X11InstanceName = Hint(0x00024002) ) const ( diff --git a/internal/glfw/window_unix.go b/internal/glfw/window_unix.go index b4320f8d8..8c1ea85d0 100644 --- a/internal/glfw/window_unix.go +++ b/internal/glfw/window_unix.go @@ -225,10 +225,14 @@ func WindowHint(target Hint, hint int) error { // Setting these hints requires no platform specific headers or functions. // // This function must only be called from the main thread. -func WindowHintString(hint Hint, value string) { +func WindowHintString(hint Hint, value string) error { str := C.CString(value) defer C.free(unsafe.Pointer(str)) C.glfwWindowHintString(C.int(hint), str) + if err := fetchErrorIgnoringPlatformError(); err != nil { + return err + } + return nil } // CreateWindow creates a window and its associated context. Most of the options diff --git a/internal/glfw/window_windows.go b/internal/glfw/window_windows.go index 9ac995c9d..2e0d79fff 100644 --- a/internal/glfw/window_windows.go +++ b/internal/glfw/window_windows.go @@ -284,6 +284,10 @@ func WindowHint(hint Hint, value int) error { } // WindowHintString is not implemented. +func WindowHintString(hint Hint, value string) error { + // Do nothing. + return nil +} func (w *Window) Destroy() error { if !_glfw.initialized { diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 83ef4f1ea..dba4e29cb 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -144,6 +144,8 @@ type RunOptions struct { ScreenTransparent bool SkipTaskbar bool SingleThread bool + X11ClassName string + X11InstanceName string } // InitialWindowPosition returns the position for centering the given second width/height pair within the first width/height pair. diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index 624a93705..96ea90d75 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -1083,6 +1083,14 @@ func (u *UserInterface) initOnMainThread(options *RunOptions) error { return err } + if err := glfw.WindowHintString(glfw.X11ClassName, options.X11ClassName); err != nil { + return err + } + + if err := glfw.WindowHintString(glfw.X11InstanceName, options.X11InstanceName); err != nil { + return err + } + // On macOS, window decoration should be initialized once after buffers are swapped (#2600). if runtime.GOOS != "darwin" { decorated := glfw.False diff --git a/run.go b/run.go index a37e37822..813d174fd 100644 --- a/run.go +++ b/run.go @@ -267,6 +267,12 @@ type RunGameOptions struct { // // The default (zero) value is false, which means that the single thread mode is disabled. SingleThread bool + + // X11DisplayName is a class name in the ICCCM WM_CLASS window property. + X11ClassName string + + // X11InstanceName is an instance name in the ICCCM WM_CLASS window property. + X11InstanceName string } // RunGameWithOptions starts the main loop and runs the game with the specified options. @@ -675,18 +681,34 @@ func SetInitFocused(focused bool) { var initUnfocused int32 = 0 func toUIRunOptions(options *RunGameOptions) *ui.RunOptions { + const ( + defaultX11ClassName = "Ebitengine-Application" + defaultX11InstanceName = "ebitengine-application" + ) + if options == nil { return &ui.RunOptions{ InitUnfocused: atomic.LoadInt32(&initUnfocused) != 0, ScreenTransparent: atomic.LoadInt32(&screenTransparent) != 0, + X11ClassName: defaultX11ClassName, + X11InstanceName: defaultX11InstanceName, } } + + if options.X11ClassName == "" { + options.X11ClassName = defaultX11ClassName + } + if options.X11InstanceName == "" { + options.X11InstanceName = defaultX11InstanceName + } return &ui.RunOptions{ GraphicsLibrary: ui.GraphicsLibrary(options.GraphicsLibrary), InitUnfocused: options.InitUnfocused, ScreenTransparent: options.ScreenTransparent, SkipTaskbar: options.SkipTaskbar, SingleThread: options.SingleThread, + X11ClassName: options.X11ClassName, + X11InstanceName: options.X11InstanceName, } }