1

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.

Marcel
  • 1,509
  • 1
  • 17
  • 39
  • 1
    Sounds like an [XY Problem](http://xyproblem.info) to me. What are you really trying to accomplish? What does *"send a window to the background"* mean to you? Do you want to establish a fixed relationship between two windows? – IInspectable Sep 05 '18 at 12:20
  • I want the behaviour of gtk desktop window type hint. the windows should all stay in the back. It's for a sticky note application and I just don't want to use my desktop as my "blackboard" to stick the notes onto. – Marcel Sep 05 '18 at 12:50
  • This is not a supported scenario. Whichever solution you opt to implement will be a hack one way or another. – IInspectable Sep 05 '18 at 14:35
  • Works with SetTypeHint(gdk.WINDOW_TYPE_HINT_DESKTOP) on linux. Seems quite supported to me. Or do you mean Windows doesn't support it? I can do it with java swing and javafx aswel (on windows). – Marcel Sep 05 '18 at 14:59
  • This question is tagged [tag:windows], so clearly I was referring to that platform. And on that platform, this is not a supported scenario. Whichever solution you pick is going to be a hack, on way or another. [Windows Desktop Gadgets](https://en.wikipedia.org/wiki/Windows_Desktop_Gadgets) was the closest you could get to what you are looking for, but those have been discontinued as of Windows 8. – IInspectable Sep 05 '18 at 15:15
  • I see, missunderstood you, sorry. – Marcel Sep 05 '18 at 15:32
  • If something is "not a supported scenario," does that mean it has legal or other problematic consequences? Are you not allowed to ship an application with it? –  Feb 10 '20 at 15:51
  • It doesn't matter whether a usecase is technically or even specification-wise supported. It won't be a legal problem. However, if you do unsupported things and manage to do so in a hacky way, it might just break in a future update. – Marcel Feb 10 '20 at 15:54

1 Answers1

0

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()
}
Marcel
  • 1,509
  • 1
  • 17
  • 39