aboutsummaryrefslogtreecommitdiffhomepage
path: root/system
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-11-15 23:20:03 +0900
committerOphestra <cat@gensokyo.uk>2025-11-15 23:25:46 +0900
commitfe40af7b7e95356b7d88e35941097edc9700f093 (patch)
treed04ddc46f4cf053e51156e1c08cdeaf16dd2a2fa /system
parent12751932d1cbfc911a75445061d87264b927de5f (diff)
internal/wayland: relocate connection struct
This interface is getting replaced, so relocating it to the deprecated wrapper package before working on its replacement. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'system')
-rw-r--r--system/wayland/deprecated.go78
1 files changed, 77 insertions, 1 deletions
diff --git a/system/wayland/deprecated.go b/system/wayland/deprecated.go
index e83c9107..e544597e 100644
--- a/system/wayland/deprecated.go
+++ b/system/wayland/deprecated.go
@@ -4,13 +4,89 @@
package wayland
import (
+ "errors"
+ "net"
+ "os"
+ "runtime"
+ "sync"
+ "syscall"
_ "unsafe" // for go:linkname
"hakurei.app/internal/wayland"
)
// Conn represents a connection to the wayland display server.
-type Conn = wayland.Conn
+//
+// Deprecated: this interface is being replaced.
+// Additionally, the package it belongs to will be removed in 0.4.
+type Conn struct {
+ conn *net.UnixConn
+
+ done chan struct{}
+ doneOnce sync.Once
+
+ mu sync.Mutex
+}
+
+// Attach connects Conn to a wayland socket.
+func (c *Conn) Attach(p string) (err error) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.conn != nil {
+ return errors.New("socket already attached")
+ }
+
+ c.conn, err = net.DialUnix("unix", nil, &net.UnixAddr{Name: p, Net: "unix"})
+ return
+}
+
+// Close releases resources and closes the connection to the wayland compositor.
+func (c *Conn) Close() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.done == nil {
+ return errors.New("no socket bound")
+ }
+
+ c.doneOnce.Do(func() {
+ c.done <- struct{}{}
+ <-c.done
+ })
+
+ // closed by wayland
+ runtime.SetFinalizer(c.conn, nil)
+ return nil
+}
+
+//go:linkname bindRawConn hakurei.app/internal/wayland.bindRawConn
+func bindRawConn(done chan struct{}, rc syscall.RawConn, p, appID, instanceID string) ([2]int, error)
+
+// Bind binds the new socket to pathname.
+func (c *Conn) Bind(pathname, appID, instanceID string) (*os.File, error) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.conn == nil {
+ return nil, errors.New("socket not attached")
+ }
+ if c.done != nil {
+ return nil, errors.New("socket already bound")
+ }
+
+ if rc, err := c.conn.SyscallConn(); err != nil {
+ // unreachable
+ return nil, err
+ } else {
+ c.done = make(chan struct{})
+ if closeFds, err := bindRawConn(c.done, rc, pathname, appID, instanceID); err != nil {
+ return nil, err
+ } else {
+ return os.NewFile(uintptr(closeFds[1]), "close_fd"), nil
+ }
+ }
+}
const (
// WaylandDisplay contains the name of the server socket