-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add function to obtain Window handle. #4483
Comments
How do you imagine this working universally for all platforms? For the most part API that are not exposed are done so for good reason. |
maybe with funkcion RunOnNative, it could be posible ... |
There is so much that can go wrong here. Linux and BSD have different window handles for X11 and Wayland, macOS has one, Windows has one, Android has one and so on. |
Partially related to #1155 |
I can see why this is desired and sometimes necessary for certain things outside of Fyne's scope, like there are certain WinAPIs that must be called with an HWND (like integrating with System Media Transport Controls for media player apps (API)). I wonder if there could be a case for a Fyne |
I'm not sure how you would do that as the information is internal to each driver internal package - and per OS too. |
For those need a temporary way to obtain a window handle in desktop environment (linux,windows.macos). Here is a working solution. var w fyne.Window
func main() {
a := app.NewWithID("io.fyne.demo")
w = a.NewWindow("Fyne Demo")
go func() {
time.Sleep(2 * time.Second)
println("Window handle:", xfyne.GetWindowHandle(w))
}()
w.Resize(fyne.NewSize(1080, 720))
w.ShowAndRun()
} also noted that window handle is assigned only after the window has been displayed.
package xfyne
import (
"fyne.io/fyne/v2"
"github.com/go-gl/glfw/v3.3/glfw"
"reflect"
"unsafe"
)
// getGlfwWindow returns the glfw.Window pointer from a fyne.Window.
// very unsafe and ugly hacks. but it works.
func getGlfwWindow(window fyne.Window) *glfw.Window {
rv := reflect.ValueOf(window)
if rv.Type().String() != "*glfw.window" {
return nil
}
rv = rv.Elem()
var glfwWindowPtr uintptr = rv.FieldByName("viewport").Pointer()
// uncomment following code to wait until window is displayed
// for glfwWindowPtr == 0 {
// glfwWindowPtr = rv.FieldByName("viewport").Pointer()
// }
return (*glfw.Window)(unsafe.Pointer(glfwWindowPtr))
}
//go:build darwin
// +build darwin
package xfyne
func GetWindowHandle(window fyne.Window) uintptr {
glfwWindow := getGlfwWindow(window)
if glfwWindow == nil {
return 0
}
return uintptr(glfwWindow.GetCocoaWindow())
}
//go:build linux
// +build linux
package xfyne
import (
"fyne.io/fyne/v2"
)
func GetWindowHandle(window fyne.Window) uintptr {
glfwWindow := getGlfwWindow(window)
if glfwWindow == nil {
return 0
}
return uintptr(glfwWindow.GetX11Window())
}
//go:build windows
// +build windows
package xfyne
import "fyne.io/fyne/v2"
func GetWindowHandle(window fyne.Window) uintptr {
glfwWindow := getGlfwWindow(window)
if glfwWindow == nil {
return 0
}
return uintptr(glfwWindow.GetWin32Window())
} |
On develop for 2.5.0 |
Here is a quick example of how to use the new API: package main
import (
"log"
"runtime"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/driver"
"fyne.io/fyne/v2/widget"
)
func main() {
app := app.New()
win := app.NewWindow("hello")
win.SetContent(widget.NewLabel("Hello world!"))
app.Lifecycle().SetOnEnteredForeground(func() {
// we will not have a window pointer until it is shown,
// so use lifecycle to wait until then
nativeWin, ok := win.(driver.NativeWindow)
if !ok {
panic("this will never happen for a top-level window")
}
nativeWin.RunNative(func(ctx any) {
switch runtime.GOOS {
case "windows":
hwnd := ctx.(driver.WindowsWindowContext).HWND
log.Printf("HWND is %x\n", hwnd)
//callSomeWinAPICGoWrapper(hwnd)
case "darwin":
nsWindow := ctx.(driver.MacWindowContext).NSWindow
log.Printf("NSWindow ptr is %x", nsWindow)
//callSomeCocoaAPICGoWrapper(nsWindow)
case "linux":
if wayland, ok := ctx.(driver.WaylandWindowContext); ok {
wlSurface := wayland.WaylandSurface
log.Printf("Wayland window ptr is %x", wlSurface)
// do something with Wayland surface pointer
} else {
x11Window := ctx.(driver.X11WindowContext).WindowHandle
log.Printf("X11 window ptr is %x", x11Window)
// do something with X11 window pointer
}
}
})
})
win.ShowAndRun()
} |
Checklist
Is your feature request related to a problem?
I need use handle pointer to set Window's other attribute.
Is it possible to construct a solution with the existing API?
No response
Describe the solution you'd like to see.
The text was updated successfully, but these errors were encountered: