From 9d0262517409a5d053d203e30925cfefd034899c Mon Sep 17 00:00:00 2001 From: Dominik Honnef Date: Wed, 23 Sep 2020 22:14:48 +0200 Subject: [PATCH 1/2] Check in go.sum --- go.sum | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 go.sum diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..aa41f46 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8= +golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 8d9c8fbe36a4cb9af2e736ad90a82af33212df8a Mon Sep 17 00:00:00 2001 From: Dominik Honnef Date: Wed, 23 Sep 2020 05:37:02 +0200 Subject: [PATCH 2/2] Convert C pointers to Go pointers Instead of wrapping C pointers in Go structs, wrap C values in Go structs, then convert C pointers to Go pointers. This lets us use actual pointers in the API, simplifying things like nil pointer checks. We use the notinheap hint for some added safety around C pointer rules (i.e. users can't accidentally allocate their own wrappers on the Go heap and pass them to C) and for some added performance (as the compiler can avoid generating barriers and whatnot when accessing these pointers.) Note that this still won't let us set finalizers, as the pointers aren't managed by Go and thus don't get garbage collected. --- cmd/tinywl/server.go | 72 ++-- cmd/tinywl/view.go | 8 +- wlroots/wlroots.go | 841 ++++++++++++++++++++++--------------------- 3 files changed, 462 insertions(+), 459 deletions(-) diff --git a/cmd/tinywl/server.go b/cmd/tinywl/server.go index 89b5921..be4262f 100644 --- a/cmd/tinywl/server.go +++ b/cmd/tinywl/server.go @@ -18,16 +18,16 @@ const ( ) type Server struct { - display wlroots.Display - backend wlroots.Backend - renderer wlroots.Renderer - layout wlroots.OutputLayout - cursor wlroots.Cursor - cursorMgr wlroots.XCursorManager - compositor wlroots.Compositor - dataDevMgr wlroots.DataDeviceManager - seat wlroots.Seat - xdgShell wlroots.XDGShell + display *wlroots.Display + backend *wlroots.Backend + renderer *wlroots.Renderer + layout *wlroots.OutputLayout + cursor *wlroots.Cursor + cursorMgr *wlroots.XCursorManager + compositor *wlroots.Compositor + dataDevMgr *wlroots.DataDeviceManager + seat *wlroots.Seat + xdgShell *wlroots.XDGShell views []*View keyboards []*Keyboard @@ -42,7 +42,7 @@ type Server struct { } type Keyboard struct { - dev wlroots.InputDevice + dev *wlroots.InputDevice } func NewServer() (*Server, error) { @@ -116,22 +116,22 @@ func (s *Server) Run() error { return nil } -func (s *Server) viewAt(lx float64, ly float64) (*View, wlroots.Surface, float64, float64) { +func (s *Server) viewAt(lx float64, ly float64) (*View, *wlroots.Surface, float64, float64) { for i := len(s.views) - 1; i >= 0; i-- { view := s.views[i] surface, sx, sy := view.XDGSurface().SurfaceAt(lx-view.X, ly-view.Y) - if !surface.Nil() { + if surface != nil { return view, surface, sx, sy } } - return nil, wlroots.Surface{}, 0, 0 + return nil, nil, 0, 0 } -func (s *Server) renderView(output wlroots.Output, view *View) { - view.XDGSurface().Walk(func(surface wlroots.Surface, sx int, sy int) { +func (s *Server) renderView(output *wlroots.Output, view *View) { + view.XDGSurface().Walk(func(surface *wlroots.Surface, sx int, sy int) { texture := surface.Texture() - if texture.Nil() { + if texture == nil { return } @@ -160,14 +160,14 @@ func (s *Server) renderView(output wlroots.Output, view *View) { }) } -func (s *Server) focusView(view *View, surface wlroots.Surface) { +func (s *Server) focusView(view *View, surface *wlroots.Surface) { prevSurface := s.seat.KeyboardState().FocusedSurface() if prevSurface == surface { // don't re-focus an already focused surface return } - if !prevSurface.Nil() { + if prevSurface != nil { // deactivate the previously focused surface prev := prevSurface.XDGSurface() prev.TopLevelSetActivated(false) @@ -186,7 +186,7 @@ func (s *Server) focusView(view *View, surface wlroots.Surface) { s.seat.NotifyKeyboardEnter(view.Surface(), s.seat.Keyboard()) } -func (s *Server) handleNewFrame(output wlroots.Output) { +func (s *Server) handleNewFrame(output *wlroots.Output) { output.AttachRender() width, height := output.EffectiveResolution() @@ -207,7 +207,7 @@ func (s *Server) handleNewFrame(output wlroots.Output) { output.Commit() } -func (s *Server) handleNewOutput(output wlroots.Output) { +func (s *Server) handleNewOutput(output *wlroots.Output) { // TODO: pick the preferred mode instead of the first one modes := output.Modes() if len(modes) > 0 { @@ -220,12 +220,12 @@ func (s *Server) handleNewOutput(output wlroots.Output) { output.SetTitle(fmt.Sprintf("tinywl (wlroots) - %s", output.Name())) } -func (s *Server) handleCursorMotion(dev wlroots.InputDevice, time uint32, dx float64, dy float64) { +func (s *Server) handleCursorMotion(dev *wlroots.InputDevice, time uint32, dx float64, dy float64) { s.cursor.Move(dev, dx, dy) s.processCursorMotion(time) } -func (s *Server) handleCursorMotionAbsolute(dev wlroots.InputDevice, time uint32, x float64, y float64) { +func (s *Server) handleCursorMotionAbsolute(dev *wlroots.InputDevice, time uint32, x float64, y float64) { s.cursor.WarpAbsolute(dev, x, y) s.processCursorMotion(time) } @@ -247,7 +247,7 @@ func (s *Server) processCursorMotion(time uint32) { s.cursorMgr.SetCursorImage(s.cursor, "left_ptr") } - if !surface.Nil() { + if surface != nil { s.seat.NotifyPointerEnter(surface, sx, sy) if s.seat.PointerState().FocusedSurface() == surface { // we only need to notify on motion if the focus didn't change @@ -296,14 +296,14 @@ func (s *Server) processCursorResize(time uint32) { s.grabbedView.XDGSurface().TopLevelSetSize(uint32(width), uint32(height)) } -func (s *Server) handleSetCursorRequest(client wlroots.SeatClient, surface wlroots.Surface, serial uint32, hotspotX int32, hotspotY int32) { +func (s *Server) handleSetCursorRequest(client *wlroots.SeatClient, surface *wlroots.Surface, serial uint32, hotspotX int32, hotspotY int32) { focusedClient := s.seat.PointerState().FocusedClient() if focusedClient == client { s.cursor.SetSurface(surface, hotspotX, hotspotY) } } -func (s *Server) handleNewInput(dev wlroots.InputDevice) { +func (s *Server) handleNewInput(dev *wlroots.InputDevice) { switch dev.Type() { case wlroots.InputDeviceTypePointer: s.cursor.AttachInputDevice(dev) @@ -316,7 +316,7 @@ func (s *Server) handleNewInput(dev wlroots.InputDevice) { context.Destroy() keyboard.SetRepeatInfo(25, 600) - keyboard.OnKey(func(keyboard wlroots.Keyboard, time uint32, keyCode uint32, updateState bool, state wlroots.KeyState) { + keyboard.OnKey(func(keyboard *wlroots.Keyboard, time uint32, keyCode uint32, updateState bool, state wlroots.KeyState) { // translate libinput keycode to xkbcommon and obtain keysyms syms := keyboard.XKBState().Syms(xkb.KeyCode(keyCode + 8)) @@ -334,7 +334,7 @@ func (s *Server) handleNewInput(dev wlroots.InputDevice) { } }) - keyboard.OnModifiers(func(keyboard wlroots.Keyboard) { + keyboard.OnModifiers(func(keyboard *wlroots.Keyboard) { s.seat.SetKeyboard(dev) s.seat.NotifyKeyboardModifiers(keyboard) }) @@ -350,20 +350,20 @@ func (s *Server) handleNewInput(dev wlroots.InputDevice) { s.seat.SetCapabilities(caps) } -func (s *Server) handleNewXDGSurface(surface wlroots.XDGSurface) { +func (s *Server) handleNewXDGSurface(surface *wlroots.XDGSurface) { if surface.Role() != wlroots.XDGSurfaceRoleTopLevel { return } view := NewView(surface) - surface.OnMap(func(surface wlroots.XDGSurface) { + surface.OnMap(func(surface *wlroots.XDGSurface) { view.Mapped = true s.focusView(view, surface.Surface()) }) - surface.OnUnmap(func(surface wlroots.XDGSurface) { + surface.OnUnmap(func(surface *wlroots.XDGSurface) { view.Mapped = false }) - surface.OnDestroy(func(surface wlroots.XDGSurface) { + surface.OnDestroy(func(surface *wlroots.XDGSurface) { // TODO: keep track of views some other way for i := range s.views { if s.views[i] == view { @@ -374,17 +374,17 @@ func (s *Server) handleNewXDGSurface(surface wlroots.XDGSurface) { }) toplevel := surface.TopLevel() - toplevel.OnRequestMove(func(client wlroots.SeatClient, serial uint32) { + toplevel.OnRequestMove(func(client *wlroots.SeatClient, serial uint32) { s.beginInteractive(view, CursorModeMove, 0) }) - toplevel.OnRequestResize(func(client wlroots.SeatClient, serial uint32, edges wlroots.Edges) { + toplevel.OnRequestResize(func(client *wlroots.SeatClient, serial uint32, edges wlroots.Edges) { s.beginInteractive(view, CursorModeResize, edges) }) s.views = append(s.views, view) } -func (s *Server) handleCursorButton(dev wlroots.InputDevice, time uint32, button uint32, state wlroots.ButtonState) { +func (s *Server) handleCursorButton(dev *wlroots.InputDevice, time uint32, button uint32, state wlroots.ButtonState) { s.seat.NotifyPointerButton(time, button, state) if state == wlroots.ButtonStateReleased { @@ -397,7 +397,7 @@ func (s *Server) handleCursorButton(dev wlroots.InputDevice, time uint32, button } } -func (s *Server) handleCursorAxis(dev wlroots.InputDevice, time uint32, source wlroots.AxisSource, orientation wlroots.AxisOrientation, delta float64, deltaDiscrete int32) { +func (s *Server) handleCursorAxis(dev *wlroots.InputDevice, time uint32, source wlroots.AxisSource, orientation wlroots.AxisOrientation, delta float64, deltaDiscrete int32) { s.seat.NotifyPointerAxis(time, orientation, delta, deltaDiscrete, source) } diff --git a/cmd/tinywl/view.go b/cmd/tinywl/view.go index 8b5de20..21033b2 100644 --- a/cmd/tinywl/view.go +++ b/cmd/tinywl/view.go @@ -3,20 +3,20 @@ package main import "github.com/swaywm/go-wlroots/wlroots" type View struct { - surface wlroots.XDGSurface + surface *wlroots.XDGSurface Mapped bool X float64 Y float64 } -func NewView(surface wlroots.XDGSurface) *View { +func NewView(surface *wlroots.XDGSurface) *View { return &View{surface: surface} } -func (v *View) Surface() wlroots.Surface { +func (v *View) Surface() *wlroots.Surface { return v.surface.Surface() } -func (v *View) XDGSurface() wlroots.XDGSurface { +func (v *View) XDGSurface() *wlroots.XDGSurface { return v.surface } diff --git a/wlroots/wlroots.go b/wlroots/wlroots.go index dad2f3a..b2542ee 100644 --- a/wlroots/wlroots.go +++ b/wlroots/wlroots.go @@ -73,27 +73,29 @@ import ( "golang.org/x/sys/unix" ) +//go:notinheap type XWayland struct { - p *C.struct_wlr_xwayland + p C.struct_wlr_xwayland } +//go:notinheap type XWaylandSurface struct { - p *C.struct_wlr_xwayland_surface + p C.struct_wlr_xwayland_surface } -func NewXWayland(display Display, compositor Compositor, lazy bool) XWayland { - p := C.wlr_xwayland_create(display.p, compositor.p, C.bool(lazy)) - return XWayland{p: p} +func NewXWayland(display *Display, compositor *Compositor, lazy bool) *XWayland { + p := C.wlr_xwayland_create(&display.p, &compositor.p, C.bool(lazy)) + return (*XWayland)(unsafe.Pointer(p)) } -func (x XWayland) Destroy() { - C.wlr_xwayland_destroy(x.p) +func (x *XWayland) Destroy() { + C.wlr_xwayland_destroy(&x.p) } -func (x XWayland) OnNewSurface(cb func(XWaylandSurface)) { - man.add(unsafe.Pointer(x.p), &x.p.events.new_surface, func(data unsafe.Pointer) { - surface := XWaylandSurface{p: (*C.struct_wlr_xwayland_surface)(data)} - man.track(unsafe.Pointer(surface.p), &surface.p.events.destroy) +func (x *XWayland) OnNewSurface(cb func(*XWaylandSurface)) { + man.add(unsafe.Pointer(x), &x.p.events.new_surface, func(data unsafe.Pointer) { + surface := (*XWaylandSurface)(data) + man.track(data, &surface.p.events.destroy) man.add(unsafe.Pointer(surface.p.surface), &surface.p.surface.events.destroy, func(data unsafe.Pointer) { man.delete(unsafe.Pointer(surface.p.surface)) }) @@ -101,15 +103,15 @@ func (x XWayland) OnNewSurface(cb func(XWaylandSurface)) { }) } -func (x XWayland) SetCursor(img XCursorImage) { - C.wlr_xwayland_set_cursor(x.p, img.p.buffer, img.p.width*4, img.p.width, img.p.height, C.int32_t(img.p.hotspot_x), C.int32_t(img.p.hotspot_y)) +func (x *XWayland) SetCursor(img *XCursorImage) { + C.wlr_xwayland_set_cursor(&x.p, img.p.buffer, img.p.width*4, img.p.width, img.p.height, C.int32_t(img.p.hotspot_x), C.int32_t(img.p.hotspot_y)) } -func (s XWaylandSurface) Surface() Surface { - return Surface{p: s.p.surface} +func (s *XWaylandSurface) Surface() *Surface { + return (*Surface)(unsafe.Pointer(s.p.surface)) } -func (s XWaylandSurface) Geometry() Box { +func (s *XWaylandSurface) Geometry() Box { return Box{ X: int(s.p.x), Y: int(s.p.y), @@ -118,43 +120,43 @@ func (s XWaylandSurface) Geometry() Box { } } -func (s XWaylandSurface) Configure(x int16, y int16, width uint16, height uint16) { - C.wlr_xwayland_surface_configure(s.p, C.int16_t(x), C.int16_t(y), C.uint16_t(width), C.uint16_t(height)) +func (s *XWaylandSurface) Configure(x int16, y int16, width uint16, height uint16) { + C.wlr_xwayland_surface_configure(&s.p, C.int16_t(x), C.int16_t(y), C.uint16_t(width), C.uint16_t(height)) } -func (s XWaylandSurface) OnMap(cb func(XWaylandSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events._map, func(data unsafe.Pointer) { +func (s *XWaylandSurface) OnMap(cb func(*XWaylandSurface)) { + man.add(unsafe.Pointer(s), &s.p.events._map, func(data unsafe.Pointer) { cb(s) }) } -func (s XWaylandSurface) OnUnmap(cb func(XWaylandSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.unmap, func(data unsafe.Pointer) { +func (s *XWaylandSurface) OnUnmap(cb func(*XWaylandSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.unmap, func(data unsafe.Pointer) { cb(s) }) } -func (s XWaylandSurface) OnDestroy(cb func(XWaylandSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.destroy, func(data unsafe.Pointer) { +func (s *XWaylandSurface) OnDestroy(cb func(*XWaylandSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.destroy, func(data unsafe.Pointer) { cb(s) }) } -func (s XWaylandSurface) OnRequestMove(cb func(surface XWaylandSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.request_move, func(data unsafe.Pointer) { +func (s *XWaylandSurface) OnRequestMove(cb func(surface *XWaylandSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.request_move, func(data unsafe.Pointer) { cb(s) }) } -func (s XWaylandSurface) OnRequestResize(cb func(surface XWaylandSurface, edges Edges)) { - man.add(unsafe.Pointer(s.p), &s.p.events.request_resize, func(data unsafe.Pointer) { +func (s *XWaylandSurface) OnRequestResize(cb func(surface *XWaylandSurface, edges Edges)) { + man.add(unsafe.Pointer(s), &s.p.events.request_resize, func(data unsafe.Pointer) { event := (*C.struct_wlr_xwayland_resize_event)(data) cb(s, Edges(event.edges)) }) } -func (s XWaylandSurface) OnRequestConfigure(cb func(surface XWaylandSurface, x int16, y int16, width uint16, height uint16)) { - man.add(unsafe.Pointer(s.p), &s.p.events.request_configure, func(data unsafe.Pointer) { +func (s *XWaylandSurface) OnRequestConfigure(cb func(surface *XWaylandSurface, x int16, y int16, width uint16, height uint16)) { + man.add(unsafe.Pointer(s), &s.p.events.request_configure, func(data unsafe.Pointer) { event := (*C.struct_wlr_xwayland_surface_configure_event)(data) cb(s, int16(event.x), int16(event.y), uint16(event.width), uint16(event.height)) }) @@ -170,46 +172,50 @@ const ( var ( // TODO: guard this with a mutex - xdgSurfaceWalkers = map[*C.struct_wlr_xdg_surface]XDGSurfaceWalkFunc{} + xdgSurfaceWalkers = map[*XDGSurface]XDGSurfaceWalkFunc{} xdgSurfaceWalkersMutex sync.RWMutex ) +//go:notinheap type XDGShell struct { - p *C.struct_wlr_xdg_shell + p C.struct_wlr_xdg_shell } +//go:notinheap type XDGSurface struct { - p *C.struct_wlr_xdg_surface + p C.struct_wlr_xdg_surface } +//go:notinheap type XDGPopup struct { - p *C.struct_wlr_xdg_popup + p C.struct_wlr_xdg_popup } -type XDGSurfaceWalkFunc func(surface Surface, sx int, sy int) +type XDGSurfaceWalkFunc func(surface *Surface, sx int, sy int) +//go:notinheap type XDGTopLevel struct { - p *C.struct_wlr_xdg_toplevel + p C.struct_wlr_xdg_toplevel } -func NewXDGShell(display Display) XDGShell { - p := C.wlr_xdg_shell_create(display.p) +func NewXDGShell(display *Display) *XDGShell { + p := C.wlr_xdg_shell_create(&display.p) man.track(unsafe.Pointer(p), &p.events.destroy) - return XDGShell{p: p} + return (*XDGShell)(unsafe.Pointer(p)) } -func (s XDGShell) OnDestroy(cb func(XDGShell)) { - man.add(unsafe.Pointer(s.p), &s.p.events.destroy, func(unsafe.Pointer) { +func (s *XDGShell) OnDestroy(cb func(*XDGShell)) { + man.add(unsafe.Pointer(s), &s.p.events.destroy, func(unsafe.Pointer) { cb(s) }) } -func (s XDGShell) OnNewSurface(cb func(XDGSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.new_surface, func(data unsafe.Pointer) { - surface := XDGSurface{p: (*C.struct_wlr_xdg_surface)(data)} - man.add(unsafe.Pointer(surface.p), &surface.p.events.destroy, func(data unsafe.Pointer) { - man.delete(unsafe.Pointer(surface.p)) - man.delete(unsafe.Pointer(surface.TopLevel().p)) +func (s *XDGShell) OnNewSurface(cb func(*XDGSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.new_surface, func(data unsafe.Pointer) { + surface := (*XDGSurface)(data) + man.add(data, &surface.p.events.destroy, func(data unsafe.Pointer) { + man.delete(unsafe.Pointer(surface)) + man.delete(unsafe.Pointer(surface.TopLevel())) }) man.add(unsafe.Pointer(surface.p.surface), &surface.p.surface.events.destroy, func(data unsafe.Pointer) { man.delete(unsafe.Pointer(surface.p.surface)) @@ -221,189 +227,184 @@ func (s XDGShell) OnNewSurface(cb func(XDGSurface)) { //export _wlr_xdg_surface_for_each_cb func _wlr_xdg_surface_for_each_cb(surface *C.struct_wlr_surface, sx C.int, sy C.int, data unsafe.Pointer) { xdgSurfaceWalkersMutex.RLock() - cb := xdgSurfaceWalkers[(*C.struct_wlr_xdg_surface)(data)] + cb := xdgSurfaceWalkers[(*XDGSurface)(data)] xdgSurfaceWalkersMutex.RUnlock() if cb != nil { - cb(Surface{p: surface}, int(sx), int(sy)) + cb((*Surface)(unsafe.Pointer(surface)), int(sx), int(sy)) } } -func (s XDGSurface) Nil() bool { - return s.p == nil -} - -func (s XDGSurface) Walk(visit XDGSurfaceWalkFunc) { +func (s *XDGSurface) Walk(visit XDGSurfaceWalkFunc) { xdgSurfaceWalkersMutex.Lock() - xdgSurfaceWalkers[s.p] = visit + xdgSurfaceWalkers[s] = visit xdgSurfaceWalkersMutex.Unlock() - C._wlr_xdg_surface_for_each_surface(s.p, unsafe.Pointer(s.p)) + C._wlr_xdg_surface_for_each_surface(&s.p, unsafe.Pointer(s)) xdgSurfaceWalkersMutex.Lock() - delete(xdgSurfaceWalkers, s.p) + delete(xdgSurfaceWalkers, s) xdgSurfaceWalkersMutex.Unlock() } -func (s XDGSurface) Role() XDGSurfaceRole { +func (s *XDGSurface) Role() XDGSurfaceRole { return XDGSurfaceRole(s.p.role) } -func (s XDGSurface) TopLevel() XDGTopLevel { +func (s *XDGSurface) TopLevel() *XDGTopLevel { p := *(*unsafe.Pointer)(unsafe.Pointer(&s.p.anon0[0])) - return XDGTopLevel{p: (*C.struct_wlr_xdg_toplevel)(p)} + return (*XDGTopLevel)(p) } -func (s XDGSurface) TopLevelSetActivated(activated bool) { - C.wlr_xdg_toplevel_set_activated(s.p, C.bool(activated)) +func (s *XDGSurface) TopLevelSetActivated(activated bool) { + C.wlr_xdg_toplevel_set_activated(&s.p, C.bool(activated)) } -func (s XDGSurface) TopLevelSetSize(width uint32, height uint32) { - C.wlr_xdg_toplevel_set_size(s.p, C.uint32_t(width), C.uint32_t(height)) +func (s *XDGSurface) TopLevelSetSize(width uint32, height uint32) { + C.wlr_xdg_toplevel_set_size(&s.p, C.uint32_t(width), C.uint32_t(height)) } -func (s XDGSurface) TopLevelSetTiled(edges Edges) { - C.wlr_xdg_toplevel_set_tiled(s.p, C.uint32_t(edges)) +func (s *XDGSurface) TopLevelSetTiled(edges Edges) { + C.wlr_xdg_toplevel_set_tiled(&s.p, C.uint32_t(edges)) } -func (s XDGSurface) SendClose() { - C.wlr_xdg_toplevel_send_close(s.p) +func (s *XDGSurface) SendClose() { + C.wlr_xdg_toplevel_send_close(&s.p) } -func (s XDGSurface) Ping() { - C.wlr_xdg_surface_ping(s.p) +func (s *XDGSurface) Ping() { + C.wlr_xdg_surface_ping(&s.p) } -func (s XDGSurface) Surface() Surface { - return Surface{p: s.p.surface} +func (s *XDGSurface) Surface() *Surface { + return (*Surface)(unsafe.Pointer(s.p.surface)) } -func (s XDGSurface) SurfaceAt(sx float64, sy float64) (surface Surface, subX float64, subY float64) { +func (s *XDGSurface) SurfaceAt(sx float64, sy float64) (surface *Surface, subX float64, subY float64) { var csubX, csubY C.double - p := C.wlr_xdg_surface_surface_at(s.p, C.double(sx), C.double(sy), &csubX, &csubY) - return Surface{p: p}, float64(csubX), float64(csubY) + p := C.wlr_xdg_surface_surface_at(&s.p, C.double(sx), C.double(sy), &csubX, &csubY) + return (*Surface)(unsafe.Pointer(p)), float64(csubX), float64(csubY) } -func (s XDGSurface) OnMap(cb func(XDGSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events._map, func(data unsafe.Pointer) { +func (s *XDGSurface) OnMap(cb func(*XDGSurface)) { + man.add(unsafe.Pointer(s), &s.p.events._map, func(data unsafe.Pointer) { cb(s) }) } -func (s XDGSurface) OnUnmap(cb func(XDGSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.unmap, func(data unsafe.Pointer) { +func (s *XDGSurface) OnUnmap(cb func(*XDGSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.unmap, func(data unsafe.Pointer) { cb(s) }) } -func (s XDGSurface) OnDestroy(cb func(XDGSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.destroy, func(data unsafe.Pointer) { +func (s *XDGSurface) OnDestroy(cb func(*XDGSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.destroy, func(data unsafe.Pointer) { cb(s) }) } -func (s XDGSurface) OnPingTimeout(cb func(XDGSurface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.ping_timeout, func(data unsafe.Pointer) { +func (s *XDGSurface) OnPingTimeout(cb func(*XDGSurface)) { + man.add(unsafe.Pointer(s), &s.p.events.ping_timeout, func(data unsafe.Pointer) { cb(s) }) } -func (s XDGSurface) OnNewPopup(cb func(XDGSurface, XDGPopup)) { - man.add(unsafe.Pointer(s.p), &s.p.events.ping_timeout, func(data unsafe.Pointer) { - popup := XDGPopup{p: (*C.struct_wlr_xdg_popup)(data)} +func (s *XDGSurface) OnNewPopup(cb func(*XDGSurface, *XDGPopup)) { + man.add(unsafe.Pointer(s), &s.p.events.ping_timeout, func(data unsafe.Pointer) { + popup := (*XDGPopup)(data) cb(s, popup) }) } -func (s XDGSurface) Geometry() Box { +func (s *XDGSurface) Geometry() Box { var cb C.struct_wlr_box - C.wlr_xdg_surface_get_geometry(s.p, &cb) + C.wlr_xdg_surface_get_geometry(&s.p, &cb) var b Box b.fromC(&cb) return b } -func (t XDGTopLevel) OnRequestMove(cb func(client SeatClient, serial uint32)) { - man.add(unsafe.Pointer(t.p), &t.p.events.request_move, func(data unsafe.Pointer) { +func (t *XDGTopLevel) OnRequestMove(cb func(client *SeatClient, serial uint32)) { + man.add(unsafe.Pointer(t), &t.p.events.request_move, func(data unsafe.Pointer) { event := (*C.struct_wlr_xdg_toplevel_move_event)(data) - client := SeatClient{p: event.seat} + client := (*SeatClient)(unsafe.Pointer(event.seat)) cb(client, uint32(event.serial)) }) } -func (t XDGTopLevel) OnRequestResize(cb func(client SeatClient, serial uint32, edges Edges)) { - man.add(unsafe.Pointer(t.p), &t.p.events.request_resize, func(data unsafe.Pointer) { +func (t *XDGTopLevel) OnRequestResize(cb func(client *SeatClient, serial uint32, edges Edges)) { + man.add(unsafe.Pointer(t), &t.p.events.request_resize, func(data unsafe.Pointer) { event := (*C.struct_wlr_xdg_toplevel_resize_event)(data) - client := SeatClient{p: event.seat} + client := (*SeatClient)(unsafe.Pointer(event.seat)) cb(client, uint32(event.serial), Edges(event.edges)) }) } -func (s XDGTopLevel) Nil() bool { - return s.p == nil -} - -func (t XDGTopLevel) Title() string { +func (t *XDGTopLevel) Title() string { return C.GoString(t.p.title) } +//go:notinheap type XCursor struct { - p *C.struct_wlr_xcursor + p C.struct_wlr_xcursor } +//go:notinheap type XCursorImage struct { - p *C.struct_wlr_xcursor_image + p C.struct_wlr_xcursor_image } +//go:notinheap type XCursorManager struct { - p *C.struct_wlr_xcursor_manager + p C.struct_wlr_xcursor_manager } -func NewXCursorManager() XCursorManager { +func NewXCursorManager() *XCursorManager { p := C.wlr_xcursor_manager_create(nil, 24) - return XCursorManager{p: p} + return (*XCursorManager)(unsafe.Pointer(p)) } -func (m XCursorManager) Destroy() { - C.wlr_xcursor_manager_destroy(m.p) +func (m *XCursorManager) Destroy() { + C.wlr_xcursor_manager_destroy(&m.p) } -func (m XCursorManager) Load() { - C.wlr_xcursor_manager_load(m.p, 1) +func (m *XCursorManager) Load() { + C.wlr_xcursor_manager_load(&m.p, 1) } -func (m XCursorManager) SetCursorImage(cursor Cursor, name string) { +func (m *XCursorManager) SetCursorImage(cursor *Cursor, name string) { s := C.CString(name) - C.wlr_xcursor_manager_set_cursor_image(m.p, s, cursor.p) + C.wlr_xcursor_manager_set_cursor_image(&m.p, s, &cursor.p) C.free(unsafe.Pointer(s)) } -func (m XCursorManager) XCursor(name string, scale float32) XCursor { +func (m *XCursorManager) XCursor(name string, scale float32) *XCursor { s := C.CString(name) - p := C.wlr_xcursor_manager_get_xcursor(m.p, s, C.float(scale)) + p := C.wlr_xcursor_manager_get_xcursor(&m.p, s, C.float(scale)) C.free(unsafe.Pointer(s)) - return XCursor{p: p} + return (*XCursor)(unsafe.Pointer(p)) } -func (c XCursor) Image(i int) XCursorImage { +func (c *XCursor) Image(i int) *XCursorImage { n := c.ImageCount() slice := (*[1 << 30]*C.struct_wlr_xcursor_image)(unsafe.Pointer(c.p.images))[:n:n] - return XCursorImage{p: slice[i]} + return (*XCursorImage)(unsafe.Pointer(slice[i])) } -func (c XCursor) Images() []XCursorImage { - images := make([]XCursorImage, 0, c.ImageCount()) +func (c *XCursor) Images() []*XCursorImage { + images := make([]*XCursorImage, 0, c.ImageCount()) for i := 0; i < cap(images); i++ { images = append(images, c.Image(i)) } return images } -func (c XCursor) ImageCount() int { +func (c *XCursor) ImageCount() int { return int(c.p.image_count) } -func (c XCursor) Name() string { +func (c *XCursor) Name() string { return C.GoString(c.p.name) } @@ -417,16 +418,13 @@ const ( EdgeRight Edges = C.WLR_EDGE_RIGHT ) +//go:notinheap type Texture struct { - p *C.struct_wlr_texture + p C.struct_wlr_texture } -func (t Texture) Destroy() { - C.wlr_texture_destroy(t.p) -} - -func (t Texture) Nil() bool { - return t.p == nil +func (t *Texture) Destroy() { + C.wlr_texture_destroy(&t.p) } type SurfaceType uint32 @@ -437,69 +435,66 @@ const ( SurfaceTypeXWayland ) +//go:notinheap type Surface struct { - p *C.struct_wlr_surface + p C.struct_wlr_surface } type SurfaceState struct { s C.struct_wlr_surface_state } -func (s Surface) Nil() bool { - return s.p == nil -} - -func (s Surface) OnDestroy(cb func(Surface)) { - man.add(unsafe.Pointer(s.p), &s.p.events.destroy, func(unsafe.Pointer) { +func (s *Surface) OnDestroy(cb func(*Surface)) { + man.add(unsafe.Pointer(s), &s.p.events.destroy, func(unsafe.Pointer) { cb(s) }) } -func (s Surface) Type() SurfaceType { - if C.wlr_surface_is_xdg_surface(s.p) { +func (s *Surface) Type() SurfaceType { + if C.wlr_surface_is_xdg_surface(&s.p) { return SurfaceTypeXDG - } else if C.wlr_surface_is_xwayland_surface(s.p) { + } else if C.wlr_surface_is_xwayland_surface(&s.p) { return SurfaceTypeXWayland } return SurfaceTypeNone } -func (s Surface) SurfaceAt(sx float64, sy float64) (surface Surface, subX float64, subY float64) { +func (s *Surface) SurfaceAt(sx float64, sy float64) (surface *Surface, subX float64, subY float64) { var csubX, csubY C.double - p := C.wlr_surface_surface_at(s.p, C.double(sx), C.double(sy), &csubX, &csubY) - return Surface{p: p}, float64(csubX), float64(csubY) + p := C.wlr_surface_surface_at(&s.p, C.double(sx), C.double(sy), &csubX, &csubY) + return (*Surface)(unsafe.Pointer(p)), float64(csubX), float64(csubY) } -func (s Surface) Texture() Texture { - p := C.wlr_surface_get_texture(s.p) - return Texture{p: p} +func (s *Surface) Texture() *Texture { + p := C.wlr_surface_get_texture(&s.p) + return (*Texture)(unsafe.Pointer(p)) } -func (s Surface) CurrentState() SurfaceState { +func (s *Surface) CurrentState() SurfaceState { return SurfaceState{s: s.p.current} } -func (s Surface) Walk(visit func()) { +func (s *Surface) Walk(visit func()) { panic("not implemented") } -func (s Surface) SendFrameDone(when time.Time) { +func (s *Surface) SendFrameDone(when time.Time) { // we ignore the returned error; the only possible error is // ERANGE, when timespec on a platform has int32 precision, but // our time requires 64 bits. This should not occur. t, _ := unix.TimeToTimespec(when) - C.wlr_surface_send_frame_done(s.p, (*C.struct_timespec)(unsafe.Pointer(&t))) + C.wlr_surface_send_frame_done(&s.p, (*C.struct_timespec)(unsafe.Pointer(&t))) } -func (s Surface) XDGSurface() XDGSurface { - p := C.wlr_xdg_surface_from_wlr_surface(s.p) - return XDGSurface{p: p} +func (s *Surface) XDGSurface() *XDGSurface { + p := C.wlr_xdg_surface_from_wlr_surface(&s.p) + return (*XDGSurface)(unsafe.Pointer(p)) } -func (s Surface) XWaylandSurface() XWaylandSurface { - p := C.wlr_xwayland_surface_from_wlr_surface(s.p) - return XWaylandSurface{p: p} +func (s *Surface) XWaylandSurface() *XWaylandSurface { + p := C.wlr_xwayland_surface_from_wlr_surface(&s.p) + return (*XWaylandSurface)(unsafe.Pointer(p)) } func (s SurfaceState) Width() int { @@ -514,12 +509,14 @@ func (s SurfaceState) Transform() uint32 { return uint32(s.s.transform) } +//go:notinheap type Seat struct { - p *C.struct_wlr_seat + p C.struct_wlr_seat } +//go:notinheap type SeatClient struct { - p *C.struct_wlr_seat_client + p C.struct_wlr_seat_client } type SeatKeyboardState struct { @@ -538,249 +535,249 @@ const ( SeatCapabilityTouch SeatCapability = C.WL_SEAT_CAPABILITY_TOUCH ) -func NewSeat(display Display, name string) Seat { +func NewSeat(display *Display, name string) *Seat { s := C.CString(name) - p := C.wlr_seat_create(display.p, s) + p := C.wlr_seat_create(&display.p, s) C.free(unsafe.Pointer(s)) man.track(unsafe.Pointer(p), &p.events.destroy) - return Seat{p: p} + return (*Seat)(unsafe.Pointer(p)) } -func (s Seat) Destroy() { - C.wlr_seat_destroy(s.p) +func (s *Seat) Destroy() { + C.wlr_seat_destroy(&s.p) } -func (s Seat) OnDestroy(cb func(Seat)) { - man.add(unsafe.Pointer(s.p), &s.p.events.destroy, func(unsafe.Pointer) { +func (s *Seat) OnDestroy(cb func(*Seat)) { + man.add(unsafe.Pointer(s), &s.p.events.destroy, func(unsafe.Pointer) { cb(s) }) } -func (s Seat) OnSetCursorRequest(cb func(client SeatClient, surface Surface, serial uint32, hotspotX int32, hotspotY int32)) { - man.add(unsafe.Pointer(s.p), &s.p.events.request_set_cursor, func(data unsafe.Pointer) { +func (s *Seat) OnSetCursorRequest(cb func(client *SeatClient, surface *Surface, serial uint32, hotspotX int32, hotspotY int32)) { + man.add(unsafe.Pointer(s), &s.p.events.request_set_cursor, func(data unsafe.Pointer) { event := (*C.struct_wlr_seat_pointer_request_set_cursor_event)(data) - client := SeatClient{p: event.seat_client} - surface := Surface{p: event.surface} + client := (*SeatClient)(unsafe.Pointer(event.seat_client)) + surface := (*Surface)(unsafe.Pointer(event.surface)) cb(client, surface, uint32(event.serial), int32(event.hotspot_x), int32(event.hotspot_y)) }) } -func (s Seat) SetCapabilities(caps SeatCapability) { - C.wlr_seat_set_capabilities(s.p, C.uint32_t(caps)) +func (s *Seat) SetCapabilities(caps SeatCapability) { + C.wlr_seat_set_capabilities(&s.p, C.uint32_t(caps)) } -func (s Seat) SetKeyboard(dev InputDevice) { - C.wlr_seat_set_keyboard(s.p, dev.p) +func (s *Seat) SetKeyboard(dev *InputDevice) { + C.wlr_seat_set_keyboard(&s.p, &dev.p) } -func (s Seat) NotifyPointerButton(time uint32, button uint32, state ButtonState) { - C.wlr_seat_pointer_notify_button(s.p, C.uint32_t(time), C.uint32_t(button), uint32(state)) +func (s *Seat) NotifyPointerButton(time uint32, button uint32, state ButtonState) { + C.wlr_seat_pointer_notify_button(&s.p, C.uint32_t(time), C.uint32_t(button), uint32(state)) } -func (s Seat) NotifyPointerAxis(time uint32, orientation AxisOrientation, delta float64, deltaDiscrete int32, source AxisSource) { - C.wlr_seat_pointer_notify_axis(s.p, C.uint32_t(time), C.enum_wlr_axis_orientation(orientation), C.double(delta), C.int32_t(deltaDiscrete), C.enum_wlr_axis_source(source)) +func (s *Seat) NotifyPointerAxis(time uint32, orientation AxisOrientation, delta float64, deltaDiscrete int32, source AxisSource) { + C.wlr_seat_pointer_notify_axis(&s.p, C.uint32_t(time), C.enum_wlr_axis_orientation(orientation), C.double(delta), C.int32_t(deltaDiscrete), C.enum_wlr_axis_source(source)) } -func (s Seat) NotifyPointerEnter(surface Surface, sx float64, sy float64) { - C.wlr_seat_pointer_notify_enter(s.p, surface.p, C.double(sx), C.double(sy)) +func (s *Seat) NotifyPointerEnter(surface *Surface, sx float64, sy float64) { + C.wlr_seat_pointer_notify_enter(&s.p, &surface.p, C.double(sx), C.double(sy)) } -func (s Seat) NotifyPointerMotion(time uint32, sx float64, sy float64) { - C.wlr_seat_pointer_notify_motion(s.p, C.uint32_t(time), C.double(sx), C.double(sy)) +func (s *Seat) NotifyPointerMotion(time uint32, sx float64, sy float64) { + C.wlr_seat_pointer_notify_motion(&s.p, C.uint32_t(time), C.double(sx), C.double(sy)) } -func (s Seat) NotifyPointerFrame() { - C.wlr_seat_pointer_notify_frame(s.p) +func (s *Seat) NotifyPointerFrame() { + C.wlr_seat_pointer_notify_frame(&s.p) } -func (s Seat) NotifyKeyboardEnter(surface Surface, k Keyboard) { - C.wlr_seat_keyboard_notify_enter(s.p, surface.p, &k.p.keycodes[0], k.p.num_keycodes, &k.p.modifiers) +func (s *Seat) NotifyKeyboardEnter(surface *Surface, k *Keyboard) { + C.wlr_seat_keyboard_notify_enter(&s.p, &surface.p, &k.p.keycodes[0], k.p.num_keycodes, &k.p.modifiers) } -func (s Seat) NotifyKeyboardModifiers(k Keyboard) { - C.wlr_seat_keyboard_notify_modifiers(s.p, &k.p.modifiers) +func (s *Seat) NotifyKeyboardModifiers(k *Keyboard) { + C.wlr_seat_keyboard_notify_modifiers(&s.p, &k.p.modifiers) } -func (s Seat) NotifyKeyboardKey(time uint32, keyCode uint32, state KeyState) { - C.wlr_seat_keyboard_notify_key(s.p, C.uint32_t(time), C.uint32_t(keyCode), C.uint32_t(state)) +func (s *Seat) NotifyKeyboardKey(time uint32, keyCode uint32, state KeyState) { + C.wlr_seat_keyboard_notify_key(&s.p, C.uint32_t(time), C.uint32_t(keyCode), C.uint32_t(state)) } -func (s Seat) ClearPointerFocus() { - C.wlr_seat_pointer_clear_focus(s.p) +func (s *Seat) ClearPointerFocus() { + C.wlr_seat_pointer_clear_focus(&s.p) } -func (s Seat) Keyboard() Keyboard { - p := C.wlr_seat_get_keyboard(s.p) - return Keyboard{p: p} +func (s *Seat) Keyboard() *Keyboard { + p := C.wlr_seat_get_keyboard(&s.p) + return (*Keyboard)(unsafe.Pointer(p)) } -func (s Seat) KeyboardState() SeatKeyboardState { +func (s *Seat) KeyboardState() SeatKeyboardState { return SeatKeyboardState{s: s.p.keyboard_state} } -func (s Seat) PointerState() SeatPointerState { +func (s *Seat) PointerState() SeatPointerState { return SeatPointerState{s: s.p.pointer_state} } -func (s SeatKeyboardState) FocusedSurface() Surface { - return Surface{p: s.s.focused_surface} +func (s SeatKeyboardState) FocusedSurface() *Surface { + return (*Surface)(unsafe.Pointer(s.s.focused_surface)) } -func (s SeatPointerState) FocusedSurface() Surface { - return Surface{p: s.s.focused_surface} +func (s SeatPointerState) FocusedSurface() *Surface { + return (*Surface)(unsafe.Pointer(s.s.focused_surface)) } -func (s SeatPointerState) FocusedClient() SeatClient { - return SeatClient{p: s.s.focused_client} +func (s SeatPointerState) FocusedClient() *SeatClient { + return (*SeatClient)(unsafe.Pointer(s.s.focused_client)) } +//go:notinheap type Renderer struct { - p *C.struct_wlr_renderer + p C.struct_wlr_renderer } -func (r Renderer) Destroy() { - C.wlr_renderer_destroy(r.p) +func (r *Renderer) Destroy() { + C.wlr_renderer_destroy(&r.p) } -func (r Renderer) OnDestroy(cb func(Renderer)) { - man.add(unsafe.Pointer(r.p), &r.p.events.destroy, func(unsafe.Pointer) { +func (r *Renderer) OnDestroy(cb func(*Renderer)) { + man.add(unsafe.Pointer(r), &r.p.events.destroy, func(unsafe.Pointer) { cb(r) }) } -func (r Renderer) InitDisplay(display Display) { - C.wlr_renderer_init_wl_display(r.p, display.p) +func (r *Renderer) InitDisplay(display *Display) { + C.wlr_renderer_init_wl_display(&r.p, &display.p) } -func (r Renderer) Begin(output Output, width int, height int) { - C.wlr_renderer_begin(r.p, C.int(width), C.int(height)) +func (r *Renderer) Begin(output *Output, width int, height int) { + C.wlr_renderer_begin(&r.p, C.int(width), C.int(height)) } -func (r Renderer) Clear(color *Color) { +func (r *Renderer) Clear(color *Color) { c := color.toC() - C.wlr_renderer_clear(r.p, &c[0]) + C.wlr_renderer_clear(&r.p, &c[0]) } -func (r Renderer) End() { - C.wlr_renderer_end(r.p) +func (r *Renderer) End() { + C.wlr_renderer_end(&r.p) } -func (r Renderer) RenderTextureWithMatrix(texture Texture, matrix *Matrix, alpha float32) { +func (r *Renderer) RenderTextureWithMatrix(texture *Texture, matrix *Matrix, alpha float32) { m := matrix.toC() - C.wlr_render_texture_with_matrix(r.p, texture.p, &m[0], C.float(alpha)) + C.wlr_render_texture_with_matrix(&r.p, &texture.p, &m[0], C.float(alpha)) } -func (r Renderer) RenderRect(box *Box, color *Color, projection *Matrix) { +func (r *Renderer) RenderRect(box *Box, color *Color, projection *Matrix) { b := box.toC() c := color.toC() pm := projection.toC() - C.wlr_render_rect(r.p, &b, &c[0], &pm[0]) + C.wlr_render_rect(&r.p, &b, &c[0], &pm[0]) } +//go:notinheap type Output struct { - p *C.struct_wlr_output + p C.struct_wlr_output } +//go:notinheap type OutputMode struct { - p *C.struct_wlr_output_mode -} - -func wrapOutput(p unsafe.Pointer) Output { - return Output{p: (*C.struct_wlr_output)(p)} + p C.struct_wlr_output_mode } -func (o Output) OnDestroy(cb func(Output)) { - man.add(unsafe.Pointer(o.p), &o.p.events.destroy, func(unsafe.Pointer) { +func (o *Output) OnDestroy(cb func(*Output)) { + man.add(unsafe.Pointer(o), &o.p.events.destroy, func(unsafe.Pointer) { cb(o) }) } -func (o Output) Name() string { +func (o *Output) Name() string { return C.GoString(&o.p.name[0]) } -func (o Output) Scale() float32 { +func (o *Output) Scale() float32 { return float32(o.p.scale) } -func (o Output) TransformMatrix() Matrix { +func (o *Output) TransformMatrix() Matrix { var matrix Matrix matrix.fromC(&o.p.transform_matrix) return matrix } -func (o Output) OnFrame(cb func(Output)) { - man.add(unsafe.Pointer(o.p), &o.p.events.frame, func(data unsafe.Pointer) { +func (o *Output) OnFrame(cb func(*Output)) { + man.add(unsafe.Pointer(o), &o.p.events.frame, func(data unsafe.Pointer) { cb(o) }) } -func (o Output) RenderSoftwareCursors() { - C.wlr_output_render_software_cursors(o.p, nil) +func (o *Output) RenderSoftwareCursors() { + C.wlr_output_render_software_cursors(&o.p, nil) } -func (o Output) TransformedResolution() (int, int) { +func (o *Output) TransformedResolution() (int, int) { var width, height C.int - C.wlr_output_transformed_resolution(o.p, &width, &height) + C.wlr_output_transformed_resolution(&o.p, &width, &height) return int(width), int(height) } -func (o Output) EffectiveResolution() (int, int) { +func (o *Output) EffectiveResolution() (int, int) { var width, height C.int - C.wlr_output_effective_resolution(o.p, &width, &height) + C.wlr_output_effective_resolution(&o.p, &width, &height) return int(width), int(height) } -func (o Output) AttachRender() (int, error) { +func (o *Output) AttachRender() (int, error) { var bufferAge C.int - if !C.wlr_output_attach_render(o.p, &bufferAge) { + if !C.wlr_output_attach_render(&o.p, &bufferAge) { return 0, errors.New("can't make output context current") } return int(bufferAge), nil } -func (o Output) Rollback() { - C.wlr_output_rollback(o.p) +func (o *Output) Rollback() { + C.wlr_output_rollback(&o.p) } -func (o Output) CreateGlobal() { - C.wlr_output_create_global(o.p) +func (o *Output) CreateGlobal() { + C.wlr_output_create_global(&o.p) } -func (o Output) DestroyGlobal() { - C.wlr_output_destroy_global(o.p) +func (o *Output) DestroyGlobal() { + C.wlr_output_destroy_global(&o.p) } -func (o Output) Commit() { - C.wlr_output_commit(o.p) +func (o *Output) Commit() { + C.wlr_output_commit(&o.p) } -func (o Output) Modes() []OutputMode { +func (o *Output) Modes() []*OutputMode { // TODO: figure out what to do with this ridiculous for loop // perhaps this can be refactored into a less ugly hack that uses reflection - var modes []OutputMode + var modes []*OutputMode var mode *C.struct_wlr_output_mode for mode := (*C.struct_wlr_output_mode)(unsafe.Pointer(uintptr(unsafe.Pointer(o.p.modes.next)) - unsafe.Offsetof(mode.link))); &mode.link != &o.p.modes; mode = (*C.struct_wlr_output_mode)(unsafe.Pointer(uintptr(unsafe.Pointer(mode.link.next)) - unsafe.Offsetof(mode.link))) { - modes = append(modes, OutputMode{p: mode}) + modes = append(modes, (*OutputMode)(unsafe.Pointer(mode))) } return modes } -func (o Output) SetMode(mode OutputMode) { - C.wlr_output_set_mode(o.p, mode.p) +func (o *Output) SetMode(mode *OutputMode) { + C.wlr_output_set_mode(&o.p, &mode.p) } -func (o Output) Enable(enable bool) { - C.wlr_output_enable(o.p, C.bool(enable)) +func (o *Output) Enable(enable bool) { + C.wlr_output_enable(&o.p, C.bool(enable)) } -func (o Output) SetTitle(title string) error { - if C.wlr_output_is_wl(o.p) { - C.wlr_wl_output_set_title(o.p, C.CString(title)) - } else if C.wlr_output_is_x11(o.p) { - C.wlr_x11_output_set_title(o.p, C.CString(title)) +func (o *Output) SetTitle(title string) error { + // FIXME(dh): who owns the *char? do we need to free it, now or later? + if C.wlr_output_is_wl(&o.p) { + C.wlr_wl_output_set_title(&o.p, C.CString(title)) + } else if C.wlr_output_is_x11(&o.p) { + C.wlr_x11_output_set_title(&o.p, C.CString(title)) } else { return errors.New("this output type cannot have a title") } @@ -788,27 +785,28 @@ func (o Output) SetTitle(title string) error { return nil } +//go:notinheap type OutputLayout struct { - p *C.struct_wlr_output_layout + p C.struct_wlr_output_layout } -func NewOutputLayout() OutputLayout { +func NewOutputLayout() *OutputLayout { p := C.wlr_output_layout_create() man.track(unsafe.Pointer(p), &p.events.destroy) - return OutputLayout{p: p} + return (*OutputLayout)(unsafe.Pointer(p)) } -func (l OutputLayout) Destroy() { - C.wlr_output_layout_destroy(l.p) +func (l *OutputLayout) Destroy() { + C.wlr_output_layout_destroy(&l.p) } -func (l OutputLayout) AddOutputAuto(output Output) { - C.wlr_output_layout_add_auto(l.p, output.p) +func (l *OutputLayout) AddOutputAuto(output *Output) { + C.wlr_output_layout_add_auto(&l.p, &output.p) } -func (l OutputLayout) Coords(output Output) (x float64, y float64) { +func (l *OutputLayout) Coords(output *Output) (x float64, y float64) { var ox, oy C.double - C.wlr_output_layout_output_coords(l.p, output.p, &ox, &oy) + C.wlr_output_layout_output_coords(&l.p, &output.p, &ox, &oy) return float64(ox), float64(oy) } @@ -816,15 +814,15 @@ func OutputTransformInvert(transform uint32) uint32 { return uint32(C.wlr_output_transform_invert(C.enum_wl_output_transform(transform))) } -func (m OutputMode) Width() int32 { +func (m *OutputMode) Width() int32 { return int32(m.p.width) } -func (m OutputMode) Height() int32 { +func (m *OutputMode) Height() int32 { return int32(m.p.height) } -func (m OutputMode) RefreshRate() int32 { +func (m *OutputMode) RefreshRate() int32 { return int32(m.p.refresh) } @@ -899,38 +897,39 @@ const ( KeyboardModifierMod5 KeyboardModifier = C.WLR_MODIFIER_MOD5 ) +//go:notinheap type Keyboard struct { - p *C.struct_wlr_keyboard + p C.struct_wlr_keyboard } -func (k Keyboard) SetKeymap(keymap xkb.Keymap) { - C.wlr_keyboard_set_keymap(k.p, (*C.struct_xkb_keymap)(keymap.Ptr())) +func (k *Keyboard) SetKeymap(keymap xkb.Keymap) { + C.wlr_keyboard_set_keymap(&k.p, (*C.struct_xkb_keymap)(keymap.Ptr())) } -func (k Keyboard) RepeatInfo() (rate int32, delay int32) { +func (k *Keyboard) RepeatInfo() (rate int32, delay int32) { return int32(k.p.repeat_info.rate), int32(k.p.repeat_info.delay) } -func (k Keyboard) SetRepeatInfo(rate int32, delay int32) { - C.wlr_keyboard_set_repeat_info(k.p, C.int32_t(rate), C.int32_t(delay)) +func (k *Keyboard) SetRepeatInfo(rate int32, delay int32) { + C.wlr_keyboard_set_repeat_info(&k.p, C.int32_t(rate), C.int32_t(delay)) } -func (k Keyboard) XKBState() xkb.State { +func (k *Keyboard) XKBState() xkb.State { return xkb.WrapState(unsafe.Pointer(k.p.xkb_state)) } -func (k Keyboard) Modifiers() KeyboardModifier { - return KeyboardModifier(C.wlr_keyboard_get_modifiers(k.p)) +func (k *Keyboard) Modifiers() KeyboardModifier { + return KeyboardModifier(C.wlr_keyboard_get_modifiers(&k.p)) } -func (k Keyboard) OnModifiers(cb func(keyboard Keyboard)) { - man.add(unsafe.Pointer(k.p), &k.p.events.modifiers, func(data unsafe.Pointer) { +func (k *Keyboard) OnModifiers(cb func(keyboard *Keyboard)) { + man.add(unsafe.Pointer(k), &k.p.events.modifiers, func(data unsafe.Pointer) { cb(k) }) } -func (k Keyboard) OnKey(cb func(keyboard Keyboard, time uint32, keyCode uint32, updateState bool, state KeyState)) { - man.add(unsafe.Pointer(k.p), &k.p.events.key, func(data unsafe.Pointer) { +func (k *Keyboard) OnKey(cb func(keyboard *Keyboard, time uint32, keyCode uint32, updateState bool, state KeyState)) { + man.add(unsafe.Pointer(k), &k.p.events.key, func(data unsafe.Pointer) { event := (*C.struct_wlr_event_keyboard_key)(data) cb(k, uint32(event.time_msec), uint32(event.keycode), bool(event.update_state), KeyState(event.state)) }) @@ -970,25 +969,26 @@ const ( AxisOrientationHorizontal AxisOrientation = C.WLR_AXIS_ORIENTATION_HORIZONTAL ) +//go:notinheap type InputDevice struct { - p *C.struct_wlr_input_device + p C.struct_wlr_input_device } -func (d InputDevice) OnDestroy(cb func(InputDevice)) { - man.add(unsafe.Pointer(d.p), &d.p.events.destroy, func(unsafe.Pointer) { +func (d *InputDevice) OnDestroy(cb func(*InputDevice)) { + man.add(unsafe.Pointer(d), &d.p.events.destroy, func(unsafe.Pointer) { cb(d) }) } -func (d InputDevice) Type() InputDeviceType { return InputDeviceType(d.p._type) } -func (d InputDevice) Vendor() int { return int(d.p.vendor) } -func (d InputDevice) Product() int { return int(d.p.product) } -func (d InputDevice) Name() string { return C.GoString(d.p.name) } -func (d InputDevice) Width() float64 { return float64(d.p.width_mm) } -func (d InputDevice) Height() float64 { return float64(d.p.height_mm) } -func (d InputDevice) OutputName() string { return C.GoString(d.p.output_name) } +func (d *InputDevice) Type() InputDeviceType { return InputDeviceType(d.p._type) } +func (d *InputDevice) Vendor() int { return int(d.p.vendor) } +func (d *InputDevice) Product() int { return int(d.p.product) } +func (d *InputDevice) Name() string { return C.GoString(d.p.name) } +func (d *InputDevice) Width() float64 { return float64(d.p.width_mm) } +func (d *InputDevice) Height() float64 { return float64(d.p.height_mm) } +func (d *InputDevice) OutputName() string { return C.GoString(d.p.output_name) } -func validateInputDeviceType(d InputDevice, fn string, req InputDeviceType) { +func validateInputDeviceType(d *InputDevice, fn string, req InputDeviceType) { if typ := d.Type(); typ != req { if int(typ) >= len(inputDeviceNames) { panic(fmt.Sprintf("%s called on input device of type %d", fn, typ)) @@ -998,100 +998,99 @@ func validateInputDeviceType(d InputDevice, fn string, req InputDeviceType) { } } -func (d InputDevice) Keyboard() Keyboard { +func (d *InputDevice) Keyboard() *Keyboard { validateInputDeviceType(d, "Keyboard", InputDeviceTypeKeyboard) p := *(*unsafe.Pointer)(unsafe.Pointer(&d.p.anon0[0])) - return Keyboard{p: (*C.struct_wlr_keyboard)(p)} -} - -func wrapInputDevice(p unsafe.Pointer) InputDevice { - return InputDevice{p: (*C.struct_wlr_input_device)(p)} + return (*Keyboard)(p) } +//go:notinheap type DMABuf struct { - p *C.struct_wlr_linux_dmabuf_v1 + p C.struct_wlr_linux_dmabuf_v1 } -func NewDMABuf(display Display, renderer Renderer) DMABuf { - p := C.wlr_linux_dmabuf_v1_create(display.p, renderer.p) +func NewDMABuf(display *Display, renderer *Renderer) *DMABuf { + p := C.wlr_linux_dmabuf_v1_create(&display.p, &renderer.p) man.track(unsafe.Pointer(p), &p.events.destroy) - return DMABuf{p: p} + return (*DMABuf)(unsafe.Pointer(p)) } -func (b DMABuf) OnDestroy(cb func(DMABuf)) { - man.add(unsafe.Pointer(b.p), &b.p.events.destroy, func(unsafe.Pointer) { +func (b *DMABuf) OnDestroy(cb func(*DMABuf)) { + man.add(unsafe.Pointer(b), &b.p.events.destroy, func(unsafe.Pointer) { cb(b) }) } +//go:notinheap type EventLoop struct { - p *C.struct_wl_event_loop + p C.struct_wl_event_loop } -func (evl EventLoop) OnDestroy(cb func(EventLoop)) { - l := man.add(unsafe.Pointer(evl.p), nil, func(data unsafe.Pointer) { +func (evl *EventLoop) OnDestroy(cb func(*EventLoop)) { + l := man.add(unsafe.Pointer(evl), nil, func(data unsafe.Pointer) { cb(evl) }) - C.wl_event_loop_add_destroy_listener(evl.p, l.p) + C.wl_event_loop_add_destroy_listener(&evl.p, l.p) } -func (evl EventLoop) Fd() uintptr { - return uintptr(C.wl_event_loop_get_fd(evl.p)) +func (evl *EventLoop) Fd() uintptr { + return uintptr(C.wl_event_loop_get_fd(&evl.p)) } -func (evl EventLoop) Dispatch(timeout time.Duration) { +func (evl *EventLoop) Dispatch(timeout time.Duration) { var d int if timeout >= 0 { d = int(timeout / time.Millisecond) } else { d = -1 } - C.wl_event_loop_dispatch(evl.p, C.int(d)) + C.wl_event_loop_dispatch(&evl.p, C.int(d)) } +//go:notinheap type Display struct { - p *C.struct_wl_display + p C.struct_wl_display } -func NewDisplay() Display { +func NewDisplay() *Display { p := C.wl_display_create() - d := Display{p: p} - d.OnDestroy(func(Display) { + d := (*Display)(unsafe.Pointer(p)) + d.OnDestroy(func(*Display) { man.delete(unsafe.Pointer(p)) }) return d } -func (d Display) Destroy() { - C.wl_display_destroy(d.p) +func (d *Display) Destroy() { + C.wl_display_destroy(&d.p) } -func (d Display) OnDestroy(cb func(Display)) { - l := man.add(unsafe.Pointer(d.p), nil, func(data unsafe.Pointer) { +func (d *Display) OnDestroy(cb func(*Display)) { + l := man.add(unsafe.Pointer(d), nil, func(data unsafe.Pointer) { cb(d) }) - C.wl_display_add_destroy_listener(d.p, l.p) + C.wl_display_add_destroy_listener(&d.p, l.p) } -func (d Display) Run() { - C.wl_display_run(d.p) +func (d *Display) Run() { + C.wl_display_run(&d.p) } -func (d Display) Terminate() { - C.wl_display_terminate(d.p) +func (d *Display) Terminate() { + C.wl_display_terminate(&d.p) } -func (d Display) EventLoop() EventLoop { - p := C.wl_display_get_event_loop(d.p) - evl := EventLoop{p: p} - evl.OnDestroy(func(EventLoop) { +func (d *Display) EventLoop() *EventLoop { + p := C.wl_display_get_event_loop(&d.p) + evl := (*EventLoop)(unsafe.Pointer(p)) + evl.OnDestroy(func(*EventLoop) { man.delete(unsafe.Pointer(p)) }) return evl } -func (d Display) AddSocketAuto() (string, error) { - socket := C.wl_display_add_socket_auto(d.p) +func (d *Display) AddSocketAuto() (string, error) { + socket := C.wl_display_add_socket_auto(&d.p) if socket == nil { return "", errors.New("can't auto add wayland socket") } @@ -1099,8 +1098,8 @@ func (d Display) AddSocketAuto() (string, error) { return C.GoString(socket), nil } -func (d Display) FlushClients() { - C.wl_display_flush_clients(d.p) +func (d *Display) FlushClients() { + C.wl_display_flush_clients(&d.p) } type ServerDecorationManagerMode uint32 @@ -1111,164 +1110,167 @@ const ( ServerDecorationManagerModeServer ServerDecorationManagerMode = C.WLR_SERVER_DECORATION_MANAGER_MODE_SERVER ) +//go:notinheap type ServerDecorationManager struct { - p *C.struct_wlr_server_decoration_manager + p C.struct_wlr_server_decoration_manager } +//go:notinheap type ServerDecoration struct { - p *C.struct_wlr_server_decoration + p C.struct_wlr_server_decoration } -func NewServerDecorationManager(display Display) ServerDecorationManager { - p := C.wlr_server_decoration_manager_create(display.p) +func NewServerDecorationManager(display *Display) *ServerDecorationManager { + p := C.wlr_server_decoration_manager_create(&display.p) man.track(unsafe.Pointer(p), &p.events.destroy) - return ServerDecorationManager{p: p} + return (*ServerDecorationManager)(unsafe.Pointer(p)) } -func (m ServerDecorationManager) OnDestroy(cb func(ServerDecorationManager)) { - man.add(unsafe.Pointer(m.p), &m.p.events.destroy, func(unsafe.Pointer) { +func (m *ServerDecorationManager) OnDestroy(cb func(*ServerDecorationManager)) { + man.add(unsafe.Pointer(m), &m.p.events.destroy, func(unsafe.Pointer) { cb(m) }) } -func (m ServerDecorationManager) SetDefaultMode(mode ServerDecorationManagerMode) { - C.wlr_server_decoration_manager_set_default_mode(m.p, C.uint32_t(mode)) +func (m *ServerDecorationManager) SetDefaultMode(mode ServerDecorationManagerMode) { + C.wlr_server_decoration_manager_set_default_mode(&m.p, C.uint32_t(mode)) } -func (m ServerDecorationManager) OnNewMode(cb func(ServerDecorationManager, ServerDecoration)) { - man.add(unsafe.Pointer(m.p), &m.p.events.new_decoration, func(data unsafe.Pointer) { - dec := ServerDecoration{ - p: (*C.struct_wlr_server_decoration)(data), - } - man.track(unsafe.Pointer(dec.p), &dec.p.events.destroy) +func (m *ServerDecorationManager) OnNewMode(cb func(*ServerDecorationManager, *ServerDecoration)) { + man.add(unsafe.Pointer(m), &m.p.events.new_decoration, func(data unsafe.Pointer) { + dec := (*ServerDecoration)(data) + man.track(unsafe.Pointer(&dec.p), &dec.p.events.destroy) cb(m, dec) }) } -func (d ServerDecoration) OnDestroy(cb func(ServerDecoration)) { - man.add(unsafe.Pointer(d.p), &d.p.events.destroy, func(unsafe.Pointer) { +func (d *ServerDecoration) OnDestroy(cb func(*ServerDecoration)) { + man.add(unsafe.Pointer(d), &d.p.events.destroy, func(unsafe.Pointer) { cb(d) }) } -func (d ServerDecoration) OnMode(cb func(ServerDecoration)) { - man.add(unsafe.Pointer(d.p), &d.p.events.mode, func(unsafe.Pointer) { +func (d *ServerDecoration) OnMode(cb func(*ServerDecoration)) { + man.add(unsafe.Pointer(d), &d.p.events.mode, func(unsafe.Pointer) { cb(d) }) } -func (d ServerDecoration) Mode() ServerDecorationManagerMode { +func (d *ServerDecoration) Mode() ServerDecorationManagerMode { return ServerDecorationManagerMode(d.p.mode) } +//go:notinheap type DataDeviceManager struct { - p *C.struct_wlr_data_device_manager + p C.struct_wlr_data_device_manager } -func NewDataDeviceManager(display Display) DataDeviceManager { - p := C.wlr_data_device_manager_create(display.p) +func NewDataDeviceManager(display *Display) *DataDeviceManager { + p := C.wlr_data_device_manager_create(&display.p) man.track(unsafe.Pointer(p), &p.events.destroy) - return DataDeviceManager{p: p} + return (*DataDeviceManager)(unsafe.Pointer(p)) } -func (m DataDeviceManager) OnDestroy(cb func(DataDeviceManager)) { - man.add(unsafe.Pointer(m.p), &m.p.events.destroy, func(unsafe.Pointer) { +func (m *DataDeviceManager) OnDestroy(cb func(*DataDeviceManager)) { + man.add(unsafe.Pointer(m), &m.p.events.destroy, func(unsafe.Pointer) { cb(m) }) } +//go:notinheap type Cursor struct { - p *C.struct_wlr_cursor + p C.struct_wlr_cursor } -func NewCursor() Cursor { +func NewCursor() *Cursor { p := C.wlr_cursor_create() - return Cursor{p: p} + return (*Cursor)(unsafe.Pointer(p)) } -func (c Cursor) Destroy() { - C.wlr_cursor_destroy(c.p) - man.delete(unsafe.Pointer(c.p)) +func (c *Cursor) Destroy() { + C.wlr_cursor_destroy(&c.p) + man.delete(unsafe.Pointer(c)) } -func (c Cursor) X() float64 { +func (c *Cursor) X() float64 { return float64(c.p.x) } -func (c Cursor) Y() float64 { +func (c *Cursor) Y() float64 { return float64(c.p.y) } -func (c Cursor) AttachOutputLayout(layout OutputLayout) { - C.wlr_cursor_attach_output_layout(c.p, layout.p) +func (c *Cursor) AttachOutputLayout(layout *OutputLayout) { + C.wlr_cursor_attach_output_layout(&c.p, &layout.p) } -func (c Cursor) AttachInputDevice(dev InputDevice) { - C.wlr_cursor_attach_input_device(c.p, dev.p) +func (c *Cursor) AttachInputDevice(dev *InputDevice) { + C.wlr_cursor_attach_input_device(&c.p, &dev.p) } -func (c Cursor) Move(dev InputDevice, dx float64, dy float64) { - C.wlr_cursor_move(c.p, dev.p, C.double(dx), C.double(dy)) +func (c *Cursor) Move(dev *InputDevice, dx float64, dy float64) { + C.wlr_cursor_move(&c.p, &dev.p, C.double(dx), C.double(dy)) } -func (c Cursor) WarpAbsolute(dev InputDevice, x float64, y float64) { - C.wlr_cursor_warp_absolute(c.p, dev.p, C.double(x), C.double(y)) +func (c *Cursor) WarpAbsolute(dev *InputDevice, x float64, y float64) { + C.wlr_cursor_warp_absolute(&c.p, &dev.p, C.double(x), C.double(y)) } -func (c Cursor) SetSurface(surface Surface, hotspotX int32, hotspotY int32) { - C.wlr_cursor_set_surface(c.p, surface.p, C.int32_t(hotspotX), C.int32_t(hotspotY)) +func (c *Cursor) SetSurface(surface *Surface, hotspotX int32, hotspotY int32) { + C.wlr_cursor_set_surface(&c.p, &surface.p, C.int32_t(hotspotX), C.int32_t(hotspotY)) } -func (c Cursor) OnMotion(cb func(dev InputDevice, time uint32, dx float64, dy float64)) { - man.add(unsafe.Pointer(c.p), &c.p.events.motion, func(data unsafe.Pointer) { +func (c *Cursor) OnMotion(cb func(dev *InputDevice, time uint32, dx float64, dy float64)) { + man.add(unsafe.Pointer(c), &c.p.events.motion, func(data unsafe.Pointer) { event := (*C.struct_wlr_event_pointer_motion)(data) - dev := InputDevice{p: event.device} + dev := (*InputDevice)(unsafe.Pointer(event.device)) cb(dev, uint32(event.time_msec), float64(event.delta_x), float64(event.delta_y)) }) } -func (c Cursor) OnMotionAbsolute(cb func(dev InputDevice, time uint32, x float64, y float64)) { - man.add(unsafe.Pointer(c.p), &c.p.events.motion_absolute, func(data unsafe.Pointer) { +func (c *Cursor) OnMotionAbsolute(cb func(dev *InputDevice, time uint32, x float64, y float64)) { + man.add(unsafe.Pointer(c), &c.p.events.motion_absolute, func(data unsafe.Pointer) { event := (*C.struct_wlr_event_pointer_motion_absolute)(data) - dev := InputDevice{p: event.device} + dev := (*InputDevice)(unsafe.Pointer(event.device)) cb(dev, uint32(event.time_msec), float64(event.x), float64(event.y)) }) } -func (c Cursor) OnButton(cb func(dev InputDevice, time uint32, button uint32, state ButtonState)) { - man.add(unsafe.Pointer(c.p), &c.p.events.button, func(data unsafe.Pointer) { +func (c *Cursor) OnButton(cb func(dev *InputDevice, time uint32, button uint32, state ButtonState)) { + man.add(unsafe.Pointer(c), &c.p.events.button, func(data unsafe.Pointer) { event := (*C.struct_wlr_event_pointer_button)(data) - dev := InputDevice{p: event.device} + dev := (*InputDevice)(unsafe.Pointer(event.device)) cb(dev, uint32(event.time_msec), uint32(event.button), ButtonState(event.state)) }) } -func (c Cursor) OnAxis(cb func(dev InputDevice, time uint32, source AxisSource, orientation AxisOrientation, delta float64, deltaDiscrete int32)) { - man.add(unsafe.Pointer(c.p), &c.p.events.axis, func(data unsafe.Pointer) { +func (c *Cursor) OnAxis(cb func(dev *InputDevice, time uint32, source AxisSource, orientation AxisOrientation, delta float64, deltaDiscrete int32)) { + man.add(unsafe.Pointer(c), &c.p.events.axis, func(data unsafe.Pointer) { event := (*C.struct_wlr_event_pointer_axis)(data) - dev := InputDevice{p: event.device} + dev := (*InputDevice)(unsafe.Pointer(event.device)) cb(dev, uint32(event.time_msec), AxisSource(event.source), AxisOrientation(event.orientation), float64(event.delta), int32(event.delta_discrete)) }) } -func (c Cursor) OnFrame(cb func()) { - man.add(unsafe.Pointer(c.p), &c.p.events.frame, func(data unsafe.Pointer) { +func (c *Cursor) OnFrame(cb func()) { + man.add(unsafe.Pointer(c), &c.p.events.frame, func(data unsafe.Pointer) { cb() }) } +//go:notinheap type Compositor struct { - p *C.struct_wlr_compositor + p C.struct_wlr_compositor } -func NewCompositor(display Display, renderer Renderer) Compositor { - p := C.wlr_compositor_create(display.p, renderer.p) +func NewCompositor(display *Display, renderer *Renderer) *Compositor { + p := C.wlr_compositor_create(&display.p, &renderer.p) man.track(unsafe.Pointer(p), &p.events.destroy) - return Compositor{p: p} + return (*Compositor)(unsafe.Pointer(p)) } -func (c Compositor) OnDestroy(cb func(Compositor)) { - man.add(unsafe.Pointer(c.p), &c.p.events.destroy, func(unsafe.Pointer) { +func (c *Compositor) OnDestroy(cb func(*Compositor)) { + man.add(unsafe.Pointer(c), &c.p.events.destroy, func(unsafe.Pointer) { cb(c) }) } @@ -1320,59 +1322,60 @@ func (b *Box) fromC(cb *C.struct_wlr_box) { b.Height = int(cb.height) } +//go:notinheap type Backend struct { - p *C.struct_wlr_backend + p C.struct_wlr_backend } -func NewBackend(display Display) Backend { - p := C.wlr_backend_autocreate(display.p, nil) +func NewBackend(display *Display) *Backend { + p := C.wlr_backend_autocreate(&display.p, nil) man.track(unsafe.Pointer(p), &p.events.destroy) - return Backend{p: p} + return (*Backend)(unsafe.Pointer(p)) } -func (b Backend) Destroy() { - C.wlr_backend_destroy(b.p) +func (b *Backend) Destroy() { + C.wlr_backend_destroy(&b.p) } -func (b Backend) OnDestroy(cb func(Backend)) { - man.add(unsafe.Pointer(b.p), &b.p.events.destroy, func(unsafe.Pointer) { +func (b *Backend) OnDestroy(cb func(*Backend)) { + man.add(unsafe.Pointer(b), &b.p.events.destroy, func(unsafe.Pointer) { cb(b) }) } -func (b Backend) Start() error { - if !C.wlr_backend_start(b.p) { +func (b *Backend) Start() error { + if !C.wlr_backend_start(&b.p) { return errors.New("can't start backend") } return nil } -func (b Backend) OnNewOutput(cb func(Output)) { - man.add(unsafe.Pointer(b.p), &b.p.events.new_output, func(data unsafe.Pointer) { - output := wrapOutput(data) - man.track(unsafe.Pointer(output.p), &output.p.events.destroy) +func (b *Backend) OnNewOutput(cb func(*Output)) { + man.add(unsafe.Pointer(b), &b.p.events.new_output, func(data unsafe.Pointer) { + output := (*Output)(data) + man.track(data, &output.p.events.destroy) cb(output) }) } -func (b Backend) OnNewInput(cb func(InputDevice)) { - man.add(unsafe.Pointer(b.p), &b.p.events.new_input, func(data unsafe.Pointer) { - dev := wrapInputDevice(data) - man.add(unsafe.Pointer(dev.p), &dev.p.events.destroy, func(data unsafe.Pointer) { +func (b *Backend) OnNewInput(cb func(*InputDevice)) { + man.add(unsafe.Pointer(b), &b.p.events.new_input, func(data unsafe.Pointer) { + dev := (*InputDevice)(data) + man.add(data, &dev.p.events.destroy, func(data unsafe.Pointer) { // delete the underlying device type first man.delete(*(*unsafe.Pointer)(unsafe.Pointer(&dev.p.anon0[0]))) // then delete the wlr_input_device itself - man.delete(unsafe.Pointer(dev.p)) + man.delete(unsafe.Pointer(&dev.p)) }) cb(dev) }) } -func (b Backend) Renderer() Renderer { - p := C.wlr_backend_get_renderer(b.p) +func (b *Backend) Renderer() *Renderer { + p := C.wlr_backend_get_renderer(&b.p) man.track(unsafe.Pointer(p), &p.events.destroy) - return Renderer{p: p} + return (*Renderer)(unsafe.Pointer(p)) } // This whole mess has to exist for a number of reasons: