Search code examples
windowswinapigtkgtk3window-managers

GTK3 - How to send a window to the background


I am trying to send a window to the background, but SetKeepBelow has no effect on windows. Is there any way to achieve this? I am using golang and gotk3, but I can add additional bindings if needed.

Another option would probably be using this: https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setwindowpos

But I am not sure how exactly, as I can't retrieve the window handle from within gtk.


Solution

  • So, I have found a solution and like mentioned in the comments of the questions, it is hacky! However, I didn't want to leave this unsolved. So what I am doing is using the SetWindowPos function of windows in order to move it on the z axis. However, in order to be able to do so, you first need the pointer to the hWnd, I am retrieving that with FindWindowA which takes a classname and a windowtitle, sicne I don't know the class, I am passing nil. Passing nil causes the function to only search by windowtitle. Ofc this solution only works if your window has a unique title!

    package main
    
    import (
        "unsafe"
    
        "github.com/gotk3/gotk3/gdk"
        "github.com/gotk3/gotk3/gtk"
        "golang.org/x/sys/windows"
    )
    
    var (
        mod                  = windows.NewLazyDLL("user32.dll")
        setWindowPosFunction = mod.NewProc("SetWindowPos")
        findWindowFunction   = mod.NewProc("FindWindowA")
    )
    
    //ToBackground moves the window to the background, preserving its size and position
    func ToBackground(hwnd uintptr, gtkWindow *gtk.Window) error {
        x, y := gtkWindow.GetPosition()
        width, height := gtkWindow.GetSize()
        _, _, err := setWindowPosFunction.Call(hwnd, uintptr(1), uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0)
    
        if err != nil && err.Error() == "The operation completed successfully." {
            return nil
        }
    
        return err
    }
    
    func main() {
        gtk.Init(nil)
    
        window, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
        window.SetTypeHint(gdk.WINDOW_TYPE_HINT_UTILITY)
        title := "unique-identifier"
        window.SetTitle(title)
        window.SetPosition(gtk.WIN_POS_CENTER)
    
        window.ShowAll()
    
        titleAsByteArray := []byte(title)
        hwnd, _, windowRetrieveError := findWindowFunction.Call(0, uintptr(unsafe.Pointer(&titleAsByteArray[0])))
        if windowRetrieveError != nil &&  windowRetrieveError.Error() != "The operation completed successfully." {
            panic(windowRetrieveError)
        }
    
        toBackgroundError := ToBackground(hwnd, window)
        if toBackgroundError != nil {
            panic(toBackgroundError)
        }
    
        gtk.Main()
    }