Saltar al contenido
Ventana nativa

Una ventana nativa

go-widgets/window: una sola API Open/Run sobre X11, Wayland, GTK4, Cocoa, Win32, Android, wasmbox y una pestaña del navegador, todo con CGO_ENABLED=0.

go-widgets/window abre una ventana real y ejecuta en ella un árbol de widgets: layout, dibujo, presentación, traducción de la entrada a toolkit.Event, y vuelta a empezar hasta que la ventana se cierra.

w, err := window.Open(window.Config{Title: "Demo"})
if err != nil {
	return err
}
defer w.Close()
return w.Run(root) // root is any toolkit.Widget

Config recibe además el tamaño inicial en puntos lógicos (cero pide un tamaño por defecto legible), la instancia y la clase de WM_CLASS, un Theme y un RenderScale.

Cómo elige Open

Plataforma y entornoBackendCómo llega a la pantalla
Linux, $GO_WIDGETS_GTK definidaGTK4GTK posee la ventana; el framebuffer es un GtkPicture, y los controles nativos son widgets GTK reales por encima de él. Necesita el runtime de libgtk-4.
Linux, $WAYLAND_DISPLAY definidaWaylandxdg-shell sobre el socket unix del compositor
Linux, en otro caso $DISPLAYX11el protocolo central de X11 sobre el socket unix, con MIT-SHM
macOSCocoaNSWindow y NSView a través de go-macos/objc (purego)
WindowsWin32un HWND de nivel superior mediante llamadas al sistema de user32 y gdi32, StretchDIBits
Android, $GW_ANDROID_SOCKET definidaHost Androidun protocolo por tramas hacia el host Java, píxeles en un memfd compartido
Android, en otro casoWayland o X11un shell bajo Termux sigue teniendo un servidor gráfico al que conectarse
js/wasm, dentro de wasmdeskwasmboxun cliente del compositor wasmdesk
js/wasm, una página corrientepestaña del navegadorun <canvas> de la página (Config.Canvas, por defecto "screen") a través de webcanvas: sin compositor, sin SharedArrayBuffer, sin aislamiento entre orígenes
cualquier otra cosa—window.ErrUnsupported, para que una compilación cruzada siga compilando

Todos los backends son CGO_ENABLED=0. El de X11 es el protocolo central escrito desde cero sobre el socket —sin Xlib, sin XCB—, con ambos órdenes de bytes, la cookie de Xauthority, el mapeo de keysyms, PutImage troceado por debajo del tamaño máximo de petición del servidor y la vía rápida MIT-SHM, con el segmento compartido pasado por SCM_RIGHTS. A Windows se llega a través de las propias DLL del proceso con syscall.NewLazyDLL y un procedimiento de ventana syscall.NewCallback; a macOS, a través del runtime de Objective-C con purego.

La parte de cada backend que no depende de la plataforma —mapeo de eventos, cálculo de coordenadas, empaquetado de píxeles, rectángulos dañados— vive en un códec cubierto al 100 %, en todos los sistemas operativos. La fina capa de unión con la plataforma se demuestra en vivo: consulte Estado.

Solo lo que ha cambiado

Una raíz que implementa DamageRenderer (como hace toolkit/scene.HostRoot) informa de los rectángulos que ha repintado, y todos los backends salvo GTK4 presentan solo esos: X11 mediante ShmPutImage de MIT-SHM, Wayland mediante el daño de wl_shm, Cocoa, Win32, Android, wasmbox y la pestaña del navegador. El primer fotograma, un cambio de tamaño y un Expose de X11 siguen presentando toda la superficie.

HiDPI

Por defecto hay un píxel de framebuffer por punto lógico: la interfaz se organiza y se pinta a un tamaño legible, y el compositor la sobremuestrea. En Windows, la ventana declara compatibilidad con DPI por monitor y el sistema operativo escala el fotograma lógico al área cliente física. RenderScale pide un framebuffer a la resolución real del panel, lo cual solo es correcto para una raíz que organiza su layout en píxeles del dispositivo.

Pantallas, y mostrar y ocultar

window.Screens() enumera las pantallas conectadas, la principal primero, en puntos lógicos y descontando los paneles del escritorio, y puede llamarse antes de Open. El nombre de una pantalla es el del propio panel ("DELL U2720Q", tomado de su EDID), y recurre al conector ("HDMI-1") cuando el panel no publica ninguno, y también cuando dos paneles conectados publican el mismo, porque un nombre que no permite distinguirlos no es un nombre.

window.Show, Hide y Raise retiran de la pantalla una ventana abierta sin cerrarla y la traen de vuelta: lo que necesita una aplicación de bandeja.

BackendShowHideRaise
X11MapWindowretirada ICCCM, para que salga de la barra de tareasmapear, elevar, _NET_ACTIVE_WINDOW
Waylandvolver a hacer commitbúfer nulo y commitErrNotSupported: xdg-shell no tiene esa petición
macOSorderFront:orderOut:activar la aplicación, makeKeyAndOrderFront:
WindowsSW_SHOWNASW_HIDESW_RESTORE y SetForegroundWindow
GTK, Android, wasmbox, pestaña del navegadorErrNotSupportedErrNotSupportedErrNotSupported

Conceder el foco corresponde a la plataforma: con la prevención del robo de foco, Raise puede limitarse a marcar la ventana como necesitada de atención, y no puede saberlo.

Creada el por tannevaled

Modificada el por tannevaled