diff --git a/layershell.go b/layershell.go index df7966f..b8d737f 100644 --- a/layershell.go +++ b/layershell.go @@ -2,10 +2,24 @@ package wlr /* #include + +void _wlr_surface_for_each_cb(struct wlr_surface *surface, int sx, int sy, void *data); + +static inline void _wlr_layer_surface_v1_for_each_surface(struct wlr_layer_surface_v1 *surface, void *user_data) { + wlr_layer_surface_v1_for_each_surface(surface, _wlr_surface_for_each_cb, user_data); +} + +static inline void _wlr_layer_surface_v1_for_each_popup_surface(struct wlr_layer_surface_v1 *surface, void *user_data) { + wlr_layer_surface_v1_for_each_popup_surface(surface, _wlr_surface_for_each_cb, user_data); +} */ import "C" -import "unsafe" +import ( + "iter" + "runtime/cgo" + "unsafe" +) type LayerShellV1 struct { p *C.struct_wlr_layer_shell_v1 @@ -22,6 +36,9 @@ func (ls LayerShellV1) OnDestroy(cb func(LayerShellV1)) Listener { }) } +// OnNewSurface is emitted when a client creates a layer surface. Its +// output may be invalid, in which case the callback has to assign one +// with SetOutput before it returns. func (ls LayerShellV1) OnNewSurface(cb func(LayerSurfaceV1)) Listener { return newListener(&ls.p.events.new_surface, func(lis Listener, data unsafe.Pointer) { cb(LayerSurfaceV1{p: (*C.struct_wlr_layer_surface_v1)(data)}) @@ -38,6 +55,151 @@ func (s LayerSurfaceV1) Surface() Surface { } } +func (s LayerSurfaceV1) Output() Output { + return Output{p: s.p.output} +} + +func (s LayerSurfaceV1) SetOutput(output Output) { + s.p.output = output.p +} + +func (s LayerSurfaceV1) Namespace() string { + return C.GoString(s.p.namespace) +} + +// Initialized returns true once the client has made its initial +// commit. Configure can't be called before that. +func (s LayerSurfaceV1) Initialized() bool { + return bool(s.p.initialized) +} + +// InitialCommit returns true if the commit currently being handled is +// the surface's initial commit. +func (s LayerSurfaceV1) InitialCommit() bool { + return bool(s.p.initial_commit) +} + +func (s LayerSurfaceV1) Current() LayerSurfaceV1State { + return LayerSurfaceV1State{v: s.p.current} +} + +func (s LayerSurfaceV1) Pending() LayerSurfaceV1State { + return LayerSurfaceV1State{v: s.p.pending} +} + +// Configure sends a configure with the given size and returns its +// serial. The surface must be initialized. +func (s LayerSurfaceV1) Configure(width, height uint32) uint32 { + return uint32(C.wlr_layer_surface_v1_configure(s.p, C.uint32_t(width), C.uint32_t(height))) +} + +// Destroy sends the closed event to the client and destroys the layer +// surface. +func (s LayerSurfaceV1) Destroy() { + C.wlr_layer_surface_v1_destroy(s.p) +} + +// ExclusiveEdge returns the edge that the exclusive zone applies to, +// or EdgeNone if there isn't one. +func (s LayerSurfaceV1) ExclusiveEdge() Edges { + return Edges(C.wlr_layer_surface_v1_get_exclusive_edge(s.p)) +} + +func (s LayerSurfaceV1) OnDestroy(cb func(LayerSurfaceV1)) Listener { + return newListener(&s.p.events.destroy, func(lis Listener, data unsafe.Pointer) { + cb(s) + }) +} + +// ForEachSurface calls cb for the surface's mapped subsurfaces and +// popups, with their positions relative to the layer surface. +func (s LayerSurfaceV1) ForEachSurface(cb func(Surface, int, int)) { + handle := cgo.NewHandle(cb) + defer handle.Delete() + + C._wlr_layer_surface_v1_for_each_surface(s.p, unsafe.Pointer(&handle)) +} + +func (s LayerSurfaceV1) Surfaces() iter.Seq[IterSurface] { + return func(yield func(IterSurface) bool) { + ok := true + s.ForEachSurface(func(s Surface, sx, sy int) { + if !ok { + return + } + + ok = yield(IterSurface{s, sx, sy}) + }) + } +} + +// ForEachPopupSurface calls cb for the surfaces of the layer surface's +// popups and their subsurfaces, from root to leaves, with their +// positions relative to the layer surface. +func (s LayerSurfaceV1) ForEachPopupSurface(cb func(Surface, int, int)) { + handle := cgo.NewHandle(cb) + defer handle.Delete() + + C._wlr_layer_surface_v1_for_each_popup_surface(s.p, unsafe.Pointer(&handle)) +} + +func (s LayerSurfaceV1) PopupSurfaces() iter.Seq[IterSurface] { + return func(yield func(IterSurface) bool) { + ok := true + s.ForEachPopupSurface(func(s Surface, sx, sy int) { + if !ok { + return + } + + ok = yield(IterSurface{s, sx, sy}) + }) + } +} + +func (s LayerSurfaceV1) PopupSurfaceAt(sx float64, sy float64) (surface Surface, subX float64, subY float64, ok bool) { + var csubX, csubY C.double + p := C.wlr_layer_surface_v1_popup_surface_at(s.p, C.double(sx), C.double(sy), &csubX, &csubY) + return Surface{p: p}, float64(csubX), float64(csubY), p != nil +} + +type LayerSurfaceV1State struct { + v C.struct_wlr_layer_surface_v1_state +} + +// Committed returns the fields that the last commit changed. +func (s LayerSurfaceV1State) Committed() LayerSurfaceV1StateField { + return LayerSurfaceV1StateField(s.v.committed) +} + +func (s LayerSurfaceV1State) Anchor() LayerSurfaceV1Anchor { + return LayerSurfaceV1Anchor(s.v.anchor) +} + +func (s LayerSurfaceV1State) ExclusiveZone() int32 { + return int32(s.v.exclusive_zone) +} + +func (s LayerSurfaceV1State) Margin() (top, right, bottom, left int32) { + m := s.v.margin + return int32(m.top), int32(m.right), int32(m.bottom), int32(m.left) +} + +func (s LayerSurfaceV1State) KeyboardInteractive() LayerSurfaceV1KeyboardInteractivity { + return LayerSurfaceV1KeyboardInteractivity(s.v.keyboard_interactive) +} + +func (s LayerSurfaceV1State) DesiredWidth() uint32 { + return uint32(s.v.desired_width) +} + +func (s LayerSurfaceV1State) DesiredHeight() uint32 { + return uint32(s.v.desired_height) +} + +func (s LayerSurfaceV1State) Layer() LayerShellV1Layer { + return LayerShellV1Layer(s.v.layer) +} + type LayerShellV1Layer int const ( @@ -46,3 +208,32 @@ const ( LayerShellV1LayerTop LayerShellV1Layer = C.ZWLR_LAYER_SHELL_V1_LAYER_TOP LayerShellV1LayerOverlay LayerShellV1Layer = C.ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY ) + +type LayerSurfaceV1Anchor uint32 + +const ( + LayerSurfaceV1AnchorTop LayerSurfaceV1Anchor = C.ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + LayerSurfaceV1AnchorBottom LayerSurfaceV1Anchor = C.ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM + LayerSurfaceV1AnchorLeft LayerSurfaceV1Anchor = C.ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + LayerSurfaceV1AnchorRight LayerSurfaceV1Anchor = C.ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT +) + +type LayerSurfaceV1KeyboardInteractivity uint32 + +const ( + LayerSurfaceV1KeyboardInteractivityNone LayerSurfaceV1KeyboardInteractivity = C.ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE + LayerSurfaceV1KeyboardInteractivityExclusive LayerSurfaceV1KeyboardInteractivity = C.ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE + LayerSurfaceV1KeyboardInteractivityOnDemand LayerSurfaceV1KeyboardInteractivity = C.ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND +) + +type LayerSurfaceV1StateField uint32 + +const ( + LayerSurfaceV1StateDesiredSize LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_DESIRED_SIZE + LayerSurfaceV1StateAnchor LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_ANCHOR + LayerSurfaceV1StateExclusiveZone LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_EXCLUSIVE_ZONE + LayerSurfaceV1StateMargin LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_MARGIN + LayerSurfaceV1StateKeyboardInteractivity LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_KEYBOARD_INTERACTIVITY + LayerSurfaceV1StateLayer LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_LAYER + LayerSurfaceV1StateExclusiveEdge LayerSurfaceV1StateField = C.WLR_LAYER_SURFACE_V1_STATE_EXCLUSIVE_EDGE +) diff --git a/seat.go b/seat.go index 6bc0841..856303d 100644 --- a/seat.go +++ b/seat.go @@ -155,6 +155,10 @@ func (s Seat) KeyboardNotifyEnter(surface Surface, keycodes []uint32, modifiers C.wlr_seat_keyboard_notify_enter(s.p, surface.p, kc, C.size_t(len(keycodes)), modifiers.p) } +func (s Seat) KeyboardNotifyClearFocus() { + C.wlr_seat_keyboard_notify_clear_focus(s.p) +} + func (s Seat) KeyboardNotifyModifiers(modifiers KeyboardModifiers) { C.wlr_seat_keyboard_notify_modifiers(s.p, modifiers.p) }