// Generated by go-wayland-scanner // https://github.com/yaslama/go-wayland/cmd/go-wayland-scanner // XML file : https://gitlab.freedesktop.org/wayland/wayland/-/raw/1.24.0/protocol/wayland.xml?ref_type=tags // // wayland Protocol Copyright: // // Copyright © 2008-2011 Kristian Høgsberg // Copyright © 2010-2011 Intel Corporation // Copyright © 2012-2013 Collabora, Ltd. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation files // (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice (including the // next paragraph) shall be included in all copies or substantial // portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package client import "golang.org/x/sys/unix" // DisplayInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const DisplayInterfaceName = "wl_display" // Display : core global object // // The core global object. This is a special singleton object. It // is used for internal Wayland protocol features. type Display struct { BaseProxy errorHandler DisplayErrorHandlerFunc deleteIdHandler DisplayDeleteIdHandlerFunc } // NewDisplay : core global object // // The core global object. This is a special singleton object. It // is used for internal Wayland protocol features. func NewDisplay(ctx *Context) *Display { wlDisplay := &Display{} ctx.Register(wlDisplay) return wlDisplay } // Sync : asynchronous roundtrip // // The sync request asks the server to emit the 'done' event // on the returned wl_callback object. Since requests are // handled in-order and events are delivered in-order, this can // be used as a barrier to ensure all previous requests and the // resulting events have been handled. // // The object returned by this request will be destroyed by the // compositor after the callback is fired and as such the client must not // attempt to use it after that point. // // The callback_data passed in the callback is undefined and should be ignored. func (i *Display) Sync() (*Callback, error) { callback := NewCallback(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], callback.ID()) err := i.Context().WriteMsg(_reqBuf[:], nil) return callback, err } // GetRegistry : get global registry object // // This request creates a registry object that allows the client // to list and bind the global objects available from the // compositor. // // It should be noted that the server side resources consumed in // response to a get_registry request can only be released when the // client disconnects, not when the client side proxy is destroyed. // Therefore, clients should invoke get_registry as infrequently as // possible to avoid wasting memory. func (i *Display) GetRegistry() (*Registry, error) { registry := NewRegistry(i.Context()) const opcode = 1 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], registry.ID()) err := i.Context().WriteMsg(_reqBuf[:], nil) return registry, err } func (i *Display) Destroy() error { i.MarkZombie() return nil } type DisplayError uint32 // DisplayError : global error values // // These errors are global and can be emitted in response to any // server request. const ( // DisplayErrorInvalidObject : server couldn't find object DisplayErrorInvalidObject DisplayError = 0 // DisplayErrorInvalidMethod : method doesn't exist on the specified interface or malformed request DisplayErrorInvalidMethod DisplayError = 1 // DisplayErrorNoMemory : server is out of memory DisplayErrorNoMemory DisplayError = 2 // DisplayErrorImplementation : implementation error in compositor DisplayErrorImplementation DisplayError = 3 ) func (e DisplayError) Name() string { switch e { case DisplayErrorInvalidObject: return "invalid_object" case DisplayErrorInvalidMethod: return "invalid_method" case DisplayErrorNoMemory: return "no_memory" case DisplayErrorImplementation: return "implementation" default: return "" } } func (e DisplayError) Value() string { switch e { case DisplayErrorInvalidObject: return "0" case DisplayErrorInvalidMethod: return "1" case DisplayErrorNoMemory: return "2" case DisplayErrorImplementation: return "3" default: return "" } } func (e DisplayError) String() string { return e.Name() + "=" + e.Value() } // DisplayErrorEvent : fatal error event // // The error event is sent out when a fatal (non-recoverable) // error has occurred. The object_id argument is the object // where the error occurred, most often in response to a request // to that object. The code identifies the error and is defined // by the object interface. As such, each interface defines its // own set of error codes. The message is a brief description // of the error, for (debugging) convenience. type DisplayErrorEvent struct { ObjectId Proxy Code uint32 Message string } type DisplayErrorHandlerFunc func(DisplayErrorEvent) // SetErrorHandler : sets handler for DisplayErrorEvent func (i *Display) SetErrorHandler(f DisplayErrorHandlerFunc) { i.errorHandler = f } // DisplayDeleteIdEvent : acknowledge object ID deletion // // This event is used internally by the object ID management // logic. When a client deletes an object that it had created, // the server will send this event to acknowledge that it has // seen the delete request. When the client receives this event, // it will know that it can safely reuse the object ID. type DisplayDeleteIdEvent struct { Id uint32 } type DisplayDeleteIdHandlerFunc func(DisplayDeleteIdEvent) // SetDeleteIdHandler : sets handler for DisplayDeleteIdEvent func (i *Display) SetDeleteIdHandler(f DisplayDeleteIdHandlerFunc) { i.deleteIdHandler = f } func (i *Display) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.errorHandler == nil { return } var e DisplayErrorEvent l := 0 e.ObjectId = i.Context().GetProxy(Uint32(data[l : l+4])) l += 4 e.Code = Uint32(data[l : l+4]) l += 4 messageLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Message = String(data[l : l+messageLen]) i.errorHandler(e) case 1: var e DisplayDeleteIdEvent l := 0 e.Id = Uint32(data[l : l+4]) l += 4 i.Context().DeleteID(e.Id) if i.deleteIdHandler != nil { i.deleteIdHandler(e) } } } // RegistryInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const RegistryInterfaceName = "wl_registry" // Registry : global registry object // // The singleton global registry object. The server has a number of // global objects that are available to all clients. These objects // typically represent an actual object in the server (for example, // an input device) or they are singleton objects that provide // extension functionality. // // When a client creates a registry object, the registry object // will emit a global event for each global currently in the // registry. Globals come and go as a result of device or // monitor hotplugs, reconfiguration or other events, and the // registry will send out global and global_remove events to // keep the client up to date with the changes. To mark the end // of the initial burst of events, the client can use the // wl_display.sync request immediately after calling // wl_display.get_registry. // // A client can bind to a global object by using the bind // request. This creates a client-side handle that lets the object // emit events to the client and lets the client invoke requests on // the object. type Registry struct { BaseProxy globalHandler RegistryGlobalHandlerFunc globalRemoveHandler RegistryGlobalRemoveHandlerFunc } // NewRegistry : global registry object // // The singleton global registry object. The server has a number of // global objects that are available to all clients. These objects // typically represent an actual object in the server (for example, // an input device) or they are singleton objects that provide // extension functionality. // // When a client creates a registry object, the registry object // will emit a global event for each global currently in the // registry. Globals come and go as a result of device or // monitor hotplugs, reconfiguration or other events, and the // registry will send out global and global_remove events to // keep the client up to date with the changes. To mark the end // of the initial burst of events, the client can use the // wl_display.sync request immediately after calling // wl_display.get_registry. // // A client can bind to a global object by using the bind // request. This creates a client-side handle that lets the object // emit events to the client and lets the client invoke requests on // the object. func NewRegistry(ctx *Context) *Registry { wlRegistry := &Registry{} ctx.Register(wlRegistry) return wlRegistry } // Bind : bind an object to the display // // Binds a new, client-created object to the server using the // specified name as the identifier. // // name: unique numeric name of the object func (i *Registry) Bind(name uint32, iface string, version uint32, id Proxy) error { const opcode = 0 ifaceLen := PaddedLen(len(iface) + 1) _reqBufLen := 8 + 4 + (4 + ifaceLen) + 4 + 4 _reqBuf := make([]byte, _reqBufLen) l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(name)) l += 4 PutString(_reqBuf[l:l+(4+ifaceLen)], iface) l += (4 + ifaceLen) PutUint32(_reqBuf[l:l+4], uint32(version)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf, nil) return err } func (i *Registry) Destroy() error { i.MarkZombie() return nil } // RegistryGlobalEvent : announce global object // // Notify the client of global objects. // // The event notifies the client that a global object with // the given name is now available, and it implements the // given version of the given interface. type RegistryGlobalEvent struct { Name uint32 Interface string Version uint32 } type RegistryGlobalHandlerFunc func(RegistryGlobalEvent) // SetGlobalHandler : sets handler for RegistryGlobalEvent func (i *Registry) SetGlobalHandler(f RegistryGlobalHandlerFunc) { i.globalHandler = f } // RegistryGlobalRemoveEvent : announce removal of global object // // Notify the client of removed global objects. // // This event notifies the client that the global identified // by name is no longer available. If the client bound to // the global using the bind request, the client should now // destroy that object. // // The object remains valid and requests to the object will be // ignored until the client destroys it, to avoid races between // the global going away and a client sending a request to it. type RegistryGlobalRemoveEvent struct { Name uint32 } type RegistryGlobalRemoveHandlerFunc func(RegistryGlobalRemoveEvent) // SetGlobalRemoveHandler : sets handler for RegistryGlobalRemoveEvent func (i *Registry) SetGlobalRemoveHandler(f RegistryGlobalRemoveHandlerFunc) { i.globalRemoveHandler = f } func (i *Registry) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.globalHandler == nil { return } var e RegistryGlobalEvent l := 0 e.Name = Uint32(data[l : l+4]) l += 4 interfaceLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Interface = String(data[l : l+interfaceLen]) l += interfaceLen e.Version = Uint32(data[l : l+4]) l += 4 i.globalHandler(e) case 1: if i.globalRemoveHandler == nil { return } var e RegistryGlobalRemoveEvent l := 0 e.Name = Uint32(data[l : l+4]) l += 4 i.globalRemoveHandler(e) } } // CallbackInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const CallbackInterfaceName = "wl_callback" // Callback : callback object // // Clients can handle the 'done' event to get notified when // the related request is done. // // Note, because wl_callback objects are created from multiple independent // factory interfaces, the wl_callback interface is frozen at version 1. type Callback struct { BaseProxy doneHandler CallbackDoneHandlerFunc } // NewCallback : callback object // // Clients can handle the 'done' event to get notified when // the related request is done. // // Note, because wl_callback objects are created from multiple independent // factory interfaces, the wl_callback interface is frozen at version 1. func NewCallback(ctx *Context) *Callback { wlCallback := &Callback{} ctx.Register(wlCallback) return wlCallback } func (i *Callback) Destroy() error { i.MarkZombie() return nil } // CallbackDoneEvent : done event // // Notify the client when the related request is done. type CallbackDoneEvent struct { CallbackData uint32 } type CallbackDoneHandlerFunc func(CallbackDoneEvent) // SetDoneHandler : sets handler for CallbackDoneEvent func (i *Callback) SetDoneHandler(f CallbackDoneHandlerFunc) { i.doneHandler = f } func (i *Callback) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.doneHandler == nil { return } var e CallbackDoneEvent l := 0 e.CallbackData = Uint32(data[l : l+4]) l += 4 i.doneHandler(e) } } // CompositorInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const CompositorInterfaceName = "wl_compositor" // Compositor : the compositor singleton // // A compositor. This object is a singleton global. The // compositor is in charge of combining the contents of multiple // surfaces into one displayable output. type Compositor struct { BaseProxy } // NewCompositor : the compositor singleton // // A compositor. This object is a singleton global. The // compositor is in charge of combining the contents of multiple // surfaces into one displayable output. func NewCompositor(ctx *Context) *Compositor { wlCompositor := &Compositor{} ctx.Register(wlCompositor) return wlCompositor } // CreateSurface : create new surface // // Ask the compositor to create a new surface. func (i *Compositor) CreateSurface() (*Surface, error) { id := NewSurface(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } // CreateRegion : create new region // // Ask the compositor to create a new region. func (i *Compositor) CreateRegion() (*Region, error) { id := NewRegion(i.Context()) const opcode = 1 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } func (i *Compositor) Destroy() error { i.MarkZombie() return nil } // ShmPoolInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const ShmPoolInterfaceName = "wl_shm_pool" // ShmPool : a shared memory pool // // The wl_shm_pool object encapsulates a piece of memory shared // between the compositor and client. Through the wl_shm_pool // object, the client can allocate shared memory wl_buffer objects. // All objects created through the same pool share the same // underlying mapped memory. Reusing the mapped memory avoids the // setup/teardown overhead and is useful when interactively resizing // a surface or for many small buffers. type ShmPool struct { BaseProxy } // NewShmPool : a shared memory pool // // The wl_shm_pool object encapsulates a piece of memory shared // between the compositor and client. Through the wl_shm_pool // object, the client can allocate shared memory wl_buffer objects. // All objects created through the same pool share the same // underlying mapped memory. Reusing the mapped memory avoids the // setup/teardown overhead and is useful when interactively resizing // a surface or for many small buffers. func NewShmPool(ctx *Context) *ShmPool { wlShmPool := &ShmPool{} ctx.Register(wlShmPool) return wlShmPool } // CreateBuffer : create a buffer from the pool // // Create a wl_buffer object from the pool. // // The buffer is created offset bytes into the pool and has // width and height as specified. The stride argument specifies // the number of bytes from the beginning of one row to the beginning // of the next. The format is the pixel format of the buffer and // must be one of those advertised through the wl_shm.format event. // // A buffer will keep a reference to the pool it was created from // so it is valid to destroy the pool immediately after creating // a buffer from it. // // offset: buffer byte offset within the pool // width: buffer width, in pixels // height: buffer height, in pixels // stride: number of bytes from the beginning of one row to the beginning of the next row // format: buffer pixel format func (i *ShmPool) CreateBuffer(offset, width, height, stride int32, format uint32) (*Buffer, error) { id := NewBuffer(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 + 4 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(offset)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(width)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(height)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(stride)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(format)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } // Destroy : destroy the pool // // Destroy the shared memory pool. // // The mmapped memory will be released when all // buffers that have been created from this pool // are gone. func (i *ShmPool) Destroy() error { defer i.MarkZombie() const opcode = 1 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Resize : change the size of the pool mapping // // This request will cause the server to remap the backing memory // for the pool from the file descriptor passed when the pool was // created, but using the new size. This request can only be // used to make the pool bigger. // // This request only changes the amount of bytes that are mmapped // by the server and does not touch the file corresponding to the // file descriptor passed at creation time. It is the client's // responsibility to ensure that the file is at least as big as // the new pool size. // // size: new size of the pool, in bytes func (i *ShmPool) Resize(size int32) error { const opcode = 2 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(size)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // ShmInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const ShmInterfaceName = "wl_shm" // Shm : shared memory support // // A singleton global object that provides support for shared // memory. // // Clients can create wl_shm_pool objects using the create_pool // request. // // On binding the wl_shm object one or more format events // are emitted to inform clients about the valid pixel formats // that can be used for buffers. type Shm struct { BaseProxy formatHandler ShmFormatHandlerFunc } // NewShm : shared memory support // // A singleton global object that provides support for shared // memory. // // Clients can create wl_shm_pool objects using the create_pool // request. // // On binding the wl_shm object one or more format events // are emitted to inform clients about the valid pixel formats // that can be used for buffers. func NewShm(ctx *Context) *Shm { wlShm := &Shm{} ctx.Register(wlShm) return wlShm } // CreatePool : create a shm pool // // Create a new wl_shm_pool object. // // The pool can be used to create shared memory based buffer // objects. The server will mmap size bytes of the passed file // descriptor, to use as backing memory for the pool. // // fd: file descriptor for the pool // size: pool size, in bytes func (i *Shm) CreatePool(fd int, size int32) (*ShmPool, error) { id := NewShmPool(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(size)) l += 4 oob := unix.UnixRights(int(fd)) err := i.Context().WriteMsg(_reqBuf[:], oob) return id, err } // Release : release the shm object // // Using this request a client can tell the server that it is not going to // use the shm object anymore. // // Objects created via this interface remain unaffected. func (i *Shm) Release() error { defer i.MarkZombie() const opcode = 1 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type ShmError uint32 // ShmError : wl_shm error values // // These errors can be emitted in response to wl_shm requests. const ( // ShmErrorInvalidFormat : buffer format is not known ShmErrorInvalidFormat ShmError = 0 // ShmErrorInvalidStride : invalid size or stride during pool or buffer creation ShmErrorInvalidStride ShmError = 1 // ShmErrorInvalidFd : mmapping the file descriptor failed ShmErrorInvalidFd ShmError = 2 ) func (e ShmError) Name() string { switch e { case ShmErrorInvalidFormat: return "invalid_format" case ShmErrorInvalidStride: return "invalid_stride" case ShmErrorInvalidFd: return "invalid_fd" default: return "" } } func (e ShmError) Value() string { switch e { case ShmErrorInvalidFormat: return "0" case ShmErrorInvalidStride: return "1" case ShmErrorInvalidFd: return "2" default: return "" } } func (e ShmError) String() string { return e.Name() + "=" + e.Value() } type ShmFormat uint32 // ShmFormat : pixel formats // // This describes the memory layout of an individual pixel. // // All renderers should support argb8888 and xrgb8888 but any other // formats are optional and may not be supported by the particular // renderer in use. // // The drm format codes match the macros defined in drm_fourcc.h, except // argb8888 and xrgb8888. The formats actually supported by the compositor // will be reported by the format event. // // For all wl_shm formats and unless specified in another protocol // extension, pre-multiplied alpha is used for pixel values. const ( // ShmFormatArgb8888 : 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian ShmFormatArgb8888 ShmFormat = 0 // ShmFormatXrgb8888 : 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian ShmFormatXrgb8888 ShmFormat = 1 // ShmFormatC8 : 8-bit color index format, [7:0] C ShmFormatC8 ShmFormat = 0x20203843 // ShmFormatRgb332 : 8-bit RGB format, [7:0] R:G:B 3:3:2 ShmFormatRgb332 ShmFormat = 0x38424752 // ShmFormatBgr233 : 8-bit BGR format, [7:0] B:G:R 2:3:3 ShmFormatBgr233 ShmFormat = 0x38524742 // ShmFormatXrgb4444 : 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian ShmFormatXrgb4444 ShmFormat = 0x32315258 // ShmFormatXbgr4444 : 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian ShmFormatXbgr4444 ShmFormat = 0x32314258 // ShmFormatRgbx4444 : 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian ShmFormatRgbx4444 ShmFormat = 0x32315852 // ShmFormatBgrx4444 : 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian ShmFormatBgrx4444 ShmFormat = 0x32315842 // ShmFormatArgb4444 : 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian ShmFormatArgb4444 ShmFormat = 0x32315241 // ShmFormatAbgr4444 : 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian ShmFormatAbgr4444 ShmFormat = 0x32314241 // ShmFormatRgba4444 : 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian ShmFormatRgba4444 ShmFormat = 0x32314152 // ShmFormatBgra4444 : 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian ShmFormatBgra4444 ShmFormat = 0x32314142 // ShmFormatXrgb1555 : 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian ShmFormatXrgb1555 ShmFormat = 0x35315258 // ShmFormatXbgr1555 : 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian ShmFormatXbgr1555 ShmFormat = 0x35314258 // ShmFormatRgbx5551 : 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian ShmFormatRgbx5551 ShmFormat = 0x35315852 // ShmFormatBgrx5551 : 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian ShmFormatBgrx5551 ShmFormat = 0x35315842 // ShmFormatArgb1555 : 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian ShmFormatArgb1555 ShmFormat = 0x35315241 // ShmFormatAbgr1555 : 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian ShmFormatAbgr1555 ShmFormat = 0x35314241 // ShmFormatRgba5551 : 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian ShmFormatRgba5551 ShmFormat = 0x35314152 // ShmFormatBgra5551 : 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian ShmFormatBgra5551 ShmFormat = 0x35314142 // ShmFormatRgb565 : 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian ShmFormatRgb565 ShmFormat = 0x36314752 // ShmFormatBgr565 : 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian ShmFormatBgr565 ShmFormat = 0x36314742 // ShmFormatRgb888 : 24-bit RGB format, [23:0] R:G:B little endian ShmFormatRgb888 ShmFormat = 0x34324752 // ShmFormatBgr888 : 24-bit BGR format, [23:0] B:G:R little endian ShmFormatBgr888 ShmFormat = 0x34324742 // ShmFormatXbgr8888 : 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian ShmFormatXbgr8888 ShmFormat = 0x34324258 // ShmFormatRgbx8888 : 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian ShmFormatRgbx8888 ShmFormat = 0x34325852 // ShmFormatBgrx8888 : 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian ShmFormatBgrx8888 ShmFormat = 0x34325842 // ShmFormatAbgr8888 : 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian ShmFormatAbgr8888 ShmFormat = 0x34324241 // ShmFormatRgba8888 : 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian ShmFormatRgba8888 ShmFormat = 0x34324152 // ShmFormatBgra8888 : 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian ShmFormatBgra8888 ShmFormat = 0x34324142 // ShmFormatXrgb2101010 : 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian ShmFormatXrgb2101010 ShmFormat = 0x30335258 // ShmFormatXbgr2101010 : 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian ShmFormatXbgr2101010 ShmFormat = 0x30334258 // ShmFormatRgbx1010102 : 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian ShmFormatRgbx1010102 ShmFormat = 0x30335852 // ShmFormatBgrx1010102 : 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian ShmFormatBgrx1010102 ShmFormat = 0x30335842 // ShmFormatArgb2101010 : 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian ShmFormatArgb2101010 ShmFormat = 0x30335241 // ShmFormatAbgr2101010 : 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian ShmFormatAbgr2101010 ShmFormat = 0x30334241 // ShmFormatRgba1010102 : 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian ShmFormatRgba1010102 ShmFormat = 0x30334152 // ShmFormatBgra1010102 : 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian ShmFormatBgra1010102 ShmFormat = 0x30334142 // ShmFormatYuyv : packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian ShmFormatYuyv ShmFormat = 0x56595559 // ShmFormatYvyu : packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian ShmFormatYvyu ShmFormat = 0x55595659 // ShmFormatUyvy : packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian ShmFormatUyvy ShmFormat = 0x59565955 // ShmFormatVyuy : packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian ShmFormatVyuy ShmFormat = 0x59555956 // ShmFormatAyuv : packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian ShmFormatAyuv ShmFormat = 0x56555941 // ShmFormatNv12 : 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane ShmFormatNv12 ShmFormat = 0x3231564e // ShmFormatNv21 : 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane ShmFormatNv21 ShmFormat = 0x3132564e // ShmFormatNv16 : 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane ShmFormatNv16 ShmFormat = 0x3631564e // ShmFormatNv61 : 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane ShmFormatNv61 ShmFormat = 0x3136564e // ShmFormatYuv410 : 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes ShmFormatYuv410 ShmFormat = 0x39565559 // ShmFormatYvu410 : 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes ShmFormatYvu410 ShmFormat = 0x39555659 // ShmFormatYuv411 : 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes ShmFormatYuv411 ShmFormat = 0x31315559 // ShmFormatYvu411 : 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes ShmFormatYvu411 ShmFormat = 0x31315659 // ShmFormatYuv420 : 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes ShmFormatYuv420 ShmFormat = 0x32315559 // ShmFormatYvu420 : 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes ShmFormatYvu420 ShmFormat = 0x32315659 // ShmFormatYuv422 : 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes ShmFormatYuv422 ShmFormat = 0x36315559 // ShmFormatYvu422 : 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes ShmFormatYvu422 ShmFormat = 0x36315659 // ShmFormatYuv444 : 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes ShmFormatYuv444 ShmFormat = 0x34325559 // ShmFormatYvu444 : 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes ShmFormatYvu444 ShmFormat = 0x34325659 // ShmFormatR8 : [7:0] R ShmFormatR8 ShmFormat = 0x20203852 // ShmFormatR16 : [15:0] R little endian ShmFormatR16 ShmFormat = 0x20363152 // ShmFormatRg88 : [15:0] R:G 8:8 little endian ShmFormatRg88 ShmFormat = 0x38384752 // ShmFormatGr88 : [15:0] G:R 8:8 little endian ShmFormatGr88 ShmFormat = 0x38385247 // ShmFormatRg1616 : [31:0] R:G 16:16 little endian ShmFormatRg1616 ShmFormat = 0x32334752 // ShmFormatGr1616 : [31:0] G:R 16:16 little endian ShmFormatGr1616 ShmFormat = 0x32335247 // ShmFormatXrgb16161616F : [63:0] x:R:G:B 16:16:16:16 little endian ShmFormatXrgb16161616F ShmFormat = 0x48345258 // ShmFormatXbgr16161616F : [63:0] x:B:G:R 16:16:16:16 little endian ShmFormatXbgr16161616F ShmFormat = 0x48344258 // ShmFormatArgb16161616F : [63:0] A:R:G:B 16:16:16:16 little endian ShmFormatArgb16161616F ShmFormat = 0x48345241 // ShmFormatAbgr16161616F : [63:0] A:B:G:R 16:16:16:16 little endian ShmFormatAbgr16161616F ShmFormat = 0x48344241 // ShmFormatXyuv8888 : [31:0] X:Y:Cb:Cr 8:8:8:8 little endian ShmFormatXyuv8888 ShmFormat = 0x56555958 // ShmFormatVuy888 : [23:0] Cr:Cb:Y 8:8:8 little endian ShmFormatVuy888 ShmFormat = 0x34325556 // ShmFormatVuy101010 : Y followed by U then V, 10:10:10. ShmFormatVuy101010 ShmFormat = 0x30335556 // ShmFormatY210 : [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels ShmFormatY210 ShmFormat = 0x30313259 // ShmFormatY212 : [63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels ShmFormatY212 ShmFormat = 0x32313259 // ShmFormatY216 : [63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels ShmFormatY216 ShmFormat = 0x36313259 // ShmFormatY410 : [31:0] A:Cr:Y:Cb 2:10:10:10 little endian ShmFormatY410 ShmFormat = 0x30313459 // ShmFormatY412 : [63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian ShmFormatY412 ShmFormat = 0x32313459 // ShmFormatY416 : [63:0] A:Cr:Y:Cb 16:16:16:16 little endian ShmFormatY416 ShmFormat = 0x36313459 // ShmFormatXvyu2101010 : [31:0] X:Cr:Y:Cb 2:10:10:10 little endian ShmFormatXvyu2101010 ShmFormat = 0x30335658 // ShmFormatXvyu1216161616 : [63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian ShmFormatXvyu1216161616 ShmFormat = 0x36335658 // ShmFormatXvyu16161616 : [63:0] X:Cr:Y:Cb 16:16:16:16 little endian ShmFormatXvyu16161616 ShmFormat = 0x38345658 // ShmFormatY0L0 : [63:0] A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian ShmFormatY0L0 ShmFormat = 0x304c3059 // ShmFormatX0L0 : [63:0] X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0 1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian ShmFormatX0L0 ShmFormat = 0x304c3058 // ShmFormatY0L2 : [63:0] A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian ShmFormatY0L2 ShmFormat = 0x324c3059 // ShmFormatX0L2 : [63:0] X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0 1:1:10:10:10:1:1:10:10:10 little endian ShmFormatX0L2 ShmFormat = 0x324c3058 ShmFormatYuv4208Bit ShmFormat = 0x38305559 ShmFormatYuv42010Bit ShmFormat = 0x30315559 ShmFormatXrgb8888A8 ShmFormat = 0x38415258 ShmFormatXbgr8888A8 ShmFormat = 0x38414258 ShmFormatRgbx8888A8 ShmFormat = 0x38415852 ShmFormatBgrx8888A8 ShmFormat = 0x38415842 ShmFormatRgb888A8 ShmFormat = 0x38413852 ShmFormatBgr888A8 ShmFormat = 0x38413842 ShmFormatRgb565A8 ShmFormat = 0x38413552 ShmFormatBgr565A8 ShmFormat = 0x38413542 // ShmFormatNv24 : non-subsampled Cr:Cb plane ShmFormatNv24 ShmFormat = 0x3432564e // ShmFormatNv42 : non-subsampled Cb:Cr plane ShmFormatNv42 ShmFormat = 0x3234564e // ShmFormatP210 : 2x1 subsampled Cr:Cb plane, 10 bit per channel ShmFormatP210 ShmFormat = 0x30313250 // ShmFormatP010 : 2x2 subsampled Cr:Cb plane 10 bits per channel ShmFormatP010 ShmFormat = 0x30313050 // ShmFormatP012 : 2x2 subsampled Cr:Cb plane 12 bits per channel ShmFormatP012 ShmFormat = 0x32313050 // ShmFormatP016 : 2x2 subsampled Cr:Cb plane 16 bits per channel ShmFormatP016 ShmFormat = 0x36313050 // ShmFormatAxbxgxrx106106106106 : [63:0] A:x:B:x:G:x:R:x 10:6:10:6:10:6:10:6 little endian ShmFormatAxbxgxrx106106106106 ShmFormat = 0x30314241 // ShmFormatNv15 : 2x2 subsampled Cr:Cb plane ShmFormatNv15 ShmFormat = 0x3531564e ShmFormatQ410 ShmFormat = 0x30313451 ShmFormatQ401 ShmFormat = 0x31303451 // ShmFormatXrgb16161616 : [63:0] x:R:G:B 16:16:16:16 little endian ShmFormatXrgb16161616 ShmFormat = 0x38345258 // ShmFormatXbgr16161616 : [63:0] x:B:G:R 16:16:16:16 little endian ShmFormatXbgr16161616 ShmFormat = 0x38344258 // ShmFormatArgb16161616 : [63:0] A:R:G:B 16:16:16:16 little endian ShmFormatArgb16161616 ShmFormat = 0x38345241 // ShmFormatAbgr16161616 : [63:0] A:B:G:R 16:16:16:16 little endian ShmFormatAbgr16161616 ShmFormat = 0x38344241 // ShmFormatC1 : [7:0] C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte ShmFormatC1 ShmFormat = 0x20203143 // ShmFormatC2 : [7:0] C0:C1:C2:C3 2:2:2:2 four pixels/byte ShmFormatC2 ShmFormat = 0x20203243 // ShmFormatC4 : [7:0] C0:C1 4:4 two pixels/byte ShmFormatC4 ShmFormat = 0x20203443 // ShmFormatD1 : [7:0] D0:D1:D2:D3:D4:D5:D6:D7 1:1:1:1:1:1:1:1 eight pixels/byte ShmFormatD1 ShmFormat = 0x20203144 // ShmFormatD2 : [7:0] D0:D1:D2:D3 2:2:2:2 four pixels/byte ShmFormatD2 ShmFormat = 0x20203244 // ShmFormatD4 : [7:0] D0:D1 4:4 two pixels/byte ShmFormatD4 ShmFormat = 0x20203444 // ShmFormatD8 : [7:0] D ShmFormatD8 ShmFormat = 0x20203844 // ShmFormatR1 : [7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte ShmFormatR1 ShmFormat = 0x20203152 // ShmFormatR2 : [7:0] R0:R1:R2:R3 2:2:2:2 four pixels/byte ShmFormatR2 ShmFormat = 0x20203252 // ShmFormatR4 : [7:0] R0:R1 4:4 two pixels/byte ShmFormatR4 ShmFormat = 0x20203452 // ShmFormatR10 : [15:0] x:R 6:10 little endian ShmFormatR10 ShmFormat = 0x20303152 // ShmFormatR12 : [15:0] x:R 4:12 little endian ShmFormatR12 ShmFormat = 0x20323152 // ShmFormatAvuy8888 : [31:0] A:Cr:Cb:Y 8:8:8:8 little endian ShmFormatAvuy8888 ShmFormat = 0x59555641 // ShmFormatXvuy8888 : [31:0] X:Cr:Cb:Y 8:8:8:8 little endian ShmFormatXvuy8888 ShmFormat = 0x59555658 // ShmFormatP030 : 2x2 subsampled Cr:Cb plane 10 bits per channel packed ShmFormatP030 ShmFormat = 0x30333050 ) func (e ShmFormat) Name() string { switch e { case ShmFormatArgb8888: return "argb8888" case ShmFormatXrgb8888: return "xrgb8888" case ShmFormatC8: return "c8" case ShmFormatRgb332: return "rgb332" case ShmFormatBgr233: return "bgr233" case ShmFormatXrgb4444: return "xrgb4444" case ShmFormatXbgr4444: return "xbgr4444" case ShmFormatRgbx4444: return "rgbx4444" case ShmFormatBgrx4444: return "bgrx4444" case ShmFormatArgb4444: return "argb4444" case ShmFormatAbgr4444: return "abgr4444" case ShmFormatRgba4444: return "rgba4444" case ShmFormatBgra4444: return "bgra4444" case ShmFormatXrgb1555: return "xrgb1555" case ShmFormatXbgr1555: return "xbgr1555" case ShmFormatRgbx5551: return "rgbx5551" case ShmFormatBgrx5551: return "bgrx5551" case ShmFormatArgb1555: return "argb1555" case ShmFormatAbgr1555: return "abgr1555" case ShmFormatRgba5551: return "rgba5551" case ShmFormatBgra5551: return "bgra5551" case ShmFormatRgb565: return "rgb565" case ShmFormatBgr565: return "bgr565" case ShmFormatRgb888: return "rgb888" case ShmFormatBgr888: return "bgr888" case ShmFormatXbgr8888: return "xbgr8888" case ShmFormatRgbx8888: return "rgbx8888" case ShmFormatBgrx8888: return "bgrx8888" case ShmFormatAbgr8888: return "abgr8888" case ShmFormatRgba8888: return "rgba8888" case ShmFormatBgra8888: return "bgra8888" case ShmFormatXrgb2101010: return "xrgb2101010" case ShmFormatXbgr2101010: return "xbgr2101010" case ShmFormatRgbx1010102: return "rgbx1010102" case ShmFormatBgrx1010102: return "bgrx1010102" case ShmFormatArgb2101010: return "argb2101010" case ShmFormatAbgr2101010: return "abgr2101010" case ShmFormatRgba1010102: return "rgba1010102" case ShmFormatBgra1010102: return "bgra1010102" case ShmFormatYuyv: return "yuyv" case ShmFormatYvyu: return "yvyu" case ShmFormatUyvy: return "uyvy" case ShmFormatVyuy: return "vyuy" case ShmFormatAyuv: return "ayuv" case ShmFormatNv12: return "nv12" case ShmFormatNv21: return "nv21" case ShmFormatNv16: return "nv16" case ShmFormatNv61: return "nv61" case ShmFormatYuv410: return "yuv410" case ShmFormatYvu410: return "yvu410" case ShmFormatYuv411: return "yuv411" case ShmFormatYvu411: return "yvu411" case ShmFormatYuv420: return "yuv420" case ShmFormatYvu420: return "yvu420" case ShmFormatYuv422: return "yuv422" case ShmFormatYvu422: return "yvu422" case ShmFormatYuv444: return "yuv444" case ShmFormatYvu444: return "yvu444" case ShmFormatR8: return "r8" case ShmFormatR16: return "r16" case ShmFormatRg88: return "rg88" case ShmFormatGr88: return "gr88" case ShmFormatRg1616: return "rg1616" case ShmFormatGr1616: return "gr1616" case ShmFormatXrgb16161616F: return "xrgb16161616f" case ShmFormatXbgr16161616F: return "xbgr16161616f" case ShmFormatArgb16161616F: return "argb16161616f" case ShmFormatAbgr16161616F: return "abgr16161616f" case ShmFormatXyuv8888: return "xyuv8888" case ShmFormatVuy888: return "vuy888" case ShmFormatVuy101010: return "vuy101010" case ShmFormatY210: return "y210" case ShmFormatY212: return "y212" case ShmFormatY216: return "y216" case ShmFormatY410: return "y410" case ShmFormatY412: return "y412" case ShmFormatY416: return "y416" case ShmFormatXvyu2101010: return "xvyu2101010" case ShmFormatXvyu1216161616: return "xvyu12_16161616" case ShmFormatXvyu16161616: return "xvyu16161616" case ShmFormatY0L0: return "y0l0" case ShmFormatX0L0: return "x0l0" case ShmFormatY0L2: return "y0l2" case ShmFormatX0L2: return "x0l2" case ShmFormatYuv4208Bit: return "yuv420_8bit" case ShmFormatYuv42010Bit: return "yuv420_10bit" case ShmFormatXrgb8888A8: return "xrgb8888_a8" case ShmFormatXbgr8888A8: return "xbgr8888_a8" case ShmFormatRgbx8888A8: return "rgbx8888_a8" case ShmFormatBgrx8888A8: return "bgrx8888_a8" case ShmFormatRgb888A8: return "rgb888_a8" case ShmFormatBgr888A8: return "bgr888_a8" case ShmFormatRgb565A8: return "rgb565_a8" case ShmFormatBgr565A8: return "bgr565_a8" case ShmFormatNv24: return "nv24" case ShmFormatNv42: return "nv42" case ShmFormatP210: return "p210" case ShmFormatP010: return "p010" case ShmFormatP012: return "p012" case ShmFormatP016: return "p016" case ShmFormatAxbxgxrx106106106106: return "axbxgxrx106106106106" case ShmFormatNv15: return "nv15" case ShmFormatQ410: return "q410" case ShmFormatQ401: return "q401" case ShmFormatXrgb16161616: return "xrgb16161616" case ShmFormatXbgr16161616: return "xbgr16161616" case ShmFormatArgb16161616: return "argb16161616" case ShmFormatAbgr16161616: return "abgr16161616" case ShmFormatC1: return "c1" case ShmFormatC2: return "c2" case ShmFormatC4: return "c4" case ShmFormatD1: return "d1" case ShmFormatD2: return "d2" case ShmFormatD4: return "d4" case ShmFormatD8: return "d8" case ShmFormatR1: return "r1" case ShmFormatR2: return "r2" case ShmFormatR4: return "r4" case ShmFormatR10: return "r10" case ShmFormatR12: return "r12" case ShmFormatAvuy8888: return "avuy8888" case ShmFormatXvuy8888: return "xvuy8888" case ShmFormatP030: return "p030" default: return "" } } func (e ShmFormat) Value() string { switch e { case ShmFormatArgb8888: return "0" case ShmFormatXrgb8888: return "1" case ShmFormatC8: return "0x20203843" case ShmFormatRgb332: return "0x38424752" case ShmFormatBgr233: return "0x38524742" case ShmFormatXrgb4444: return "0x32315258" case ShmFormatXbgr4444: return "0x32314258" case ShmFormatRgbx4444: return "0x32315852" case ShmFormatBgrx4444: return "0x32315842" case ShmFormatArgb4444: return "0x32315241" case ShmFormatAbgr4444: return "0x32314241" case ShmFormatRgba4444: return "0x32314152" case ShmFormatBgra4444: return "0x32314142" case ShmFormatXrgb1555: return "0x35315258" case ShmFormatXbgr1555: return "0x35314258" case ShmFormatRgbx5551: return "0x35315852" case ShmFormatBgrx5551: return "0x35315842" case ShmFormatArgb1555: return "0x35315241" case ShmFormatAbgr1555: return "0x35314241" case ShmFormatRgba5551: return "0x35314152" case ShmFormatBgra5551: return "0x35314142" case ShmFormatRgb565: return "0x36314752" case ShmFormatBgr565: return "0x36314742" case ShmFormatRgb888: return "0x34324752" case ShmFormatBgr888: return "0x34324742" case ShmFormatXbgr8888: return "0x34324258" case ShmFormatRgbx8888: return "0x34325852" case ShmFormatBgrx8888: return "0x34325842" case ShmFormatAbgr8888: return "0x34324241" case ShmFormatRgba8888: return "0x34324152" case ShmFormatBgra8888: return "0x34324142" case ShmFormatXrgb2101010: return "0x30335258" case ShmFormatXbgr2101010: return "0x30334258" case ShmFormatRgbx1010102: return "0x30335852" case ShmFormatBgrx1010102: return "0x30335842" case ShmFormatArgb2101010: return "0x30335241" case ShmFormatAbgr2101010: return "0x30334241" case ShmFormatRgba1010102: return "0x30334152" case ShmFormatBgra1010102: return "0x30334142" case ShmFormatYuyv: return "0x56595559" case ShmFormatYvyu: return "0x55595659" case ShmFormatUyvy: return "0x59565955" case ShmFormatVyuy: return "0x59555956" case ShmFormatAyuv: return "0x56555941" case ShmFormatNv12: return "0x3231564e" case ShmFormatNv21: return "0x3132564e" case ShmFormatNv16: return "0x3631564e" case ShmFormatNv61: return "0x3136564e" case ShmFormatYuv410: return "0x39565559" case ShmFormatYvu410: return "0x39555659" case ShmFormatYuv411: return "0x31315559" case ShmFormatYvu411: return "0x31315659" case ShmFormatYuv420: return "0x32315559" case ShmFormatYvu420: return "0x32315659" case ShmFormatYuv422: return "0x36315559" case ShmFormatYvu422: return "0x36315659" case ShmFormatYuv444: return "0x34325559" case ShmFormatYvu444: return "0x34325659" case ShmFormatR8: return "0x20203852" case ShmFormatR16: return "0x20363152" case ShmFormatRg88: return "0x38384752" case ShmFormatGr88: return "0x38385247" case ShmFormatRg1616: return "0x32334752" case ShmFormatGr1616: return "0x32335247" case ShmFormatXrgb16161616F: return "0x48345258" case ShmFormatXbgr16161616F: return "0x48344258" case ShmFormatArgb16161616F: return "0x48345241" case ShmFormatAbgr16161616F: return "0x48344241" case ShmFormatXyuv8888: return "0x56555958" case ShmFormatVuy888: return "0x34325556" case ShmFormatVuy101010: return "0x30335556" case ShmFormatY210: return "0x30313259" case ShmFormatY212: return "0x32313259" case ShmFormatY216: return "0x36313259" case ShmFormatY410: return "0x30313459" case ShmFormatY412: return "0x32313459" case ShmFormatY416: return "0x36313459" case ShmFormatXvyu2101010: return "0x30335658" case ShmFormatXvyu1216161616: return "0x36335658" case ShmFormatXvyu16161616: return "0x38345658" case ShmFormatY0L0: return "0x304c3059" case ShmFormatX0L0: return "0x304c3058" case ShmFormatY0L2: return "0x324c3059" case ShmFormatX0L2: return "0x324c3058" case ShmFormatYuv4208Bit: return "0x38305559" case ShmFormatYuv42010Bit: return "0x30315559" case ShmFormatXrgb8888A8: return "0x38415258" case ShmFormatXbgr8888A8: return "0x38414258" case ShmFormatRgbx8888A8: return "0x38415852" case ShmFormatBgrx8888A8: return "0x38415842" case ShmFormatRgb888A8: return "0x38413852" case ShmFormatBgr888A8: return "0x38413842" case ShmFormatRgb565A8: return "0x38413552" case ShmFormatBgr565A8: return "0x38413542" case ShmFormatNv24: return "0x3432564e" case ShmFormatNv42: return "0x3234564e" case ShmFormatP210: return "0x30313250" case ShmFormatP010: return "0x30313050" case ShmFormatP012: return "0x32313050" case ShmFormatP016: return "0x36313050" case ShmFormatAxbxgxrx106106106106: return "0x30314241" case ShmFormatNv15: return "0x3531564e" case ShmFormatQ410: return "0x30313451" case ShmFormatQ401: return "0x31303451" case ShmFormatXrgb16161616: return "0x38345258" case ShmFormatXbgr16161616: return "0x38344258" case ShmFormatArgb16161616: return "0x38345241" case ShmFormatAbgr16161616: return "0x38344241" case ShmFormatC1: return "0x20203143" case ShmFormatC2: return "0x20203243" case ShmFormatC4: return "0x20203443" case ShmFormatD1: return "0x20203144" case ShmFormatD2: return "0x20203244" case ShmFormatD4: return "0x20203444" case ShmFormatD8: return "0x20203844" case ShmFormatR1: return "0x20203152" case ShmFormatR2: return "0x20203252" case ShmFormatR4: return "0x20203452" case ShmFormatR10: return "0x20303152" case ShmFormatR12: return "0x20323152" case ShmFormatAvuy8888: return "0x59555641" case ShmFormatXvuy8888: return "0x59555658" case ShmFormatP030: return "0x30333050" default: return "" } } func (e ShmFormat) String() string { return e.Name() + "=" + e.Value() } // ShmFormatEvent : pixel format description // // Informs the client about a valid pixel format that // can be used for buffers. Known formats include // argb8888 and xrgb8888. type ShmFormatEvent struct { Format uint32 } type ShmFormatHandlerFunc func(ShmFormatEvent) // SetFormatHandler : sets handler for ShmFormatEvent func (i *Shm) SetFormatHandler(f ShmFormatHandlerFunc) { i.formatHandler = f } func (i *Shm) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.formatHandler == nil { return } var e ShmFormatEvent l := 0 e.Format = Uint32(data[l : l+4]) l += 4 i.formatHandler(e) } } // BufferInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const BufferInterfaceName = "wl_buffer" // Buffer : content for a wl_surface // // A buffer provides the content for a wl_surface. Buffers are // created through factory interfaces such as wl_shm, wp_linux_buffer_params // (from the linux-dmabuf protocol extension) or similar. It has a width and // a height and can be attached to a wl_surface, but the mechanism by which a // client provides and updates the contents is defined by the buffer factory // interface. // // Color channels are assumed to be electrical rather than optical (in other // words, encoded with a transfer function) unless otherwise specified. If // the buffer uses a format that has an alpha channel, the alpha channel is // assumed to be premultiplied into the electrical color channel values // (after transfer function encoding) unless otherwise specified. // // Note, because wl_buffer objects are created from multiple independent // factory interfaces, the wl_buffer interface is frozen at version 1. type Buffer struct { BaseProxy releaseHandler BufferReleaseHandlerFunc } // NewBuffer : content for a wl_surface // // A buffer provides the content for a wl_surface. Buffers are // created through factory interfaces such as wl_shm, wp_linux_buffer_params // (from the linux-dmabuf protocol extension) or similar. It has a width and // a height and can be attached to a wl_surface, but the mechanism by which a // client provides and updates the contents is defined by the buffer factory // interface. // // Color channels are assumed to be electrical rather than optical (in other // words, encoded with a transfer function) unless otherwise specified. If // the buffer uses a format that has an alpha channel, the alpha channel is // assumed to be premultiplied into the electrical color channel values // (after transfer function encoding) unless otherwise specified. // // Note, because wl_buffer objects are created from multiple independent // factory interfaces, the wl_buffer interface is frozen at version 1. func NewBuffer(ctx *Context) *Buffer { wlBuffer := &Buffer{} ctx.Register(wlBuffer) return wlBuffer } // Destroy : destroy a buffer // // Destroy a buffer. If and how you need to release the backing // storage is defined by the buffer factory interface. // // For possible side-effects to a surface, see wl_surface.attach. func (i *Buffer) Destroy() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // BufferReleaseEvent : compositor releases buffer // // Sent when this wl_buffer is no longer used by the compositor. // // For more information on when release events may or may not be sent, // and what consequences it has, please see the description of // wl_surface.attach. // // If a client receives a release event before the frame callback // requested in the same wl_surface.commit that attaches this // wl_buffer to a surface, then the client is immediately free to // reuse the buffer and its backing storage, and does not need a // second buffer for the next surface content update. Typically // this is possible, when the compositor maintains a copy of the // wl_surface contents, e.g. as a GL texture. This is an important // optimization for GL(ES) compositors with wl_shm clients. type BufferReleaseEvent struct{} type BufferReleaseHandlerFunc func(BufferReleaseEvent) // SetReleaseHandler : sets handler for BufferReleaseEvent func (i *Buffer) SetReleaseHandler(f BufferReleaseHandlerFunc) { i.releaseHandler = f } func (i *Buffer) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.releaseHandler == nil { return } var e BufferReleaseEvent i.releaseHandler(e) } } // DataOfferInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const DataOfferInterfaceName = "wl_data_offer" // DataOffer : offer to transfer data // // A wl_data_offer represents a piece of data offered for transfer // by another client (the source client). It is used by the // copy-and-paste and drag-and-drop mechanisms. The offer // describes the different mime types that the data can be // converted to and provides the mechanism for transferring the // data directly from the source client. type DataOffer struct { BaseProxy offerHandler DataOfferOfferHandlerFunc sourceActionsHandler DataOfferSourceActionsHandlerFunc actionHandler DataOfferActionHandlerFunc } // NewDataOffer : offer to transfer data // // A wl_data_offer represents a piece of data offered for transfer // by another client (the source client). It is used by the // copy-and-paste and drag-and-drop mechanisms. The offer // describes the different mime types that the data can be // converted to and provides the mechanism for transferring the // data directly from the source client. func NewDataOffer(ctx *Context) *DataOffer { wlDataOffer := &DataOffer{} ctx.Register(wlDataOffer) return wlDataOffer } // Accept : accept one of the offered mime types // // Indicate that the client can accept the given mime type, or // NULL for not accepted. // // For objects of version 2 or older, this request is used by the // client to give feedback whether the client can receive the given // mime type, or NULL if none is accepted; the feedback does not // determine whether the drag-and-drop operation succeeds or not. // // For objects of version 3 or newer, this request determines the // final result of the drag-and-drop operation. If the end result // is that no mime types were accepted, the drag-and-drop operation // will be cancelled and the corresponding drag source will receive // wl_data_source.cancelled. Clients may still use this event in // conjunction with wl_data_source.action for feedback. // // serial: serial number of the accept request // mimeType: mime type accepted by the client func (i *DataOffer) Accept(serial uint32, mimeType string) error { const opcode = 0 mimeTypeLen := PaddedLen(len(mimeType) + 1) _reqBufLen := 8 + 4 + (4 + mimeTypeLen) _reqBuf := make([]byte, _reqBufLen) l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 PutString(_reqBuf[l:l+(4+mimeTypeLen)], mimeType) l += (4 + mimeTypeLen) err := i.Context().WriteMsg(_reqBuf, nil) return err } // Receive : request that the data is transferred // // To transfer the offered data, the client issues this request // and indicates the mime type it wants to receive. The transfer // happens through the passed file descriptor (typically created // with the pipe system call). The source client writes the data // in the mime type representation requested and then closes the // file descriptor. // // The receiving client reads from the read end of the pipe until // EOF and then closes its end, at which point the transfer is // complete. // // This request may happen multiple times for different mime types, // both before and after wl_data_device.drop. Drag-and-drop destination // clients may preemptively fetch data or examine it more closely to // determine acceptance. // // mimeType: mime type desired by receiver // fd: file descriptor for data transfer func (i *DataOffer) Receive(mimeType string, fd int) error { const opcode = 1 mimeTypeLen := PaddedLen(len(mimeType) + 1) _reqBufLen := 8 + (4 + mimeTypeLen) _reqBuf := make([]byte, _reqBufLen) l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutString(_reqBuf[l:l+(4+mimeTypeLen)], mimeType) l += (4 + mimeTypeLen) oob := unix.UnixRights(int(fd)) err := i.Context().WriteMsg(_reqBuf, oob) return err } // Destroy : destroy data offer // // Destroy the data offer. func (i *DataOffer) Destroy() error { defer i.MarkZombie() const opcode = 2 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Finish : the offer will no longer be used // // Notifies the compositor that the drag destination successfully // finished the drag-and-drop operation. // // Upon receiving this request, the compositor will emit // wl_data_source.dnd_finished on the drag source client. // // It is a client error to perform other requests than // wl_data_offer.destroy after this one. It is also an error to perform // this request after a NULL mime type has been set in // wl_data_offer.accept or no action was received through // wl_data_offer.action. // // If wl_data_offer.finish request is received for a non drag and drop // operation, the invalid_finish protocol error is raised. func (i *DataOffer) Finish() error { const opcode = 3 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetActions : set the available/preferred drag-and-drop actions // // Sets the actions that the destination side client supports for // this operation. This request may trigger the emission of // wl_data_source.action and wl_data_offer.action events if the compositor // needs to change the selected action. // // This request can be called multiple times throughout the // drag-and-drop operation, typically in response to wl_data_device.enter // or wl_data_device.motion events. // // This request determines the final result of the drag-and-drop // operation. If the end result is that no action is accepted, // the drag source will receive wl_data_source.cancelled. // // The dnd_actions argument must contain only values expressed in the // wl_data_device_manager.dnd_actions enum, and the preferred_action // argument must only contain one of those values set, otherwise it // will result in a protocol error. // // While managing an "ask" action, the destination drag-and-drop client // may perform further wl_data_offer.receive requests, and is expected // to perform one last wl_data_offer.set_actions request with a preferred // action other than "ask" (and optionally wl_data_offer.accept) before // requesting wl_data_offer.finish, in order to convey the action selected // by the user. If the preferred action is not in the // wl_data_offer.source_actions mask, an error will be raised. // // If the "ask" action is dismissed (e.g. user cancellation), the client // is expected to perform wl_data_offer.destroy right away. // // This request can only be made on drag-and-drop offers, a protocol error // will be raised otherwise. // // dndActions: actions supported by the destination client // preferredAction: action preferred by the destination client func (i *DataOffer) SetActions(dndActions, preferredAction uint32) error { const opcode = 4 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(dndActions)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(preferredAction)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type DataOfferError uint32 // DataOfferError : const ( // DataOfferErrorInvalidFinish : finish request was called untimely DataOfferErrorInvalidFinish DataOfferError = 0 // DataOfferErrorInvalidActionMask : action mask contains invalid values DataOfferErrorInvalidActionMask DataOfferError = 1 // DataOfferErrorInvalidAction : action argument has an invalid value DataOfferErrorInvalidAction DataOfferError = 2 // DataOfferErrorInvalidOffer : offer doesn't accept this request DataOfferErrorInvalidOffer DataOfferError = 3 ) func (e DataOfferError) Name() string { switch e { case DataOfferErrorInvalidFinish: return "invalid_finish" case DataOfferErrorInvalidActionMask: return "invalid_action_mask" case DataOfferErrorInvalidAction: return "invalid_action" case DataOfferErrorInvalidOffer: return "invalid_offer" default: return "" } } func (e DataOfferError) Value() string { switch e { case DataOfferErrorInvalidFinish: return "0" case DataOfferErrorInvalidActionMask: return "1" case DataOfferErrorInvalidAction: return "2" case DataOfferErrorInvalidOffer: return "3" default: return "" } } func (e DataOfferError) String() string { return e.Name() + "=" + e.Value() } // DataOfferOfferEvent : advertise offered mime type // // Sent immediately after creating the wl_data_offer object. One // event per offered mime type. type DataOfferOfferEvent struct { MimeType string } type DataOfferOfferHandlerFunc func(DataOfferOfferEvent) // SetOfferHandler : sets handler for DataOfferOfferEvent func (i *DataOffer) SetOfferHandler(f DataOfferOfferHandlerFunc) { i.offerHandler = f } // DataOfferSourceActionsEvent : notify the source-side available actions // // This event indicates the actions offered by the data source. It // will be sent immediately after creating the wl_data_offer object, // or anytime the source side changes its offered actions through // wl_data_source.set_actions. type DataOfferSourceActionsEvent struct { SourceActions uint32 } type DataOfferSourceActionsHandlerFunc func(DataOfferSourceActionsEvent) // SetSourceActionsHandler : sets handler for DataOfferSourceActionsEvent func (i *DataOffer) SetSourceActionsHandler(f DataOfferSourceActionsHandlerFunc) { i.sourceActionsHandler = f } // DataOfferActionEvent : notify the selected action // // This event indicates the action selected by the compositor after // matching the source/destination side actions. Only one action (or // none) will be offered here. // // This event can be emitted multiple times during the drag-and-drop // operation in response to destination side action changes through // wl_data_offer.set_actions. // // This event will no longer be emitted after wl_data_device.drop // happened on the drag-and-drop destination, the client must // honor the last action received, or the last preferred one set // through wl_data_offer.set_actions when handling an "ask" action. // // Compositors may also change the selected action on the fly, mainly // in response to keyboard modifier changes during the drag-and-drop // operation. // // The most recent action received is always the valid one. Prior to // receiving wl_data_device.drop, the chosen action may change (e.g. // due to keyboard modifiers being pressed). At the time of receiving // wl_data_device.drop the drag-and-drop destination must honor the // last action received. // // Action changes may still happen after wl_data_device.drop, // especially on "ask" actions, where the drag-and-drop destination // may choose another action afterwards. Action changes happening // at this stage are always the result of inter-client negotiation, the // compositor shall no longer be able to induce a different action. // // Upon "ask" actions, it is expected that the drag-and-drop destination // may potentially choose a different action and/or mime type, // based on wl_data_offer.source_actions and finally chosen by the // user (e.g. popping up a menu with the available options). The // final wl_data_offer.set_actions and wl_data_offer.accept requests // must happen before the call to wl_data_offer.finish. type DataOfferActionEvent struct { DndAction uint32 } type DataOfferActionHandlerFunc func(DataOfferActionEvent) // SetActionHandler : sets handler for DataOfferActionEvent func (i *DataOffer) SetActionHandler(f DataOfferActionHandlerFunc) { i.actionHandler = f } func (i *DataOffer) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.offerHandler == nil { return } var e DataOfferOfferEvent l := 0 mimeTypeLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.MimeType = String(data[l : l+mimeTypeLen]) l += mimeTypeLen i.offerHandler(e) case 1: if i.sourceActionsHandler == nil { return } var e DataOfferSourceActionsEvent l := 0 e.SourceActions = Uint32(data[l : l+4]) l += 4 i.sourceActionsHandler(e) case 2: if i.actionHandler == nil { return } var e DataOfferActionEvent l := 0 e.DndAction = Uint32(data[l : l+4]) l += 4 i.actionHandler(e) } } // DataSourceInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const DataSourceInterfaceName = "wl_data_source" // DataSource : offer to transfer data // // The wl_data_source object is the source side of a wl_data_offer. // It is created by the source client in a data transfer and // provides a way to describe the offered data and a way to respond // to requests to transfer the data. type DataSource struct { BaseProxy targetHandler DataSourceTargetHandlerFunc sendHandler DataSourceSendHandlerFunc cancelledHandler DataSourceCancelledHandlerFunc dndDropPerformedHandler DataSourceDndDropPerformedHandlerFunc dndFinishedHandler DataSourceDndFinishedHandlerFunc actionHandler DataSourceActionHandlerFunc } // NewDataSource : offer to transfer data // // The wl_data_source object is the source side of a wl_data_offer. // It is created by the source client in a data transfer and // provides a way to describe the offered data and a way to respond // to requests to transfer the data. func NewDataSource(ctx *Context) *DataSource { wlDataSource := &DataSource{} ctx.Register(wlDataSource) return wlDataSource } // Offer : add an offered mime type // // This request adds a mime type to the set of mime types // advertised to targets. Can be called several times to offer // multiple types. // // mimeType: mime type offered by the data source func (i *DataSource) Offer(mimeType string) error { const opcode = 0 mimeTypeLen := PaddedLen(len(mimeType) + 1) _reqBufLen := 8 + (4 + mimeTypeLen) _reqBuf := make([]byte, _reqBufLen) l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutString(_reqBuf[l:l+(4+mimeTypeLen)], mimeType) l += (4 + mimeTypeLen) err := i.Context().WriteMsg(_reqBuf, nil) return err } // Destroy : destroy the data source // // Destroy the data source. func (i *DataSource) Destroy() error { defer i.MarkZombie() const opcode = 1 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetActions : set the available drag-and-drop actions // // Sets the actions that the source side client supports for this // operation. This request may trigger wl_data_source.action and // wl_data_offer.action events if the compositor needs to change the // selected action. // // The dnd_actions argument must contain only values expressed in the // wl_data_device_manager.dnd_actions enum, otherwise it will result // in a protocol error. // // This request must be made once only, and can only be made on sources // used in drag-and-drop, so it must be performed before // wl_data_device.start_drag. Attempting to use the source other than // for drag-and-drop will raise a protocol error. // // dndActions: actions supported by the data source func (i *DataSource) SetActions(dndActions uint32) error { const opcode = 2 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(dndActions)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type DataSourceError uint32 // DataSourceError : const ( // DataSourceErrorInvalidActionMask : action mask contains invalid values DataSourceErrorInvalidActionMask DataSourceError = 0 // DataSourceErrorInvalidSource : source doesn't accept this request DataSourceErrorInvalidSource DataSourceError = 1 ) func (e DataSourceError) Name() string { switch e { case DataSourceErrorInvalidActionMask: return "invalid_action_mask" case DataSourceErrorInvalidSource: return "invalid_source" default: return "" } } func (e DataSourceError) Value() string { switch e { case DataSourceErrorInvalidActionMask: return "0" case DataSourceErrorInvalidSource: return "1" default: return "" } } func (e DataSourceError) String() string { return e.Name() + "=" + e.Value() } // DataSourceTargetEvent : a target accepts an offered mime type // // Sent when a target accepts pointer_focus or motion events. If // a target does not accept any of the offered types, type is NULL. // // Used for feedback during drag-and-drop. type DataSourceTargetEvent struct { MimeType string } type DataSourceTargetHandlerFunc func(DataSourceTargetEvent) // SetTargetHandler : sets handler for DataSourceTargetEvent func (i *DataSource) SetTargetHandler(f DataSourceTargetHandlerFunc) { i.targetHandler = f } // DataSourceSendEvent : send the data // // Request for data from the client. Send the data as the // specified mime type over the passed file descriptor, then // close it. type DataSourceSendEvent struct { MimeType string Fd int } type DataSourceSendHandlerFunc func(DataSourceSendEvent) // SetSendHandler : sets handler for DataSourceSendEvent func (i *DataSource) SetSendHandler(f DataSourceSendHandlerFunc) { i.sendHandler = f } // DataSourceCancelledEvent : selection was cancelled // // This data source is no longer valid. There are several reasons why // this could happen: // // - The data source has been replaced by another data source. // - The drag-and-drop operation was performed, but the drop destination // did not accept any of the mime types offered through // wl_data_source.target. // - The drag-and-drop operation was performed, but the drop destination // did not select any of the actions present in the mask offered through // wl_data_source.action. // - The drag-and-drop operation was performed but didn't happen over a // surface. // - The compositor cancelled the drag-and-drop operation (e.g. compositor // dependent timeouts to avoid stale drag-and-drop transfers). // // The client should clean up and destroy this data source. // // For objects of version 2 or older, wl_data_source.cancelled will // only be emitted if the data source was replaced by another data // source. type DataSourceCancelledEvent struct{} type DataSourceCancelledHandlerFunc func(DataSourceCancelledEvent) // SetCancelledHandler : sets handler for DataSourceCancelledEvent func (i *DataSource) SetCancelledHandler(f DataSourceCancelledHandlerFunc) { i.cancelledHandler = f } // DataSourceDndDropPerformedEvent : the drag-and-drop operation physically finished // // The user performed the drop action. This event does not indicate // acceptance, wl_data_source.cancelled may still be emitted afterwards // if the drop destination does not accept any mime type. // // However, this event might however not be received if the compositor // cancelled the drag-and-drop operation before this event could happen. // // Note that the data_source may still be used in the future and should // not be destroyed here. type DataSourceDndDropPerformedEvent struct{} type DataSourceDndDropPerformedHandlerFunc func(DataSourceDndDropPerformedEvent) // SetDndDropPerformedHandler : sets handler for DataSourceDndDropPerformedEvent func (i *DataSource) SetDndDropPerformedHandler(f DataSourceDndDropPerformedHandlerFunc) { i.dndDropPerformedHandler = f } // DataSourceDndFinishedEvent : the drag-and-drop operation concluded // // The drop destination finished interoperating with this data // source, so the client is now free to destroy this data source and // free all associated data. // // If the action used to perform the operation was "move", the // source can now delete the transferred data. type DataSourceDndFinishedEvent struct{} type DataSourceDndFinishedHandlerFunc func(DataSourceDndFinishedEvent) // SetDndFinishedHandler : sets handler for DataSourceDndFinishedEvent func (i *DataSource) SetDndFinishedHandler(f DataSourceDndFinishedHandlerFunc) { i.dndFinishedHandler = f } // DataSourceActionEvent : notify the selected action // // This event indicates the action selected by the compositor after // matching the source/destination side actions. Only one action (or // none) will be offered here. // // This event can be emitted multiple times during the drag-and-drop // operation, mainly in response to destination side changes through // wl_data_offer.set_actions, and as the data device enters/leaves // surfaces. // // It is only possible to receive this event after // wl_data_source.dnd_drop_performed if the drag-and-drop operation // ended in an "ask" action, in which case the final wl_data_source.action // event will happen immediately before wl_data_source.dnd_finished. // // Compositors may also change the selected action on the fly, mainly // in response to keyboard modifier changes during the drag-and-drop // operation. // // The most recent action received is always the valid one. The chosen // action may change alongside negotiation (e.g. an "ask" action can turn // into a "move" operation), so the effects of the final action must // always be applied in wl_data_offer.dnd_finished. // // Clients can trigger cursor surface changes from this point, so // they reflect the current action. type DataSourceActionEvent struct { DndAction uint32 } type DataSourceActionHandlerFunc func(DataSourceActionEvent) // SetActionHandler : sets handler for DataSourceActionEvent func (i *DataSource) SetActionHandler(f DataSourceActionHandlerFunc) { i.actionHandler = f } func (i *DataSource) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.targetHandler == nil { return } var e DataSourceTargetEvent l := 0 mimeTypeLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.MimeType = String(data[l : l+mimeTypeLen]) l += mimeTypeLen i.targetHandler(e) case 1: if i.sendHandler == nil { if fd != -1 { unix.Close(fd) } return } var e DataSourceSendEvent l := 0 mimeTypeLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.MimeType = String(data[l : l+mimeTypeLen]) l += mimeTypeLen e.Fd = fd i.sendHandler(e) case 2: if i.cancelledHandler == nil { return } var e DataSourceCancelledEvent i.cancelledHandler(e) case 3: if i.dndDropPerformedHandler == nil { return } var e DataSourceDndDropPerformedEvent i.dndDropPerformedHandler(e) case 4: if i.dndFinishedHandler == nil { return } var e DataSourceDndFinishedEvent i.dndFinishedHandler(e) case 5: if i.actionHandler == nil { return } var e DataSourceActionEvent l := 0 e.DndAction = Uint32(data[l : l+4]) l += 4 i.actionHandler(e) } } // DataDeviceInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const DataDeviceInterfaceName = "wl_data_device" // DataDevice : data transfer device // // There is one wl_data_device per seat which can be obtained // from the global wl_data_device_manager singleton. // // A wl_data_device provides access to inter-client data transfer // mechanisms such as copy-and-paste and drag-and-drop. type DataDevice struct { BaseProxy dataOfferHandler DataDeviceDataOfferHandlerFunc enterHandler DataDeviceEnterHandlerFunc leaveHandler DataDeviceLeaveHandlerFunc motionHandler DataDeviceMotionHandlerFunc dropHandler DataDeviceDropHandlerFunc selectionHandler DataDeviceSelectionHandlerFunc } // NewDataDevice : data transfer device // // There is one wl_data_device per seat which can be obtained // from the global wl_data_device_manager singleton. // // A wl_data_device provides access to inter-client data transfer // mechanisms such as copy-and-paste and drag-and-drop. func NewDataDevice(ctx *Context) *DataDevice { wlDataDevice := &DataDevice{} ctx.Register(wlDataDevice) return wlDataDevice } // StartDrag : start drag-and-drop operation // // This request asks the compositor to start a drag-and-drop // operation on behalf of the client. // // The source argument is the data source that provides the data // for the eventual data transfer. If source is NULL, enter, leave // and motion events are sent only to the client that initiated the // drag and the client is expected to handle the data passing // internally. If source is destroyed, the drag-and-drop session will be // cancelled. // // The origin surface is the surface where the drag originates and // the client must have an active implicit grab that matches the // serial. // // The icon surface is an optional (can be NULL) surface that // provides an icon to be moved around with the cursor. Initially, // the top-left corner of the icon surface is placed at the cursor // hotspot, but subsequent wl_surface.offset requests can move the // relative position. Attach requests must be confirmed with // wl_surface.commit as usual. The icon surface is given the role of // a drag-and-drop icon. If the icon surface already has another role, // it raises a protocol error. // // The input region is ignored for wl_surfaces with the role of a // drag-and-drop icon. // // The given source may not be used in any further set_selection or // start_drag requests. Attempting to reuse a previously-used source // may send a used_source error. // // source: data source for the eventual transfer // origin: surface where the drag originates // icon: drag-and-drop icon surface // serial: serial number of the implicit grab on the origin func (i *DataDevice) StartDrag(source *DataSource, origin, icon *Surface, serial uint32) error { const opcode = 0 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 if source == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], source.ID()) l += 4 } PutUint32(_reqBuf[l:l+4], origin.ID()) l += 4 if icon == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], icon.ID()) l += 4 } PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetSelection : copy data to the selection // // This request asks the compositor to set the selection // to the data from the source on behalf of the client. // // To unset the selection, set the source to NULL. // // The given source may not be used in any further set_selection or // start_drag requests. Attempting to reuse a previously-used source // may send a used_source error. // // source: data source for the selection // serial: serial number of the event that triggered this request func (i *DataDevice) SetSelection(source *DataSource, serial uint32) error { const opcode = 1 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 if source == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], source.ID()) l += 4 } PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Release : destroy data device // // This request destroys the data device. func (i *DataDevice) Release() error { defer i.MarkZombie() const opcode = 2 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type DataDeviceError uint32 // DataDeviceError : const ( // DataDeviceErrorRole : given wl_surface has another role DataDeviceErrorRole DataDeviceError = 0 // DataDeviceErrorUsedSource : source has already been used DataDeviceErrorUsedSource DataDeviceError = 1 ) func (e DataDeviceError) Name() string { switch e { case DataDeviceErrorRole: return "role" case DataDeviceErrorUsedSource: return "used_source" default: return "" } } func (e DataDeviceError) Value() string { switch e { case DataDeviceErrorRole: return "0" case DataDeviceErrorUsedSource: return "1" default: return "" } } func (e DataDeviceError) String() string { return e.Name() + "=" + e.Value() } // DataDeviceDataOfferEvent : introduce a new wl_data_offer // // The data_offer event introduces a new wl_data_offer object, // which will subsequently be used in either the // data_device.enter event (for drag-and-drop) or the // data_device.selection event (for selections). Immediately // following the data_device.data_offer event, the new data_offer // object will send out data_offer.offer events to describe the // mime types it offers. type DataDeviceDataOfferEvent struct { Id *DataOffer } type DataDeviceDataOfferHandlerFunc func(DataDeviceDataOfferEvent) // SetDataOfferHandler : sets handler for DataDeviceDataOfferEvent func (i *DataDevice) SetDataOfferHandler(f DataDeviceDataOfferHandlerFunc) { i.dataOfferHandler = f } // DataDeviceEnterEvent : initiate drag-and-drop session // // This event is sent when an active drag-and-drop pointer enters // a surface owned by the client. The position of the pointer at // enter time is provided by the x and y arguments, in surface-local // coordinates. type DataDeviceEnterEvent struct { Serial uint32 Surface *Surface X float64 Y float64 Id *DataOffer } type DataDeviceEnterHandlerFunc func(DataDeviceEnterEvent) // SetEnterHandler : sets handler for DataDeviceEnterEvent func (i *DataDevice) SetEnterHandler(f DataDeviceEnterHandlerFunc) { i.enterHandler = f } // DataDeviceLeaveEvent : end drag-and-drop session // // This event is sent when the drag-and-drop pointer leaves the // surface and the session ends. The client must destroy the // wl_data_offer introduced at enter time at this point. type DataDeviceLeaveEvent struct{} type DataDeviceLeaveHandlerFunc func(DataDeviceLeaveEvent) // SetLeaveHandler : sets handler for DataDeviceLeaveEvent func (i *DataDevice) SetLeaveHandler(f DataDeviceLeaveHandlerFunc) { i.leaveHandler = f } // DataDeviceMotionEvent : drag-and-drop session motion // // This event is sent when the drag-and-drop pointer moves within // the currently focused surface. The new position of the pointer // is provided by the x and y arguments, in surface-local // coordinates. type DataDeviceMotionEvent struct { Time uint32 X float64 Y float64 } type DataDeviceMotionHandlerFunc func(DataDeviceMotionEvent) // SetMotionHandler : sets handler for DataDeviceMotionEvent func (i *DataDevice) SetMotionHandler(f DataDeviceMotionHandlerFunc) { i.motionHandler = f } // DataDeviceDropEvent : end drag-and-drop session successfully // // The event is sent when a drag-and-drop operation is ended // because the implicit grab is removed. // // The drag-and-drop destination is expected to honor the last action // received through wl_data_offer.action, if the resulting action is // "copy" or "move", the destination can still perform // wl_data_offer.receive requests, and is expected to end all // transfers with a wl_data_offer.finish request. // // If the resulting action is "ask", the action will not be considered // final. The drag-and-drop destination is expected to perform one last // wl_data_offer.set_actions request, or wl_data_offer.destroy in order // to cancel the operation. type DataDeviceDropEvent struct{} type DataDeviceDropHandlerFunc func(DataDeviceDropEvent) // SetDropHandler : sets handler for DataDeviceDropEvent func (i *DataDevice) SetDropHandler(f DataDeviceDropHandlerFunc) { i.dropHandler = f } // DataDeviceSelectionEvent : advertise new selection // // The selection event is sent out to notify the client of a new // wl_data_offer for the selection for this device. The // data_device.data_offer and the data_offer.offer events are // sent out immediately before this event to introduce the data // offer object. The selection event is sent to a client // immediately before receiving keyboard focus and when a new // selection is set while the client has keyboard focus. The // data_offer is valid until a new data_offer or NULL is received // or until the client loses keyboard focus. Switching surface with // keyboard focus within the same client doesn't mean a new selection // will be sent. The client must destroy the previous selection // data_offer, if any, upon receiving this event. type DataDeviceSelectionEvent struct { Id *DataOffer } type DataDeviceSelectionHandlerFunc func(DataDeviceSelectionEvent) // SetSelectionHandler : sets handler for DataDeviceSelectionEvent func (i *DataDevice) SetSelectionHandler(f DataDeviceSelectionHandlerFunc) { i.selectionHandler = f } func (i *DataDevice) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.dataOfferHandler == nil { return } var e DataDeviceDataOfferEvent l := 0 e.Id = i.Context().GetProxy(Uint32(data[l : l+4])).(*DataOffer) l += 4 i.dataOfferHandler(e) case 1: if i.enterHandler == nil { return } var e DataDeviceEnterEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Surface = i.Context().GetProxy(Uint32(data[l : l+4])).(*Surface) l += 4 e.X = Fixed(data[l : l+4]) l += 4 e.Y = Fixed(data[l : l+4]) l += 4 e.Id = i.Context().GetProxy(Uint32(data[l : l+4])).(*DataOffer) l += 4 i.enterHandler(e) case 2: if i.leaveHandler == nil { return } var e DataDeviceLeaveEvent i.leaveHandler(e) case 3: if i.motionHandler == nil { return } var e DataDeviceMotionEvent l := 0 e.Time = Uint32(data[l : l+4]) l += 4 e.X = Fixed(data[l : l+4]) l += 4 e.Y = Fixed(data[l : l+4]) l += 4 i.motionHandler(e) case 4: if i.dropHandler == nil { return } var e DataDeviceDropEvent i.dropHandler(e) case 5: if i.selectionHandler == nil { return } var e DataDeviceSelectionEvent l := 0 e.Id = i.Context().GetProxy(Uint32(data[l : l+4])).(*DataOffer) l += 4 i.selectionHandler(e) } } // DataDeviceManagerInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const DataDeviceManagerInterfaceName = "wl_data_device_manager" // DataDeviceManager : data transfer interface // // The wl_data_device_manager is a singleton global object that // provides access to inter-client data transfer mechanisms such as // copy-and-paste and drag-and-drop. These mechanisms are tied to // a wl_seat and this interface lets a client get a wl_data_device // corresponding to a wl_seat. // // Depending on the version bound, the objects created from the bound // wl_data_device_manager object will have different requirements for // functioning properly. See wl_data_source.set_actions, // wl_data_offer.accept and wl_data_offer.finish for details. type DataDeviceManager struct { BaseProxy } // NewDataDeviceManager : data transfer interface // // The wl_data_device_manager is a singleton global object that // provides access to inter-client data transfer mechanisms such as // copy-and-paste and drag-and-drop. These mechanisms are tied to // a wl_seat and this interface lets a client get a wl_data_device // corresponding to a wl_seat. // // Depending on the version bound, the objects created from the bound // wl_data_device_manager object will have different requirements for // functioning properly. See wl_data_source.set_actions, // wl_data_offer.accept and wl_data_offer.finish for details. func NewDataDeviceManager(ctx *Context) *DataDeviceManager { wlDataDeviceManager := &DataDeviceManager{} ctx.Register(wlDataDeviceManager) return wlDataDeviceManager } // CreateDataSource : create a new data source // // Create a new data source. func (i *DataDeviceManager) CreateDataSource() (*DataSource, error) { id := NewDataSource(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } // GetDataDevice : create a new data device // // Create a new data device for a given seat. // // seat: seat associated with the data device func (i *DataDeviceManager) GetDataDevice(seat *Seat) (*DataDevice, error) { id := NewDataDevice(i.Context()) const opcode = 1 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 PutUint32(_reqBuf[l:l+4], seat.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } func (i *DataDeviceManager) Destroy() error { i.MarkZombie() return nil } type DataDeviceManagerDndAction uint32 // DataDeviceManagerDndAction : drag and drop actions // // This is a bitmask of the available/preferred actions in a // drag-and-drop operation. // // In the compositor, the selected action is a result of matching the // actions offered by the source and destination sides. "action" events // with a "none" action will be sent to both source and destination if // there is no match. All further checks will effectively happen on // (source actions ∩ destination actions). // // In addition, compositors may also pick different actions in // reaction to key modifiers being pressed. One common design that // is used in major toolkits (and the behavior recommended for // compositors) is: // // - If no modifiers are pressed, the first match (in bit order) // will be used. // - Pressing Shift selects "move", if enabled in the mask. // - Pressing Control selects "copy", if enabled in the mask. // // Behavior beyond that is considered implementation-dependent. // Compositors may for example bind other modifiers (like Alt/Meta) // or drags initiated with other buttons than BTN_LEFT to specific // actions (e.g. "ask"). const ( // DataDeviceManagerDndActionNone : no action DataDeviceManagerDndActionNone DataDeviceManagerDndAction = 0 // DataDeviceManagerDndActionCopy : copy action DataDeviceManagerDndActionCopy DataDeviceManagerDndAction = 1 // DataDeviceManagerDndActionMove : move action DataDeviceManagerDndActionMove DataDeviceManagerDndAction = 2 // DataDeviceManagerDndActionAsk : ask action DataDeviceManagerDndActionAsk DataDeviceManagerDndAction = 4 ) func (e DataDeviceManagerDndAction) Name() string { switch e { case DataDeviceManagerDndActionNone: return "none" case DataDeviceManagerDndActionCopy: return "copy" case DataDeviceManagerDndActionMove: return "move" case DataDeviceManagerDndActionAsk: return "ask" default: return "" } } func (e DataDeviceManagerDndAction) Value() string { switch e { case DataDeviceManagerDndActionNone: return "0" case DataDeviceManagerDndActionCopy: return "1" case DataDeviceManagerDndActionMove: return "2" case DataDeviceManagerDndActionAsk: return "4" default: return "" } } func (e DataDeviceManagerDndAction) String() string { return e.Name() + "=" + e.Value() } // ShellInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const ShellInterfaceName = "wl_shell" // Shell : create desktop-style surfaces // // This interface is implemented by servers that provide // desktop-style user interfaces. // // It allows clients to associate a wl_shell_surface with // a basic surface. // // Note! This protocol is deprecated and not intended for production use. // For desktop-style user interfaces, use xdg_shell. Compositors and clients // should not implement this interface. type Shell struct { BaseProxy } // NewShell : create desktop-style surfaces // // This interface is implemented by servers that provide // desktop-style user interfaces. // // It allows clients to associate a wl_shell_surface with // a basic surface. // // Note! This protocol is deprecated and not intended for production use. // For desktop-style user interfaces, use xdg_shell. Compositors and clients // should not implement this interface. func NewShell(ctx *Context) *Shell { wlShell := &Shell{} ctx.Register(wlShell) return wlShell } // GetShellSurface : create a shell surface from a surface // // Create a shell surface for an existing surface. This gives // the wl_surface the role of a shell surface. If the wl_surface // already has another role, it raises a protocol error. // // Only one shell surface can be associated with a given surface. // // surface: surface to be given the shell surface role func (i *Shell) GetShellSurface(surface *Surface) (*ShellSurface, error) { id := NewShellSurface(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 PutUint32(_reqBuf[l:l+4], surface.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } func (i *Shell) Destroy() error { i.MarkZombie() return nil } type ShellError uint32 // ShellError : const ( // ShellErrorRole : given wl_surface has another role ShellErrorRole ShellError = 0 ) func (e ShellError) Name() string { switch e { case ShellErrorRole: return "role" default: return "" } } func (e ShellError) Value() string { switch e { case ShellErrorRole: return "0" default: return "" } } func (e ShellError) String() string { return e.Name() + "=" + e.Value() } // ShellSurfaceInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const ShellSurfaceInterfaceName = "wl_shell_surface" // ShellSurface : desktop-style metadata interface // // An interface that may be implemented by a wl_surface, for // implementations that provide a desktop-style user interface. // // It provides requests to treat surfaces like toplevel, fullscreen // or popup windows, move, resize or maximize them, associate // metadata like title and class, etc. // // On the server side the object is automatically destroyed when // the related wl_surface is destroyed. On the client side, // wl_shell_surface_destroy() must be called before destroying // the wl_surface object. type ShellSurface struct { BaseProxy pingHandler ShellSurfacePingHandlerFunc configureHandler ShellSurfaceConfigureHandlerFunc popupDoneHandler ShellSurfacePopupDoneHandlerFunc } // NewShellSurface : desktop-style metadata interface // // An interface that may be implemented by a wl_surface, for // implementations that provide a desktop-style user interface. // // It provides requests to treat surfaces like toplevel, fullscreen // or popup windows, move, resize or maximize them, associate // metadata like title and class, etc. // // On the server side the object is automatically destroyed when // the related wl_surface is destroyed. On the client side, // wl_shell_surface_destroy() must be called before destroying // the wl_surface object. func NewShellSurface(ctx *Context) *ShellSurface { wlShellSurface := &ShellSurface{} ctx.Register(wlShellSurface) return wlShellSurface } // Pong : respond to a ping event // // A client must respond to a ping event with a pong request or // the client may be deemed unresponsive. // // serial: serial number of the ping event func (i *ShellSurface) Pong(serial uint32) error { const opcode = 0 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Move : start an interactive move // // Start a pointer-driven move of the surface. // // This request must be used in response to a button press event. // The server may ignore move requests depending on the state of // the surface (e.g. fullscreen or maximized). // // seat: seat whose pointer is used // serial: serial number of the implicit grab on the pointer func (i *ShellSurface) Move(seat *Seat, serial uint32) error { const opcode = 1 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], seat.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Resize : start an interactive resize // // Start a pointer-driven resizing of the surface. // // This request must be used in response to a button press event. // The server may ignore resize requests depending on the state of // the surface (e.g. fullscreen or maximized). // // seat: seat whose pointer is used // serial: serial number of the implicit grab on the pointer // edges: which edge or corner is being dragged func (i *ShellSurface) Resize(seat *Seat, serial, edges uint32) error { const opcode = 2 const _reqBufLen = 8 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], seat.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(edges)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetToplevel : make the surface a toplevel surface // // Map the surface as a toplevel surface. // // A toplevel surface is not fullscreen, maximized or transient. func (i *ShellSurface) SetToplevel() error { const opcode = 3 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetTransient : make the surface a transient surface // // Map the surface relative to an existing surface. // // The x and y arguments specify the location of the upper left // corner of the surface relative to the upper left corner of the // parent surface, in surface-local coordinates. // // The flags argument controls details of the transient behaviour. // // parent: parent surface // x: surface-local x coordinate // y: surface-local y coordinate // flags: transient surface behavior func (i *ShellSurface) SetTransient(parent *Surface, x, y int32, flags uint32) error { const opcode = 4 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], parent.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(flags)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetFullscreen : make the surface a fullscreen surface // // Map the surface as a fullscreen surface. // // If an output parameter is given then the surface will be made // fullscreen on that output. If the client does not specify the // output then the compositor will apply its policy - usually // choosing the output on which the surface has the biggest surface // area. // // The client may specify a method to resolve a size conflict // between the output size and the surface size - this is provided // through the method parameter. // // The framerate parameter is used only when the method is set // to "driver", to indicate the preferred framerate. A value of 0 // indicates that the client does not care about framerate. The // framerate is specified in mHz, that is framerate of 60000 is 60Hz. // // A method of "scale" or "driver" implies a scaling operation of // the surface, either via a direct scaling operation or a change of // the output mode. This will override any kind of output scaling, so // that mapping a surface with a buffer size equal to the mode can // fill the screen independent of buffer_scale. // // A method of "fill" means we don't scale up the buffer, however // any output scale is applied. This means that you may run into // an edge case where the application maps a buffer with the same // size of the output mode but buffer_scale 1 (thus making a // surface larger than the output). In this case it is allowed to // downscale the results to fit the screen. // // The compositor must reply to this request with a configure event // with the dimensions for the output on which the surface will // be made fullscreen. // // method: method for resolving size conflict // framerate: framerate in mHz // output: output on which the surface is to be fullscreen func (i *ShellSurface) SetFullscreen(method, framerate uint32, output *Output) error { const opcode = 5 const _reqBufLen = 8 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(method)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(framerate)) l += 4 if output == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], output.ID()) l += 4 } err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetPopup : make the surface a popup surface // // Map the surface as a popup. // // A popup surface is a transient surface with an added pointer // grab. // // An existing implicit grab will be changed to owner-events mode, // and the popup grab will continue after the implicit grab ends // (i.e. releasing the mouse button does not cause the popup to // be unmapped). // // The popup grab continues until the window is destroyed or a // mouse button is pressed in any other client's window. A click // in any of the client's surfaces is reported as normal, however, // clicks in other clients' surfaces will be discarded and trigger // the callback. // // The x and y arguments specify the location of the upper left // corner of the surface relative to the upper left corner of the // parent surface, in surface-local coordinates. // // seat: seat whose pointer is used // serial: serial number of the implicit grab on the pointer // parent: parent surface // x: surface-local x coordinate // y: surface-local y coordinate // flags: transient surface behavior func (i *ShellSurface) SetPopup(seat *Seat, serial uint32, parent *Surface, x, y int32, flags uint32) error { const opcode = 6 const _reqBufLen = 8 + 4 + 4 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], seat.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 PutUint32(_reqBuf[l:l+4], parent.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(flags)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetMaximized : make the surface a maximized surface // // Map the surface as a maximized surface. // // If an output parameter is given then the surface will be // maximized on that output. If the client does not specify the // output then the compositor will apply its policy - usually // choosing the output on which the surface has the biggest surface // area. // // The compositor will reply with a configure event telling // the expected new surface size. The operation is completed // on the next buffer attach to this surface. // // A maximized surface typically fills the entire output it is // bound to, except for desktop elements such as panels. This is // the main difference between a maximized shell surface and a // fullscreen shell surface. // // The details depend on the compositor implementation. // // output: output on which the surface is to be maximized func (i *ShellSurface) SetMaximized(output *Output) error { const opcode = 7 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 if output == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], output.ID()) l += 4 } err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetTitle : set surface title // // Set a short title for the surface. // // This string may be used to identify the surface in a task bar, // window list, or other user interface elements provided by the // compositor. // // The string must be encoded in UTF-8. // // title: surface title func (i *ShellSurface) SetTitle(title string) error { const opcode = 8 titleLen := PaddedLen(len(title) + 1) _reqBufLen := 8 + (4 + titleLen) _reqBuf := make([]byte, _reqBufLen) l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutString(_reqBuf[l:l+(4+titleLen)], title) l += (4 + titleLen) err := i.Context().WriteMsg(_reqBuf, nil) return err } // SetClass : set surface class // // Set a class for the surface. // // The surface class identifies the general class of applications // to which the surface belongs. A common convention is to use the // file name (or the full path if it is a non-standard location) of // the application's .desktop file as the class. // // class: surface class func (i *ShellSurface) SetClass(class string) error { const opcode = 9 classLen := PaddedLen(len(class) + 1) _reqBufLen := 8 + (4 + classLen) _reqBuf := make([]byte, _reqBufLen) l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutString(_reqBuf[l:l+(4+classLen)], class) l += (4 + classLen) err := i.Context().WriteMsg(_reqBuf, nil) return err } func (i *ShellSurface) Destroy() error { i.MarkZombie() return nil } type ShellSurfaceResize uint32 // ShellSurfaceResize : edge values for resizing // // These values are used to indicate which edge of a surface // is being dragged in a resize operation. The server may // use this information to adapt its behavior, e.g. choose // an appropriate cursor image. const ( // ShellSurfaceResizeNone : no edge ShellSurfaceResizeNone ShellSurfaceResize = 0 // ShellSurfaceResizeTop : top edge ShellSurfaceResizeTop ShellSurfaceResize = 1 // ShellSurfaceResizeBottom : bottom edge ShellSurfaceResizeBottom ShellSurfaceResize = 2 // ShellSurfaceResizeLeft : left edge ShellSurfaceResizeLeft ShellSurfaceResize = 4 // ShellSurfaceResizeTopLeft : top and left edges ShellSurfaceResizeTopLeft ShellSurfaceResize = 5 // ShellSurfaceResizeBottomLeft : bottom and left edges ShellSurfaceResizeBottomLeft ShellSurfaceResize = 6 // ShellSurfaceResizeRight : right edge ShellSurfaceResizeRight ShellSurfaceResize = 8 // ShellSurfaceResizeTopRight : top and right edges ShellSurfaceResizeTopRight ShellSurfaceResize = 9 // ShellSurfaceResizeBottomRight : bottom and right edges ShellSurfaceResizeBottomRight ShellSurfaceResize = 10 ) func (e ShellSurfaceResize) Name() string { switch e { case ShellSurfaceResizeNone: return "none" case ShellSurfaceResizeTop: return "top" case ShellSurfaceResizeBottom: return "bottom" case ShellSurfaceResizeLeft: return "left" case ShellSurfaceResizeTopLeft: return "top_left" case ShellSurfaceResizeBottomLeft: return "bottom_left" case ShellSurfaceResizeRight: return "right" case ShellSurfaceResizeTopRight: return "top_right" case ShellSurfaceResizeBottomRight: return "bottom_right" default: return "" } } func (e ShellSurfaceResize) Value() string { switch e { case ShellSurfaceResizeNone: return "0" case ShellSurfaceResizeTop: return "1" case ShellSurfaceResizeBottom: return "2" case ShellSurfaceResizeLeft: return "4" case ShellSurfaceResizeTopLeft: return "5" case ShellSurfaceResizeBottomLeft: return "6" case ShellSurfaceResizeRight: return "8" case ShellSurfaceResizeTopRight: return "9" case ShellSurfaceResizeBottomRight: return "10" default: return "" } } func (e ShellSurfaceResize) String() string { return e.Name() + "=" + e.Value() } type ShellSurfaceTransient uint32 // ShellSurfaceTransient : details of transient behaviour // // These flags specify details of the expected behaviour // of transient surfaces. Used in the set_transient request. const ( // ShellSurfaceTransientInactive : do not set keyboard focus ShellSurfaceTransientInactive ShellSurfaceTransient = 0x1 ) func (e ShellSurfaceTransient) Name() string { switch e { case ShellSurfaceTransientInactive: return "inactive" default: return "" } } func (e ShellSurfaceTransient) Value() string { switch e { case ShellSurfaceTransientInactive: return "0x1" default: return "" } } func (e ShellSurfaceTransient) String() string { return e.Name() + "=" + e.Value() } type ShellSurfaceFullscreenMethod uint32 // ShellSurfaceFullscreenMethod : different method to set the surface fullscreen // // Hints to indicate to the compositor how to deal with a conflict // between the dimensions of the surface and the dimensions of the // output. The compositor is free to ignore this parameter. const ( // ShellSurfaceFullscreenMethodDefault : no preference, apply default policy ShellSurfaceFullscreenMethodDefault ShellSurfaceFullscreenMethod = 0 // ShellSurfaceFullscreenMethodScale : scale, preserve the surface's aspect ratio and center on output ShellSurfaceFullscreenMethodScale ShellSurfaceFullscreenMethod = 1 // ShellSurfaceFullscreenMethodDriver : switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch ShellSurfaceFullscreenMethodDriver ShellSurfaceFullscreenMethod = 2 // ShellSurfaceFullscreenMethodFill : no upscaling, center on output and add black borders to compensate size mismatch ShellSurfaceFullscreenMethodFill ShellSurfaceFullscreenMethod = 3 ) func (e ShellSurfaceFullscreenMethod) Name() string { switch e { case ShellSurfaceFullscreenMethodDefault: return "default" case ShellSurfaceFullscreenMethodScale: return "scale" case ShellSurfaceFullscreenMethodDriver: return "driver" case ShellSurfaceFullscreenMethodFill: return "fill" default: return "" } } func (e ShellSurfaceFullscreenMethod) Value() string { switch e { case ShellSurfaceFullscreenMethodDefault: return "0" case ShellSurfaceFullscreenMethodScale: return "1" case ShellSurfaceFullscreenMethodDriver: return "2" case ShellSurfaceFullscreenMethodFill: return "3" default: return "" } } func (e ShellSurfaceFullscreenMethod) String() string { return e.Name() + "=" + e.Value() } // ShellSurfacePingEvent : ping client // // Ping a client to check if it is receiving events and sending // requests. A client is expected to reply with a pong request. type ShellSurfacePingEvent struct { Serial uint32 } type ShellSurfacePingHandlerFunc func(ShellSurfacePingEvent) // SetPingHandler : sets handler for ShellSurfacePingEvent func (i *ShellSurface) SetPingHandler(f ShellSurfacePingHandlerFunc) { i.pingHandler = f } // ShellSurfaceConfigureEvent : suggest resize // // The configure event asks the client to resize its surface. // // The size is a hint, in the sense that the client is free to // ignore it if it doesn't resize, pick a smaller size (to // satisfy aspect ratio or resize in steps of NxM pixels). // // The edges parameter provides a hint about how the surface // was resized. The client may use this information to decide // how to adjust its content to the new size (e.g. a scrolling // area might adjust its content position to leave the viewable // content unmoved). // // The client is free to dismiss all but the last configure // event it received. // // The width and height arguments specify the size of the window // in surface-local coordinates. type ShellSurfaceConfigureEvent struct { Edges uint32 Width int32 Height int32 } type ShellSurfaceConfigureHandlerFunc func(ShellSurfaceConfigureEvent) // SetConfigureHandler : sets handler for ShellSurfaceConfigureEvent func (i *ShellSurface) SetConfigureHandler(f ShellSurfaceConfigureHandlerFunc) { i.configureHandler = f } // ShellSurfacePopupDoneEvent : popup interaction is done // // The popup_done event is sent out when a popup grab is broken, // that is, when the user clicks a surface that doesn't belong // to the client owning the popup surface. type ShellSurfacePopupDoneEvent struct{} type ShellSurfacePopupDoneHandlerFunc func(ShellSurfacePopupDoneEvent) // SetPopupDoneHandler : sets handler for ShellSurfacePopupDoneEvent func (i *ShellSurface) SetPopupDoneHandler(f ShellSurfacePopupDoneHandlerFunc) { i.popupDoneHandler = f } func (i *ShellSurface) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.pingHandler == nil { return } var e ShellSurfacePingEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 i.pingHandler(e) case 1: if i.configureHandler == nil { return } var e ShellSurfaceConfigureEvent l := 0 e.Edges = Uint32(data[l : l+4]) l += 4 e.Width = int32(Uint32(data[l : l+4])) l += 4 e.Height = int32(Uint32(data[l : l+4])) l += 4 i.configureHandler(e) case 2: if i.popupDoneHandler == nil { return } var e ShellSurfacePopupDoneEvent i.popupDoneHandler(e) } } // SurfaceInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const SurfaceInterfaceName = "wl_surface" // Surface : an onscreen surface // // A surface is a rectangular area that may be displayed on zero // or more outputs, and shown any number of times at the compositor's // discretion. They can present wl_buffers, receive user input, and // define a local coordinate system. // // The size of a surface (and relative positions on it) is described // in surface-local coordinates, which may differ from the buffer // coordinates of the pixel content, in case a buffer_transform // or a buffer_scale is used. // // A surface without a "role" is fairly useless: a compositor does // not know where, when or how to present it. The role is the // purpose of a wl_surface. Examples of roles are a cursor for a // pointer (as set by wl_pointer.set_cursor), a drag icon // (wl_data_device.start_drag), a sub-surface // (wl_subcompositor.get_subsurface), and a window as defined by a // shell protocol (e.g. wl_shell.get_shell_surface). // // A surface can have only one role at a time. Initially a // wl_surface does not have a role. Once a wl_surface is given a // role, it is set permanently for the whole lifetime of the // wl_surface object. Giving the current role again is allowed, // unless explicitly forbidden by the relevant interface // specification. // // Surface roles are given by requests in other interfaces such as // wl_pointer.set_cursor. The request should explicitly mention // that this request gives a role to a wl_surface. Often, this // request also creates a new protocol object that represents the // role and adds additional functionality to wl_surface. When a // client wants to destroy a wl_surface, they must destroy this role // object before the wl_surface, otherwise a defunct_role_object error is // sent. // // Destroying the role object does not remove the role from the // wl_surface, but it may stop the wl_surface from "playing the role". // For instance, if a wl_subsurface object is destroyed, the wl_surface // it was created for will be unmapped and forget its position and // z-order. It is allowed to create a wl_subsurface for the same // wl_surface again, but it is not allowed to use the wl_surface as // a cursor (cursor is a different role than sub-surface, and role // switching is not allowed). type Surface struct { BaseProxy enterHandler SurfaceEnterHandlerFunc leaveHandler SurfaceLeaveHandlerFunc preferredBufferScaleHandler SurfacePreferredBufferScaleHandlerFunc preferredBufferTransformHandler SurfacePreferredBufferTransformHandlerFunc } // NewSurface : an onscreen surface // // A surface is a rectangular area that may be displayed on zero // or more outputs, and shown any number of times at the compositor's // discretion. They can present wl_buffers, receive user input, and // define a local coordinate system. // // The size of a surface (and relative positions on it) is described // in surface-local coordinates, which may differ from the buffer // coordinates of the pixel content, in case a buffer_transform // or a buffer_scale is used. // // A surface without a "role" is fairly useless: a compositor does // not know where, when or how to present it. The role is the // purpose of a wl_surface. Examples of roles are a cursor for a // pointer (as set by wl_pointer.set_cursor), a drag icon // (wl_data_device.start_drag), a sub-surface // (wl_subcompositor.get_subsurface), and a window as defined by a // shell protocol (e.g. wl_shell.get_shell_surface). // // A surface can have only one role at a time. Initially a // wl_surface does not have a role. Once a wl_surface is given a // role, it is set permanently for the whole lifetime of the // wl_surface object. Giving the current role again is allowed, // unless explicitly forbidden by the relevant interface // specification. // // Surface roles are given by requests in other interfaces such as // wl_pointer.set_cursor. The request should explicitly mention // that this request gives a role to a wl_surface. Often, this // request also creates a new protocol object that represents the // role and adds additional functionality to wl_surface. When a // client wants to destroy a wl_surface, they must destroy this role // object before the wl_surface, otherwise a defunct_role_object error is // sent. // // Destroying the role object does not remove the role from the // wl_surface, but it may stop the wl_surface from "playing the role". // For instance, if a wl_subsurface object is destroyed, the wl_surface // it was created for will be unmapped and forget its position and // z-order. It is allowed to create a wl_subsurface for the same // wl_surface again, but it is not allowed to use the wl_surface as // a cursor (cursor is a different role than sub-surface, and role // switching is not allowed). func NewSurface(ctx *Context) *Surface { wlSurface := &Surface{} ctx.Register(wlSurface) return wlSurface } // Destroy : delete surface // // Deletes the surface and invalidates its object ID. func (i *Surface) Destroy() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Attach : set the surface contents // // Set a buffer as the content of this surface. // // The new size of the surface is calculated based on the buffer // size transformed by the inverse buffer_transform and the // inverse buffer_scale. This means that at commit time the supplied // buffer size must be an integer multiple of the buffer_scale. If // that's not the case, an invalid_size error is sent. // // The x and y arguments specify the location of the new pending // buffer's upper left corner, relative to the current buffer's upper // left corner, in surface-local coordinates. In other words, the // x and y, combined with the new surface size define in which // directions the surface's size changes. Setting anything other than 0 // as x and y arguments is discouraged, and should instead be replaced // with using the separate wl_surface.offset request. // // When the bound wl_surface version is 5 or higher, passing any // non-zero x or y is a protocol violation, and will result in an // 'invalid_offset' error being raised. The x and y arguments are ignored // and do not change the pending state. To achieve equivalent semantics, // use wl_surface.offset. // // Surface contents are double-buffered state, see wl_surface.commit. // // The initial surface contents are void; there is no content. // wl_surface.attach assigns the given wl_buffer as the pending // wl_buffer. wl_surface.commit makes the pending wl_buffer the new // surface contents, and the size of the surface becomes the size // calculated from the wl_buffer, as described above. After commit, // there is no pending buffer until the next attach. // // Committing a pending wl_buffer allows the compositor to read the // pixels in the wl_buffer. The compositor may access the pixels at // any time after the wl_surface.commit request. When the compositor // will not access the pixels anymore, it will send the // wl_buffer.release event. Only after receiving wl_buffer.release, // the client may reuse the wl_buffer. A wl_buffer that has been // attached and then replaced by another attach instead of committed // will not receive a release event, and is not used by the // compositor. // // If a pending wl_buffer has been committed to more than one wl_surface, // the delivery of wl_buffer.release events becomes undefined. A well // behaved client should not rely on wl_buffer.release events in this // case. Alternatively, a client could create multiple wl_buffer objects // from the same backing storage or use a protocol extension providing // per-commit release notifications. // // Destroying the wl_buffer after wl_buffer.release does not change // the surface contents. Destroying the wl_buffer before wl_buffer.release // is allowed as long as the underlying buffer storage isn't re-used (this // can happen e.g. on client process termination). However, if the client // destroys the wl_buffer before receiving the wl_buffer.release event and // mutates the underlying buffer storage, the surface contents become // undefined immediately. // // If wl_surface.attach is sent with a NULL wl_buffer, the // following wl_surface.commit will remove the surface content. // // If a pending wl_buffer has been destroyed, the result is not specified. // Many compositors are known to remove the surface content on the following // wl_surface.commit, but this behaviour is not universal. Clients seeking to // maximise compatibility should not destroy pending buffers and should // ensure that they explicitly remove content from surfaces, even after // destroying buffers. // // buffer: buffer of surface contents // x: surface-local x coordinate // y: surface-local y coordinate func (i *Surface) Attach(buffer *Buffer, x, y int32) error { const opcode = 1 const _reqBufLen = 8 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 if buffer == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], buffer.ID()) l += 4 } PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Damage : mark part of the surface damaged // // This request is used to describe the regions where the pending // buffer is different from the current surface contents, and where // the surface therefore needs to be repainted. The compositor // ignores the parts of the damage that fall outside of the surface. // // Damage is double-buffered state, see wl_surface.commit. // // The damage rectangle is specified in surface-local coordinates, // where x and y specify the upper left corner of the damage rectangle. // // The initial value for pending damage is empty: no damage. // wl_surface.damage adds pending damage: the new pending damage // is the union of old pending damage and the given rectangle. // // wl_surface.commit assigns pending damage as the current damage, // and clears pending damage. The server will clear the current // damage as it repaints the surface. // // Note! New clients should not use this request. Instead damage can be // posted with wl_surface.damage_buffer which uses buffer coordinates // instead of surface coordinates. // // x: surface-local x coordinate // y: surface-local y coordinate // width: width of damage rectangle // height: height of damage rectangle func (i *Surface) Damage(x, y, width, height int32) error { const opcode = 2 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(width)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(height)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Frame : request a frame throttling hint // // Request a notification when it is a good time to start drawing a new // frame, by creating a frame callback. This is useful for throttling // redrawing operations, and driving animations. // // When a client is animating on a wl_surface, it can use the 'frame' // request to get notified when it is a good time to draw and commit the // next frame of animation. If the client commits an update earlier than // that, it is likely that some updates will not make it to the display, // and the client is wasting resources by drawing too often. // // The frame request will take effect on the next wl_surface.commit. // The notification will only be posted for one frame unless // requested again. For a wl_surface, the notifications are posted in // the order the frame requests were committed. // // The server must send the notifications so that a client // will not send excessive updates, while still allowing // the highest possible update rate for clients that wait for the reply // before drawing again. The server should give some time for the client // to draw and commit after sending the frame callback events to let it // hit the next output refresh. // // A server should avoid signaling the frame callbacks if the // surface is not visible in any way, e.g. the surface is off-screen, // or completely obscured by other opaque surfaces. // // The object returned by this request will be destroyed by the // compositor after the callback is fired and as such the client must not // attempt to use it after that point. // // The callback_data passed in the callback is the current time, in // milliseconds, with an undefined base. func (i *Surface) Frame() (*Callback, error) { callback := NewCallback(i.Context()) const opcode = 3 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], callback.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return callback, err } // SetOpaqueRegion : set opaque region // // This request sets the region of the surface that contains // opaque content. // // The opaque region is an optimization hint for the compositor // that lets it optimize the redrawing of content behind opaque // regions. Setting an opaque region is not required for correct // behaviour, but marking transparent content as opaque will result // in repaint artifacts. // // The opaque region is specified in surface-local coordinates. // // The compositor ignores the parts of the opaque region that fall // outside of the surface. // // Opaque region is double-buffered state, see wl_surface.commit. // // wl_surface.set_opaque_region changes the pending opaque region. // wl_surface.commit copies the pending region to the current region. // Otherwise, the pending and current regions are never changed. // // The initial value for an opaque region is empty. Setting the pending // opaque region has copy semantics, and the wl_region object can be // destroyed immediately. A NULL wl_region causes the pending opaque // region to be set to empty. // // region: opaque region of the surface func (i *Surface) SetOpaqueRegion(region *Region) error { const opcode = 4 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 if region == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], region.ID()) l += 4 } err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetInputRegion : set input region // // This request sets the region of the surface that can receive // pointer and touch events. // // Input events happening outside of this region will try the next // surface in the server surface stack. The compositor ignores the // parts of the input region that fall outside of the surface. // // The input region is specified in surface-local coordinates. // // Input region is double-buffered state, see wl_surface.commit. // // wl_surface.set_input_region changes the pending input region. // wl_surface.commit copies the pending region to the current region. // Otherwise the pending and current regions are never changed, // except cursor and icon surfaces are special cases, see // wl_pointer.set_cursor and wl_data_device.start_drag. // // The initial value for an input region is infinite. That means the // whole surface will accept input. Setting the pending input region // has copy semantics, and the wl_region object can be destroyed // immediately. A NULL wl_region causes the input region to be set // to infinite. // // region: input region of the surface func (i *Surface) SetInputRegion(region *Region) error { const opcode = 5 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 if region == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], region.ID()) l += 4 } err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Commit : commit pending surface state // // Surface state (input, opaque, and damage regions, attached buffers, // etc.) is double-buffered. Protocol requests modify the pending state, // as opposed to the active state in use by the compositor. // // A commit request atomically creates a content update from the pending // state, even if the pending state has not been touched. The content // update is placed in a queue until it becomes active. After commit, the // new pending state is as documented for each related request. // // When the content update is applied, the wl_buffer is applied before all // other state. This means that all coordinates in double-buffered state // are relative to the newly attached wl_buffers, except for // wl_surface.attach itself. If there is no newly attached wl_buffer, the // coordinates are relative to the previous content update. // // All requests that need a commit to become effective are documented // to affect double-buffered state. // // Other interfaces may add further double-buffered surface state. func (i *Surface) Commit() error { const opcode = 6 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetBufferTransform : sets the buffer transformation // // This request sets the transformation that the client has already applied // to the content of the buffer. The accepted values for the transform // parameter are the values for wl_output.transform. // // The compositor applies the inverse of this transformation whenever it // uses the buffer contents. // // Buffer transform is double-buffered state, see wl_surface.commit. // // A newly created surface has its buffer transformation set to normal. // // wl_surface.set_buffer_transform changes the pending buffer // transformation. wl_surface.commit copies the pending buffer // transformation to the current one. Otherwise, the pending and current // values are never changed. // // The purpose of this request is to allow clients to render content // according to the output transform, thus permitting the compositor to // use certain optimizations even if the display is rotated. Using // hardware overlays and scanning out a client buffer for fullscreen // surfaces are examples of such optimizations. Those optimizations are // highly dependent on the compositor implementation, so the use of this // request should be considered on a case-by-case basis. // // Note that if the transform value includes 90 or 270 degree rotation, // the width of the buffer will become the surface height and the height // of the buffer will become the surface width. // // If transform is not one of the values from the // wl_output.transform enum the invalid_transform protocol error // is raised. // // transform: transform for interpreting buffer contents func (i *Surface) SetBufferTransform(transform int32) error { const opcode = 7 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(transform)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetBufferScale : sets the buffer scaling factor // // This request sets an optional scaling factor on how the compositor // interprets the contents of the buffer attached to the window. // // Buffer scale is double-buffered state, see wl_surface.commit. // // A newly created surface has its buffer scale set to 1. // // wl_surface.set_buffer_scale changes the pending buffer scale. // wl_surface.commit copies the pending buffer scale to the current one. // Otherwise, the pending and current values are never changed. // // The purpose of this request is to allow clients to supply higher // resolution buffer data for use on high resolution outputs. It is // intended that you pick the same buffer scale as the scale of the // output that the surface is displayed on. This means the compositor // can avoid scaling when rendering the surface on that output. // // Note that if the scale is larger than 1, then you have to attach // a buffer that is larger (by a factor of scale in each dimension) // than the desired surface size. // // If scale is not greater than 0 the invalid_scale protocol error is // raised. // // scale: scale for interpreting buffer contents func (i *Surface) SetBufferScale(scale int32) error { const opcode = 8 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(scale)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // DamageBuffer : mark part of the surface damaged using buffer coordinates // // This request is used to describe the regions where the pending // buffer is different from the current surface contents, and where // the surface therefore needs to be repainted. The compositor // ignores the parts of the damage that fall outside of the surface. // // Damage is double-buffered state, see wl_surface.commit. // // The damage rectangle is specified in buffer coordinates, // where x and y specify the upper left corner of the damage rectangle. // // The initial value for pending damage is empty: no damage. // wl_surface.damage_buffer adds pending damage: the new pending // damage is the union of old pending damage and the given rectangle. // // wl_surface.commit assigns pending damage as the current damage, // and clears pending damage. The server will clear the current // damage as it repaints the surface. // // This request differs from wl_surface.damage in only one way - it // takes damage in buffer coordinates instead of surface-local // coordinates. While this generally is more intuitive than surface // coordinates, it is especially desirable when using wp_viewport // or when a drawing library (like EGL) is unaware of buffer scale // and buffer transform. // // Note: Because buffer transformation changes and damage requests may // be interleaved in the protocol stream, it is impossible to determine // the actual mapping between surface and buffer damage until // wl_surface.commit time. Therefore, compositors wishing to take both // kinds of damage into account will have to accumulate damage from the // two requests separately and only transform from one to the other // after receiving the wl_surface.commit. // // x: buffer-local x coordinate // y: buffer-local y coordinate // width: width of damage rectangle // height: height of damage rectangle func (i *Surface) DamageBuffer(x, y, width, height int32) error { const opcode = 9 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(width)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(height)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Offset : set the surface contents offset // // The x and y arguments specify the location of the new pending // buffer's upper left corner, relative to the current buffer's upper // left corner, in surface-local coordinates. In other words, the // x and y, combined with the new surface size define in which // directions the surface's size changes. // // The exact semantics of wl_surface.offset are role-specific. Refer to // the documentation of specific roles for more information. // // Surface location offset is double-buffered state, see // wl_surface.commit. // // This request is semantically equivalent to and the replaces the x and y // arguments in the wl_surface.attach request in wl_surface versions prior // to 5. See wl_surface.attach for details. // // x: surface-local x coordinate // y: surface-local y coordinate func (i *Surface) Offset(x, y int32) error { const opcode = 10 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type SurfaceError uint32 // SurfaceError : wl_surface error values // // These errors can be emitted in response to wl_surface requests. const ( // SurfaceErrorInvalidScale : buffer scale value is invalid SurfaceErrorInvalidScale SurfaceError = 0 // SurfaceErrorInvalidTransform : buffer transform value is invalid SurfaceErrorInvalidTransform SurfaceError = 1 // SurfaceErrorInvalidSize : buffer size is invalid SurfaceErrorInvalidSize SurfaceError = 2 // SurfaceErrorInvalidOffset : buffer offset is invalid SurfaceErrorInvalidOffset SurfaceError = 3 // SurfaceErrorDefunctRoleObject : surface was destroyed before its role object SurfaceErrorDefunctRoleObject SurfaceError = 4 ) func (e SurfaceError) Name() string { switch e { case SurfaceErrorInvalidScale: return "invalid_scale" case SurfaceErrorInvalidTransform: return "invalid_transform" case SurfaceErrorInvalidSize: return "invalid_size" case SurfaceErrorInvalidOffset: return "invalid_offset" case SurfaceErrorDefunctRoleObject: return "defunct_role_object" default: return "" } } func (e SurfaceError) Value() string { switch e { case SurfaceErrorInvalidScale: return "0" case SurfaceErrorInvalidTransform: return "1" case SurfaceErrorInvalidSize: return "2" case SurfaceErrorInvalidOffset: return "3" case SurfaceErrorDefunctRoleObject: return "4" default: return "" } } func (e SurfaceError) String() string { return e.Name() + "=" + e.Value() } // SurfaceEnterEvent : surface enters an output // // This is emitted whenever a surface's creation, movement, or resizing // results in some part of it being within the scanout region of an // output. // // Note that a surface may be overlapping with zero or more outputs. type SurfaceEnterEvent struct { Output *Output } type SurfaceEnterHandlerFunc func(SurfaceEnterEvent) // SetEnterHandler : sets handler for SurfaceEnterEvent func (i *Surface) SetEnterHandler(f SurfaceEnterHandlerFunc) { i.enterHandler = f } // SurfaceLeaveEvent : surface leaves an output // // This is emitted whenever a surface's creation, movement, or resizing // results in it no longer having any part of it within the scanout region // of an output. // // Clients should not use the number of outputs the surface is on for frame // throttling purposes. The surface might be hidden even if no leave event // has been sent, and the compositor might expect new surface content // updates even if no enter event has been sent. The frame event should be // used instead. type SurfaceLeaveEvent struct { Output *Output } type SurfaceLeaveHandlerFunc func(SurfaceLeaveEvent) // SetLeaveHandler : sets handler for SurfaceLeaveEvent func (i *Surface) SetLeaveHandler(f SurfaceLeaveHandlerFunc) { i.leaveHandler = f } // SurfacePreferredBufferScaleEvent : preferred buffer scale for the surface // // This event indicates the preferred buffer scale for this surface. It is // sent whenever the compositor's preference changes. // // Before receiving this event the preferred buffer scale for this surface // is 1. // // It is intended that scaling aware clients use this event to scale their // content and use wl_surface.set_buffer_scale to indicate the scale they // have rendered with. This allows clients to supply a higher detail // buffer. // // The compositor shall emit a scale value greater than 0. type SurfacePreferredBufferScaleEvent struct { Factor int32 } type SurfacePreferredBufferScaleHandlerFunc func(SurfacePreferredBufferScaleEvent) // SetPreferredBufferScaleHandler : sets handler for SurfacePreferredBufferScaleEvent func (i *Surface) SetPreferredBufferScaleHandler(f SurfacePreferredBufferScaleHandlerFunc) { i.preferredBufferScaleHandler = f } // SurfacePreferredBufferTransformEvent : preferred buffer transform for the surface // // This event indicates the preferred buffer transform for this surface. // It is sent whenever the compositor's preference changes. // // Before receiving this event the preferred buffer transform for this // surface is normal. // // Applying this transformation to the surface buffer contents and using // wl_surface.set_buffer_transform might allow the compositor to use the // surface buffer more efficiently. type SurfacePreferredBufferTransformEvent struct { Transform uint32 } type SurfacePreferredBufferTransformHandlerFunc func(SurfacePreferredBufferTransformEvent) // SetPreferredBufferTransformHandler : sets handler for SurfacePreferredBufferTransformEvent func (i *Surface) SetPreferredBufferTransformHandler(f SurfacePreferredBufferTransformHandlerFunc) { i.preferredBufferTransformHandler = f } func (i *Surface) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.enterHandler == nil { return } var e SurfaceEnterEvent l := 0 e.Output = i.Context().GetProxy(Uint32(data[l : l+4])).(*Output) l += 4 i.enterHandler(e) case 1: if i.leaveHandler == nil { return } var e SurfaceLeaveEvent l := 0 e.Output = i.Context().GetProxy(Uint32(data[l : l+4])).(*Output) l += 4 i.leaveHandler(e) case 2: if i.preferredBufferScaleHandler == nil { return } var e SurfacePreferredBufferScaleEvent l := 0 e.Factor = int32(Uint32(data[l : l+4])) l += 4 i.preferredBufferScaleHandler(e) case 3: if i.preferredBufferTransformHandler == nil { return } var e SurfacePreferredBufferTransformEvent l := 0 e.Transform = Uint32(data[l : l+4]) l += 4 i.preferredBufferTransformHandler(e) } } // SeatInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const SeatInterfaceName = "wl_seat" // Seat : group of input devices // // A seat is a group of keyboards, pointer and touch devices. This // object is published as a global during start up, or when such a // device is hot plugged. A seat typically has a pointer and // maintains a keyboard focus and a pointer focus. type Seat struct { BaseProxy capabilitiesHandler SeatCapabilitiesHandlerFunc nameHandler SeatNameHandlerFunc } // NewSeat : group of input devices // // A seat is a group of keyboards, pointer and touch devices. This // object is published as a global during start up, or when such a // device is hot plugged. A seat typically has a pointer and // maintains a keyboard focus and a pointer focus. func NewSeat(ctx *Context) *Seat { wlSeat := &Seat{} ctx.Register(wlSeat) return wlSeat } // GetPointer : return pointer object // // The ID provided will be initialized to the wl_pointer interface // for this seat. // // This request only takes effect if the seat has the pointer // capability, or has had the pointer capability in the past. // It is a protocol violation to issue this request on a seat that has // never had the pointer capability. The missing_capability error will // be sent in this case. func (i *Seat) GetPointer() (*Pointer, error) { id := NewPointer(i.Context()) const opcode = 0 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } // GetKeyboard : return keyboard object // // The ID provided will be initialized to the wl_keyboard interface // for this seat. // // This request only takes effect if the seat has the keyboard // capability, or has had the keyboard capability in the past. // It is a protocol violation to issue this request on a seat that has // never had the keyboard capability. The missing_capability error will // be sent in this case. func (i *Seat) GetKeyboard() (*Keyboard, error) { id := NewKeyboard(i.Context()) const opcode = 1 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } // GetTouch : return touch object // // The ID provided will be initialized to the wl_touch interface // for this seat. // // This request only takes effect if the seat has the touch // capability, or has had the touch capability in the past. // It is a protocol violation to issue this request on a seat that has // never had the touch capability. The missing_capability error will // be sent in this case. func (i *Seat) GetTouch() (*Touch, error) { id := NewTouch(i.Context()) const opcode = 2 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } // Release : release the seat object // // Using this request a client can tell the server that it is not going to // use the seat object anymore. func (i *Seat) Release() error { defer i.MarkZombie() const opcode = 3 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type SeatCapability uint32 // SeatCapability : seat capability bitmask // // This is a bitmask of capabilities this seat has; if a member is // set, then it is present on the seat. const ( // SeatCapabilityPointer : the seat has pointer devices SeatCapabilityPointer SeatCapability = 1 // SeatCapabilityKeyboard : the seat has one or more keyboards SeatCapabilityKeyboard SeatCapability = 2 // SeatCapabilityTouch : the seat has touch devices SeatCapabilityTouch SeatCapability = 4 ) func (e SeatCapability) Name() string { switch e { case SeatCapabilityPointer: return "pointer" case SeatCapabilityKeyboard: return "keyboard" case SeatCapabilityTouch: return "touch" default: return "" } } func (e SeatCapability) Value() string { switch e { case SeatCapabilityPointer: return "1" case SeatCapabilityKeyboard: return "2" case SeatCapabilityTouch: return "4" default: return "" } } func (e SeatCapability) String() string { return e.Name() + "=" + e.Value() } type SeatError uint32 // SeatError : wl_seat error values // // These errors can be emitted in response to wl_seat requests. const ( // SeatErrorMissingCapability : get_pointer, get_keyboard or get_touch called on seat without the matching capability SeatErrorMissingCapability SeatError = 0 ) func (e SeatError) Name() string { switch e { case SeatErrorMissingCapability: return "missing_capability" default: return "" } } func (e SeatError) Value() string { switch e { case SeatErrorMissingCapability: return "0" default: return "" } } func (e SeatError) String() string { return e.Name() + "=" + e.Value() } // SeatCapabilitiesEvent : seat capabilities changed // // This is sent on binding to the seat global or whenever a seat gains // or loses the pointer, keyboard or touch capabilities. // The argument is a capability enum containing the complete set of // capabilities this seat has. // // When the pointer capability is added, a client may create a // wl_pointer object using the wl_seat.get_pointer request. This object // will receive pointer events until the capability is removed in the // future. // // When the pointer capability is removed, a client should destroy the // wl_pointer objects associated with the seat where the capability was // removed, using the wl_pointer.release request. No further pointer // events will be received on these objects. // // In some compositors, if a seat regains the pointer capability and a // client has a previously obtained wl_pointer object of version 4 or // less, that object may start sending pointer events again. This // behavior is considered a misinterpretation of the intended behavior // and must not be relied upon by the client. wl_pointer objects of // version 5 or later must not send events if created before the most // recent event notifying the client of an added pointer capability. // // The above behavior also applies to wl_keyboard and wl_touch with the // keyboard and touch capabilities, respectively. type SeatCapabilitiesEvent struct { Capabilities uint32 } type SeatCapabilitiesHandlerFunc func(SeatCapabilitiesEvent) // SetCapabilitiesHandler : sets handler for SeatCapabilitiesEvent func (i *Seat) SetCapabilitiesHandler(f SeatCapabilitiesHandlerFunc) { i.capabilitiesHandler = f } // SeatNameEvent : unique identifier for this seat // // In a multi-seat configuration the seat name can be used by clients to // help identify which physical devices the seat represents. // // The seat name is a UTF-8 string with no convention defined for its // contents. Each name is unique among all wl_seat globals. The name is // only guaranteed to be unique for the current compositor instance. // // The same seat names are used for all clients. Thus, the name can be // shared across processes to refer to a specific wl_seat global. // // The name event is sent after binding to the seat global, and should be sent // before announcing capabilities. This event only sent once per seat object, // and the name does not change over the lifetime of the wl_seat global. // // Compositors may re-use the same seat name if the wl_seat global is // destroyed and re-created later. type SeatNameEvent struct { Name string } type SeatNameHandlerFunc func(SeatNameEvent) // SetNameHandler : sets handler for SeatNameEvent func (i *Seat) SetNameHandler(f SeatNameHandlerFunc) { i.nameHandler = f } func (i *Seat) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.capabilitiesHandler == nil { return } var e SeatCapabilitiesEvent l := 0 e.Capabilities = Uint32(data[l : l+4]) l += 4 i.capabilitiesHandler(e) case 1: if i.nameHandler == nil { return } var e SeatNameEvent l := 0 nameLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Name = String(data[l : l+nameLen]) l += nameLen i.nameHandler(e) } } // PointerInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const PointerInterfaceName = "wl_pointer" // Pointer : pointer input device // // The wl_pointer interface represents one or more input devices, // such as mice, which control the pointer location and pointer_focus // of a seat. // // The wl_pointer interface generates motion, enter and leave // events for the surfaces that the pointer is located over, // and button and axis events for button presses, button releases // and scrolling. type Pointer struct { BaseProxy enterHandler PointerEnterHandlerFunc leaveHandler PointerLeaveHandlerFunc motionHandler PointerMotionHandlerFunc buttonHandler PointerButtonHandlerFunc axisHandler PointerAxisHandlerFunc frameHandler PointerFrameHandlerFunc axisSourceHandler PointerAxisSourceHandlerFunc axisStopHandler PointerAxisStopHandlerFunc axisDiscreteHandler PointerAxisDiscreteHandlerFunc axisValue120Handler PointerAxisValue120HandlerFunc axisRelativeDirectionHandler PointerAxisRelativeDirectionHandlerFunc } // NewPointer : pointer input device // // The wl_pointer interface represents one or more input devices, // such as mice, which control the pointer location and pointer_focus // of a seat. // // The wl_pointer interface generates motion, enter and leave // events for the surfaces that the pointer is located over, // and button and axis events for button presses, button releases // and scrolling. func NewPointer(ctx *Context) *Pointer { wlPointer := &Pointer{} ctx.Register(wlPointer) return wlPointer } // SetCursor : set the pointer surface // // Set the pointer surface, i.e., the surface that contains the // pointer image (cursor). This request gives the surface the role // of a cursor. If the surface already has another role, it raises // a protocol error. // // The cursor actually changes only if the pointer // focus for this device is one of the requesting client's surfaces // or the surface parameter is the current pointer surface. If // there was a previous surface set with this request it is // replaced. If surface is NULL, the pointer image is hidden. // // The parameters hotspot_x and hotspot_y define the position of // the pointer surface relative to the pointer location. Its // top-left corner is always at (x, y) - (hotspot_x, hotspot_y), // where (x, y) are the coordinates of the pointer location, in // surface-local coordinates. // // On wl_surface.offset requests to the pointer surface, hotspot_x // and hotspot_y are decremented by the x and y parameters // passed to the request. The offset must be applied by // wl_surface.commit as usual. // // The hotspot can also be updated by passing the currently set // pointer surface to this request with new values for hotspot_x // and hotspot_y. // // The input region is ignored for wl_surfaces with the role of // a cursor. When the use as a cursor ends, the wl_surface is // unmapped. // // The serial parameter must match the latest wl_pointer.enter // serial number sent to the client. Otherwise the request will be // ignored. // // serial: serial number of the enter event // surface: pointer surface // hotspotX: surface-local x coordinate // hotspotY: surface-local y coordinate func (i *Pointer) SetCursor(serial uint32, surface *Surface, hotspotX, hotspotY int32) error { const opcode = 0 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(serial)) l += 4 if surface == nil { PutUint32(_reqBuf[l:l+4], 0) l += 4 } else { PutUint32(_reqBuf[l:l+4], surface.ID()) l += 4 } PutUint32(_reqBuf[l:l+4], uint32(hotspotX)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(hotspotY)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Release : release the pointer object // // Using this request a client can tell the server that it is not going to // use the pointer object anymore. // // This request destroys the pointer proxy object, so clients must not call // wl_pointer_destroy() after using this request. func (i *Pointer) Release() error { defer i.MarkZombie() const opcode = 1 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type PointerError uint32 // PointerError : const ( // PointerErrorRole : given wl_surface has another role PointerErrorRole PointerError = 0 ) func (e PointerError) Name() string { switch e { case PointerErrorRole: return "role" default: return "" } } func (e PointerError) Value() string { switch e { case PointerErrorRole: return "0" default: return "" } } func (e PointerError) String() string { return e.Name() + "=" + e.Value() } type PointerButtonState uint32 // PointerButtonState : physical button state // // Describes the physical state of a button that produced the button // event. const ( // PointerButtonStateReleased : the button is not pressed PointerButtonStateReleased PointerButtonState = 0 // PointerButtonStatePressed : the button is pressed PointerButtonStatePressed PointerButtonState = 1 ) func (e PointerButtonState) Name() string { switch e { case PointerButtonStateReleased: return "released" case PointerButtonStatePressed: return "pressed" default: return "" } } func (e PointerButtonState) Value() string { switch e { case PointerButtonStateReleased: return "0" case PointerButtonStatePressed: return "1" default: return "" } } func (e PointerButtonState) String() string { return e.Name() + "=" + e.Value() } type PointerAxis uint32 // PointerAxis : axis types // // Describes the axis types of scroll events. const ( // PointerAxisVerticalScroll : vertical axis PointerAxisVerticalScroll PointerAxis = 0 // PointerAxisHorizontalScroll : horizontal axis PointerAxisHorizontalScroll PointerAxis = 1 ) func (e PointerAxis) Name() string { switch e { case PointerAxisVerticalScroll: return "vertical_scroll" case PointerAxisHorizontalScroll: return "horizontal_scroll" default: return "" } } func (e PointerAxis) Value() string { switch e { case PointerAxisVerticalScroll: return "0" case PointerAxisHorizontalScroll: return "1" default: return "" } } func (e PointerAxis) String() string { return e.Name() + "=" + e.Value() } type PointerAxisSource uint32 // PointerAxisSource : axis source types // // Describes the source types for axis events. This indicates to the // client how an axis event was physically generated; a client may // adjust the user interface accordingly. For example, scroll events // from a "finger" source may be in a smooth coordinate space with // kinetic scrolling whereas a "wheel" source may be in discrete steps // of a number of lines. // // The "continuous" axis source is a device generating events in a // continuous coordinate space, but using something other than a // finger. One example for this source is button-based scrolling where // the vertical motion of a device is converted to scroll events while // a button is held down. // // The "wheel tilt" axis source indicates that the actual device is a // wheel but the scroll event is not caused by a rotation but a // (usually sideways) tilt of the wheel. const ( // PointerAxisSourceWheel : a physical wheel rotation PointerAxisSourceWheel PointerAxisSource = 0 // PointerAxisSourceFinger : finger on a touch surface PointerAxisSourceFinger PointerAxisSource = 1 // PointerAxisSourceContinuous : continuous coordinate space PointerAxisSourceContinuous PointerAxisSource = 2 // PointerAxisSourceWheelTilt : a physical wheel tilt PointerAxisSourceWheelTilt PointerAxisSource = 3 ) func (e PointerAxisSource) Name() string { switch e { case PointerAxisSourceWheel: return "wheel" case PointerAxisSourceFinger: return "finger" case PointerAxisSourceContinuous: return "continuous" case PointerAxisSourceWheelTilt: return "wheel_tilt" default: return "" } } func (e PointerAxisSource) Value() string { switch e { case PointerAxisSourceWheel: return "0" case PointerAxisSourceFinger: return "1" case PointerAxisSourceContinuous: return "2" case PointerAxisSourceWheelTilt: return "3" default: return "" } } func (e PointerAxisSource) String() string { return e.Name() + "=" + e.Value() } type PointerAxisRelativeDirection uint32 // PointerAxisRelativeDirection : axis relative direction // // This specifies the direction of the physical motion that caused a // wl_pointer.axis event, relative to the wl_pointer.axis direction. const ( // PointerAxisRelativeDirectionIdentical : physical motion matches axis direction PointerAxisRelativeDirectionIdentical PointerAxisRelativeDirection = 0 // PointerAxisRelativeDirectionInverted : physical motion is the inverse of the axis direction PointerAxisRelativeDirectionInverted PointerAxisRelativeDirection = 1 ) func (e PointerAxisRelativeDirection) Name() string { switch e { case PointerAxisRelativeDirectionIdentical: return "identical" case PointerAxisRelativeDirectionInverted: return "inverted" default: return "" } } func (e PointerAxisRelativeDirection) Value() string { switch e { case PointerAxisRelativeDirectionIdentical: return "0" case PointerAxisRelativeDirectionInverted: return "1" default: return "" } } func (e PointerAxisRelativeDirection) String() string { return e.Name() + "=" + e.Value() } // PointerEnterEvent : enter event // // Notification that this seat's pointer is focused on a certain // surface. // // When a seat's focus enters a surface, the pointer image // is undefined and a client should respond to this event by setting // an appropriate pointer image with the set_cursor request. type PointerEnterEvent struct { Serial uint32 Surface *Surface SurfaceX float64 SurfaceY float64 } type PointerEnterHandlerFunc func(PointerEnterEvent) // SetEnterHandler : sets handler for PointerEnterEvent func (i *Pointer) SetEnterHandler(f PointerEnterHandlerFunc) { i.enterHandler = f } // PointerLeaveEvent : leave event // // Notification that this seat's pointer is no longer focused on // a certain surface. // // The leave notification is sent before the enter notification // for the new focus. type PointerLeaveEvent struct { Serial uint32 Surface *Surface } type PointerLeaveHandlerFunc func(PointerLeaveEvent) // SetLeaveHandler : sets handler for PointerLeaveEvent func (i *Pointer) SetLeaveHandler(f PointerLeaveHandlerFunc) { i.leaveHandler = f } // PointerMotionEvent : pointer motion event // // Notification of pointer location change. The arguments // surface_x and surface_y are the location relative to the // focused surface. type PointerMotionEvent struct { Time uint32 SurfaceX float64 SurfaceY float64 } type PointerMotionHandlerFunc func(PointerMotionEvent) // SetMotionHandler : sets handler for PointerMotionEvent func (i *Pointer) SetMotionHandler(f PointerMotionHandlerFunc) { i.motionHandler = f } // PointerButtonEvent : pointer button event // // Mouse button click and release notifications. // // The location of the click is given by the last motion or // enter event. // The time argument is a timestamp with millisecond // granularity, with an undefined base. // // The button is a button code as defined in the Linux kernel's // linux/input-event-codes.h header file, e.g. BTN_LEFT. // // Any 16-bit button code value is reserved for future additions to the // kernel's event code list. All other button codes above 0xFFFF are // currently undefined but may be used in future versions of this // protocol. type PointerButtonEvent struct { Serial uint32 Time uint32 Button uint32 State uint32 } type PointerButtonHandlerFunc func(PointerButtonEvent) // SetButtonHandler : sets handler for PointerButtonEvent func (i *Pointer) SetButtonHandler(f PointerButtonHandlerFunc) { i.buttonHandler = f } // PointerAxisEvent : axis event // // Scroll and other axis notifications. // // For scroll events (vertical and horizontal scroll axes), the // value parameter is the length of a vector along the specified // axis in a coordinate space identical to those of motion events, // representing a relative movement along the specified axis. // // For devices that support movements non-parallel to axes multiple // axis events will be emitted. // // When applicable, for example for touch pads, the server can // choose to emit scroll events where the motion vector is // equivalent to a motion event vector. // // When applicable, a client can transform its content relative to the // scroll distance. type PointerAxisEvent struct { Time uint32 Axis uint32 Value float64 } type PointerAxisHandlerFunc func(PointerAxisEvent) // SetAxisHandler : sets handler for PointerAxisEvent func (i *Pointer) SetAxisHandler(f PointerAxisHandlerFunc) { i.axisHandler = f } // PointerFrameEvent : end of a pointer event sequence // // Indicates the end of a set of events that logically belong together. // A client is expected to accumulate the data in all events within the // frame before proceeding. // // All wl_pointer events before a wl_pointer.frame event belong // logically together. For example, in a diagonal scroll motion the // compositor will send an optional wl_pointer.axis_source event, two // wl_pointer.axis events (horizontal and vertical) and finally a // wl_pointer.frame event. The client may use this information to // calculate a diagonal vector for scrolling. // // When multiple wl_pointer.axis events occur within the same frame, // the motion vector is the combined motion of all events. // When a wl_pointer.axis and a wl_pointer.axis_stop event occur within // the same frame, this indicates that axis movement in one axis has // stopped but continues in the other axis. // When multiple wl_pointer.axis_stop events occur within the same // frame, this indicates that these axes stopped in the same instance. // // A wl_pointer.frame event is sent for every logical event group, // even if the group only contains a single wl_pointer event. // Specifically, a client may get a sequence: motion, frame, button, // frame, axis, frame, axis_stop, frame. // // The wl_pointer.enter and wl_pointer.leave events are logical events // generated by the compositor and not the hardware. These events are // also grouped by a wl_pointer.frame. When a pointer moves from one // surface to another, a compositor should group the // wl_pointer.leave event within the same wl_pointer.frame. // However, a client must not rely on wl_pointer.leave and // wl_pointer.enter being in the same wl_pointer.frame. // Compositor-specific policies may require the wl_pointer.leave and // wl_pointer.enter event being split across multiple wl_pointer.frame // groups. type PointerFrameEvent struct{} type PointerFrameHandlerFunc func(PointerFrameEvent) // SetFrameHandler : sets handler for PointerFrameEvent func (i *Pointer) SetFrameHandler(f PointerFrameHandlerFunc) { i.frameHandler = f } // PointerAxisSourceEvent : axis source event // // Source information for scroll and other axes. // // This event does not occur on its own. It is sent before a // wl_pointer.frame event and carries the source information for // all events within that frame. // // The source specifies how this event was generated. If the source is // wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be // sent when the user lifts the finger off the device. // // If the source is wl_pointer.axis_source.wheel, // wl_pointer.axis_source.wheel_tilt or // wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may // or may not be sent. Whether a compositor sends an axis_stop event // for these sources is hardware-specific and implementation-dependent; // clients must not rely on receiving an axis_stop event for these // scroll sources and should treat scroll sequences from these scroll // sources as unterminated by default. // // This event is optional. If the source is unknown for a particular // axis event sequence, no event is sent. // Only one wl_pointer.axis_source event is permitted per frame. // // The order of wl_pointer.axis_discrete and wl_pointer.axis_source is // not guaranteed. type PointerAxisSourceEvent struct { AxisSource uint32 } type PointerAxisSourceHandlerFunc func(PointerAxisSourceEvent) // SetAxisSourceHandler : sets handler for PointerAxisSourceEvent func (i *Pointer) SetAxisSourceHandler(f PointerAxisSourceHandlerFunc) { i.axisSourceHandler = f } // PointerAxisStopEvent : axis stop event // // Stop notification for scroll and other axes. // // For some wl_pointer.axis_source types, a wl_pointer.axis_stop event // is sent to notify a client that the axis sequence has terminated. // This enables the client to implement kinetic scrolling. // See the wl_pointer.axis_source documentation for information on when // this event may be generated. // // Any wl_pointer.axis events with the same axis_source after this // event should be considered as the start of a new axis motion. // // The timestamp is to be interpreted identical to the timestamp in the // wl_pointer.axis event. The timestamp value may be the same as a // preceding wl_pointer.axis event. type PointerAxisStopEvent struct { Time uint32 Axis uint32 } type PointerAxisStopHandlerFunc func(PointerAxisStopEvent) // SetAxisStopHandler : sets handler for PointerAxisStopEvent func (i *Pointer) SetAxisStopHandler(f PointerAxisStopHandlerFunc) { i.axisStopHandler = f } // PointerAxisDiscreteEvent : axis click event // // Discrete step information for scroll and other axes. // // This event carries the axis value of the wl_pointer.axis event in // discrete steps (e.g. mouse wheel clicks). // // This event is deprecated with wl_pointer version 8 - this event is not // sent to clients supporting version 8 or later. // // This event does not occur on its own, it is coupled with a // wl_pointer.axis event that represents this axis value on a // continuous scale. The protocol guarantees that each axis_discrete // event is always followed by exactly one axis event with the same // axis number within the same wl_pointer.frame. Note that the protocol // allows for other events to occur between the axis_discrete and // its coupled axis event, including other axis_discrete or axis // events. A wl_pointer.frame must not contain more than one axis_discrete // event per axis type. // // This event is optional; continuous scrolling devices // like two-finger scrolling on touchpads do not have discrete // steps and do not generate this event. // // The discrete value carries the directional information. e.g. a value // of -2 is two steps towards the negative direction of this axis. // // The axis number is identical to the axis number in the associated // axis event. // // The order of wl_pointer.axis_discrete and wl_pointer.axis_source is // not guaranteed. type PointerAxisDiscreteEvent struct { Axis uint32 Discrete int32 } type PointerAxisDiscreteHandlerFunc func(PointerAxisDiscreteEvent) // SetAxisDiscreteHandler : sets handler for PointerAxisDiscreteEvent func (i *Pointer) SetAxisDiscreteHandler(f PointerAxisDiscreteHandlerFunc) { i.axisDiscreteHandler = f } // PointerAxisValue120Event : axis high-resolution scroll event // // Discrete high-resolution scroll information. // // This event carries high-resolution wheel scroll information, // with each multiple of 120 representing one logical scroll step // (a wheel detent). For example, an axis_value120 of 30 is one quarter of // a logical scroll step in the positive direction, a value120 of // -240 are two logical scroll steps in the negative direction within the // same hardware event. // Clients that rely on discrete scrolling should accumulate the // value120 to multiples of 120 before processing the event. // // The value120 must not be zero. // // This event replaces the wl_pointer.axis_discrete event in clients // supporting wl_pointer version 8 or later. // // Where a wl_pointer.axis_source event occurs in the same // wl_pointer.frame, the axis source applies to this event. // // The order of wl_pointer.axis_value120 and wl_pointer.axis_source is // not guaranteed. type PointerAxisValue120Event struct { Axis uint32 Value120 int32 } type PointerAxisValue120HandlerFunc func(PointerAxisValue120Event) // SetAxisValue120Handler : sets handler for PointerAxisValue120Event func (i *Pointer) SetAxisValue120Handler(f PointerAxisValue120HandlerFunc) { i.axisValue120Handler = f } // PointerAxisRelativeDirectionEvent : axis relative physical direction event // // Relative directional information of the entity causing the axis // motion. // // For a wl_pointer.axis event, the wl_pointer.axis_relative_direction // event specifies the movement direction of the entity causing the // wl_pointer.axis event. For example: // - if a user's fingers on a touchpad move down and this // causes a wl_pointer.axis vertical_scroll down event, the physical // direction is 'identical' // - if a user's fingers on a touchpad move down and this causes a // wl_pointer.axis vertical_scroll up scroll up event ('natural // scrolling'), the physical direction is 'inverted'. // // A client may use this information to adjust scroll motion of // components. Specifically, enabling natural scrolling causes the // content to change direction compared to traditional scrolling. // Some widgets like volume control sliders should usually match the // physical direction regardless of whether natural scrolling is // active. This event enables clients to match the scroll direction of // a widget to the physical direction. // // This event does not occur on its own, it is coupled with a // wl_pointer.axis event that represents this axis value. // The protocol guarantees that each axis_relative_direction event is // always followed by exactly one axis event with the same // axis number within the same wl_pointer.frame. Note that the protocol // allows for other events to occur between the axis_relative_direction // and its coupled axis event. // // The axis number is identical to the axis number in the associated // axis event. // // The order of wl_pointer.axis_relative_direction, // wl_pointer.axis_discrete and wl_pointer.axis_source is not // guaranteed. type PointerAxisRelativeDirectionEvent struct { Axis uint32 Direction uint32 } type PointerAxisRelativeDirectionHandlerFunc func(PointerAxisRelativeDirectionEvent) // SetAxisRelativeDirectionHandler : sets handler for PointerAxisRelativeDirectionEvent func (i *Pointer) SetAxisRelativeDirectionHandler(f PointerAxisRelativeDirectionHandlerFunc) { i.axisRelativeDirectionHandler = f } func (i *Pointer) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.enterHandler == nil { return } var e PointerEnterEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Surface = i.Context().GetProxy(Uint32(data[l : l+4])).(*Surface) l += 4 e.SurfaceX = Fixed(data[l : l+4]) l += 4 e.SurfaceY = Fixed(data[l : l+4]) l += 4 i.enterHandler(e) case 1: if i.leaveHandler == nil { return } var e PointerLeaveEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Surface = i.Context().GetProxy(Uint32(data[l : l+4])).(*Surface) l += 4 i.leaveHandler(e) case 2: if i.motionHandler == nil { return } var e PointerMotionEvent l := 0 e.Time = Uint32(data[l : l+4]) l += 4 e.SurfaceX = Fixed(data[l : l+4]) l += 4 e.SurfaceY = Fixed(data[l : l+4]) l += 4 i.motionHandler(e) case 3: if i.buttonHandler == nil { return } var e PointerButtonEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Time = Uint32(data[l : l+4]) l += 4 e.Button = Uint32(data[l : l+4]) l += 4 e.State = Uint32(data[l : l+4]) l += 4 i.buttonHandler(e) case 4: if i.axisHandler == nil { return } var e PointerAxisEvent l := 0 e.Time = Uint32(data[l : l+4]) l += 4 e.Axis = Uint32(data[l : l+4]) l += 4 e.Value = Fixed(data[l : l+4]) l += 4 i.axisHandler(e) case 5: if i.frameHandler == nil { return } var e PointerFrameEvent i.frameHandler(e) case 6: if i.axisSourceHandler == nil { return } var e PointerAxisSourceEvent l := 0 e.AxisSource = Uint32(data[l : l+4]) l += 4 i.axisSourceHandler(e) case 7: if i.axisStopHandler == nil { return } var e PointerAxisStopEvent l := 0 e.Time = Uint32(data[l : l+4]) l += 4 e.Axis = Uint32(data[l : l+4]) l += 4 i.axisStopHandler(e) case 8: if i.axisDiscreteHandler == nil { return } var e PointerAxisDiscreteEvent l := 0 e.Axis = Uint32(data[l : l+4]) l += 4 e.Discrete = int32(Uint32(data[l : l+4])) l += 4 i.axisDiscreteHandler(e) case 9: if i.axisValue120Handler == nil { return } var e PointerAxisValue120Event l := 0 e.Axis = Uint32(data[l : l+4]) l += 4 e.Value120 = int32(Uint32(data[l : l+4])) l += 4 i.axisValue120Handler(e) case 10: if i.axisRelativeDirectionHandler == nil { return } var e PointerAxisRelativeDirectionEvent l := 0 e.Axis = Uint32(data[l : l+4]) l += 4 e.Direction = Uint32(data[l : l+4]) l += 4 i.axisRelativeDirectionHandler(e) } } // KeyboardInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const KeyboardInterfaceName = "wl_keyboard" // Keyboard : keyboard input device // // The wl_keyboard interface represents one or more keyboards // associated with a seat. // // Each wl_keyboard has the following logical state: // // - an active surface (possibly null), // - the keys currently logically down, // - the active modifiers, // - the active group. // // By default, the active surface is null, the keys currently logically down // are empty, the active modifiers and the active group are 0. type Keyboard struct { BaseProxy keymapHandler KeyboardKeymapHandlerFunc enterHandler KeyboardEnterHandlerFunc leaveHandler KeyboardLeaveHandlerFunc keyHandler KeyboardKeyHandlerFunc modifiersHandler KeyboardModifiersHandlerFunc repeatInfoHandler KeyboardRepeatInfoHandlerFunc } // NewKeyboard : keyboard input device // // The wl_keyboard interface represents one or more keyboards // associated with a seat. // // Each wl_keyboard has the following logical state: // // - an active surface (possibly null), // - the keys currently logically down, // - the active modifiers, // - the active group. // // By default, the active surface is null, the keys currently logically down // are empty, the active modifiers and the active group are 0. func NewKeyboard(ctx *Context) *Keyboard { wlKeyboard := &Keyboard{} ctx.Register(wlKeyboard) return wlKeyboard } // Release : release the keyboard object func (i *Keyboard) Release() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type KeyboardKeymapFormat uint32 // KeyboardKeymapFormat : keyboard mapping format // // This specifies the format of the keymap provided to the // client with the wl_keyboard.keymap event. const ( // KeyboardKeymapFormatNoKeymap : no keymap; client must understand how to interpret the raw keycode KeyboardKeymapFormatNoKeymap KeyboardKeymapFormat = 0 // KeyboardKeymapFormatXkbV1 : libxkbcommon compatible, null-terminated string; to determine the xkb keycode, clients must add 8 to the key event keycode KeyboardKeymapFormatXkbV1 KeyboardKeymapFormat = 1 ) func (e KeyboardKeymapFormat) Name() string { switch e { case KeyboardKeymapFormatNoKeymap: return "no_keymap" case KeyboardKeymapFormatXkbV1: return "xkb_v1" default: return "" } } func (e KeyboardKeymapFormat) Value() string { switch e { case KeyboardKeymapFormatNoKeymap: return "0" case KeyboardKeymapFormatXkbV1: return "1" default: return "" } } func (e KeyboardKeymapFormat) String() string { return e.Name() + "=" + e.Value() } type KeyboardKeyState uint32 // KeyboardKeyState : physical key state // // Describes the physical state of a key that produced the key event. // // Since version 10, the key can be in a "repeated" pseudo-state which // means the same as "pressed", but is used to signal repetition in the // key event. // // The key may only enter the repeated state after entering the pressed // state and before entering the released state. This event may be // generated multiple times while the key is down. const ( // KeyboardKeyStateReleased : key is not pressed KeyboardKeyStateReleased KeyboardKeyState = 0 // KeyboardKeyStatePressed : key is pressed KeyboardKeyStatePressed KeyboardKeyState = 1 // KeyboardKeyStateRepeated : key was repeated KeyboardKeyStateRepeated KeyboardKeyState = 2 ) func (e KeyboardKeyState) Name() string { switch e { case KeyboardKeyStateReleased: return "released" case KeyboardKeyStatePressed: return "pressed" case KeyboardKeyStateRepeated: return "repeated" default: return "" } } func (e KeyboardKeyState) Value() string { switch e { case KeyboardKeyStateReleased: return "0" case KeyboardKeyStatePressed: return "1" case KeyboardKeyStateRepeated: return "2" default: return "" } } func (e KeyboardKeyState) String() string { return e.Name() + "=" + e.Value() } // KeyboardKeymapEvent : keyboard mapping // // This event provides a file descriptor to the client which can be // memory-mapped in read-only mode to provide a keyboard mapping // description. // // From version 7 onwards, the fd must be mapped with MAP_PRIVATE by // the recipient, as MAP_SHARED may fail. type KeyboardKeymapEvent struct { Format uint32 Fd int Size uint32 } type KeyboardKeymapHandlerFunc func(KeyboardKeymapEvent) // SetKeymapHandler : sets handler for KeyboardKeymapEvent func (i *Keyboard) SetKeymapHandler(f KeyboardKeymapHandlerFunc) { i.keymapHandler = f } // KeyboardEnterEvent : enter event // // Notification that this seat's keyboard focus is on a certain // surface. // // The compositor must send the wl_keyboard.modifiers event after this // event. // // In the wl_keyboard logical state, this event sets the active surface to // the surface argument and the keys currently logically down to the keys // in the keys argument. The compositor must not send this event if the // wl_keyboard already had an active surface immediately before this event. // // Clients should not use the list of pressed keys to emulate key-press // events. The order of keys in the list is unspecified. type KeyboardEnterEvent struct { Serial uint32 Surface *Surface Keys []byte } type KeyboardEnterHandlerFunc func(KeyboardEnterEvent) // SetEnterHandler : sets handler for KeyboardEnterEvent func (i *Keyboard) SetEnterHandler(f KeyboardEnterHandlerFunc) { i.enterHandler = f } // KeyboardLeaveEvent : leave event // // Notification that this seat's keyboard focus is no longer on // a certain surface. // // The leave notification is sent before the enter notification // for the new focus. // // In the wl_keyboard logical state, this event resets all values to their // defaults. The compositor must not send this event if the active surface // of the wl_keyboard was not equal to the surface argument immediately // before this event. type KeyboardLeaveEvent struct { Serial uint32 Surface *Surface } type KeyboardLeaveHandlerFunc func(KeyboardLeaveEvent) // SetLeaveHandler : sets handler for KeyboardLeaveEvent func (i *Keyboard) SetLeaveHandler(f KeyboardLeaveHandlerFunc) { i.leaveHandler = f } // KeyboardKeyEvent : key event // // A key was pressed or released. // The time argument is a timestamp with millisecond // granularity, with an undefined base. // // The key is a platform-specific key code that can be interpreted // by feeding it to the keyboard mapping (see the keymap event). // // If this event produces a change in modifiers, then the resulting // wl_keyboard.modifiers event must be sent after this event. // // In the wl_keyboard logical state, this event adds the key to the keys // currently logically down (if the state argument is pressed) or removes // the key from the keys currently logically down (if the state argument is // released). The compositor must not send this event if the wl_keyboard // did not have an active surface immediately before this event. The // compositor must not send this event if state is pressed (resp. released) // and the key was already logically down (resp. was not logically down) // immediately before this event. // // Since version 10, compositors may send key events with the "repeated" // key state when a wl_keyboard.repeat_info event with a rate argument of // 0 has been received. This allows the compositor to take over the // responsibility of key repetition. type KeyboardKeyEvent struct { Serial uint32 Time uint32 Key uint32 State uint32 } type KeyboardKeyHandlerFunc func(KeyboardKeyEvent) // SetKeyHandler : sets handler for KeyboardKeyEvent func (i *Keyboard) SetKeyHandler(f KeyboardKeyHandlerFunc) { i.keyHandler = f } // KeyboardModifiersEvent : modifier and group state // // Notifies clients that the modifier and/or group state has // changed, and it should update its local state. // // The compositor may send this event without a surface of the client // having keyboard focus, for example to tie modifier information to // pointer focus instead. If a modifier event with pressed modifiers is sent // without a prior enter event, the client can assume the modifier state is // valid until it receives the next wl_keyboard.modifiers event. In order to // reset the modifier state again, the compositor can send a // wl_keyboard.modifiers event with no pressed modifiers. // // In the wl_keyboard logical state, this event updates the modifiers and // group. type KeyboardModifiersEvent struct { Serial uint32 ModsDepressed uint32 ModsLatched uint32 ModsLocked uint32 Group uint32 } type KeyboardModifiersHandlerFunc func(KeyboardModifiersEvent) // SetModifiersHandler : sets handler for KeyboardModifiersEvent func (i *Keyboard) SetModifiersHandler(f KeyboardModifiersHandlerFunc) { i.modifiersHandler = f } // KeyboardRepeatInfoEvent : repeat rate and delay // // Informs the client about the keyboard's repeat rate and delay. // // This event is sent as soon as the wl_keyboard object has been created, // and is guaranteed to be received by the client before any key press // event. // // Negative values for either rate or delay are illegal. A rate of zero // will disable any repeating (regardless of the value of delay). // // This event can be sent later on as well with a new value if necessary, // so clients should continue listening for the event past the creation // of wl_keyboard. type KeyboardRepeatInfoEvent struct { Rate int32 Delay int32 } type KeyboardRepeatInfoHandlerFunc func(KeyboardRepeatInfoEvent) // SetRepeatInfoHandler : sets handler for KeyboardRepeatInfoEvent func (i *Keyboard) SetRepeatInfoHandler(f KeyboardRepeatInfoHandlerFunc) { i.repeatInfoHandler = f } func (i *Keyboard) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.keymapHandler == nil { if fd != -1 { unix.Close(fd) } return } var e KeyboardKeymapEvent l := 0 e.Format = Uint32(data[l : l+4]) l += 4 e.Fd = fd e.Size = Uint32(data[l : l+4]) l += 4 i.keymapHandler(e) case 1: if i.enterHandler == nil { return } var e KeyboardEnterEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Surface = i.Context().GetProxy(Uint32(data[l : l+4])).(*Surface) l += 4 keysLen := int(Uint32(data[l : l+4])) l += 4 e.Keys = make([]byte, keysLen) copy(e.Keys, data[l:l+keysLen]) l += keysLen i.enterHandler(e) case 2: if i.leaveHandler == nil { return } var e KeyboardLeaveEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Surface = i.Context().GetProxy(Uint32(data[l : l+4])).(*Surface) l += 4 i.leaveHandler(e) case 3: if i.keyHandler == nil { return } var e KeyboardKeyEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Time = Uint32(data[l : l+4]) l += 4 e.Key = Uint32(data[l : l+4]) l += 4 e.State = Uint32(data[l : l+4]) l += 4 i.keyHandler(e) case 4: if i.modifiersHandler == nil { return } var e KeyboardModifiersEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.ModsDepressed = Uint32(data[l : l+4]) l += 4 e.ModsLatched = Uint32(data[l : l+4]) l += 4 e.ModsLocked = Uint32(data[l : l+4]) l += 4 e.Group = Uint32(data[l : l+4]) l += 4 i.modifiersHandler(e) case 5: if i.repeatInfoHandler == nil { return } var e KeyboardRepeatInfoEvent l := 0 e.Rate = int32(Uint32(data[l : l+4])) l += 4 e.Delay = int32(Uint32(data[l : l+4])) l += 4 i.repeatInfoHandler(e) } } // TouchInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const TouchInterfaceName = "wl_touch" // Touch : touchscreen input device // // The wl_touch interface represents a touchscreen // associated with a seat. // // Touch interactions can consist of one or more contacts. // For each contact, a series of events is generated, starting // with a down event, followed by zero or more motion events, // and ending with an up event. Events relating to the same // contact point can be identified by the ID of the sequence. type Touch struct { BaseProxy downHandler TouchDownHandlerFunc upHandler TouchUpHandlerFunc motionHandler TouchMotionHandlerFunc frameHandler TouchFrameHandlerFunc cancelHandler TouchCancelHandlerFunc shapeHandler TouchShapeHandlerFunc orientationHandler TouchOrientationHandlerFunc } // NewTouch : touchscreen input device // // The wl_touch interface represents a touchscreen // associated with a seat. // // Touch interactions can consist of one or more contacts. // For each contact, a series of events is generated, starting // with a down event, followed by zero or more motion events, // and ending with an up event. Events relating to the same // contact point can be identified by the ID of the sequence. func NewTouch(ctx *Context) *Touch { wlTouch := &Touch{} ctx.Register(wlTouch) return wlTouch } // Release : release the touch object func (i *Touch) Release() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // TouchDownEvent : touch down event and beginning of a touch sequence // // A new touch point has appeared on the surface. This touch point is // assigned a unique ID. Future events from this touch point reference // this ID. The ID ceases to be valid after a touch up event and may be // reused in the future. type TouchDownEvent struct { Serial uint32 Time uint32 Surface *Surface Id int32 X float64 Y float64 } type TouchDownHandlerFunc func(TouchDownEvent) // SetDownHandler : sets handler for TouchDownEvent func (i *Touch) SetDownHandler(f TouchDownHandlerFunc) { i.downHandler = f } // TouchUpEvent : end of a touch event sequence // // The touch point has disappeared. No further events will be sent for // this touch point and the touch point's ID is released and may be // reused in a future touch down event. type TouchUpEvent struct { Serial uint32 Time uint32 Id int32 } type TouchUpHandlerFunc func(TouchUpEvent) // SetUpHandler : sets handler for TouchUpEvent func (i *Touch) SetUpHandler(f TouchUpHandlerFunc) { i.upHandler = f } // TouchMotionEvent : update of touch point coordinates // // A touch point has changed coordinates. type TouchMotionEvent struct { Time uint32 Id int32 X float64 Y float64 } type TouchMotionHandlerFunc func(TouchMotionEvent) // SetMotionHandler : sets handler for TouchMotionEvent func (i *Touch) SetMotionHandler(f TouchMotionHandlerFunc) { i.motionHandler = f } // TouchFrameEvent : end of touch frame event // // Indicates the end of a set of events that logically belong together. // A client is expected to accumulate the data in all events within the // frame before proceeding. // // A wl_touch.frame terminates at least one event but otherwise no // guarantee is provided about the set of events within a frame. A client // must assume that any state not updated in a frame is unchanged from the // previously known state. type TouchFrameEvent struct{} type TouchFrameHandlerFunc func(TouchFrameEvent) // SetFrameHandler : sets handler for TouchFrameEvent func (i *Touch) SetFrameHandler(f TouchFrameHandlerFunc) { i.frameHandler = f } // TouchCancelEvent : touch session cancelled // // Sent if the compositor decides the touch stream is a global // gesture. No further events are sent to the clients from that // particular gesture. Touch cancellation applies to all touch points // currently active on this client's surface. The client is // responsible for finalizing the touch points, future touch points on // this surface may reuse the touch point ID. // // No frame event is required after the cancel event. type TouchCancelEvent struct{} type TouchCancelHandlerFunc func(TouchCancelEvent) // SetCancelHandler : sets handler for TouchCancelEvent func (i *Touch) SetCancelHandler(f TouchCancelHandlerFunc) { i.cancelHandler = f } // TouchShapeEvent : update shape of touch point // // Sent when a touchpoint has changed its shape. // // This event does not occur on its own. It is sent before a // wl_touch.frame event and carries the new shape information for // any previously reported, or new touch points of that frame. // // Other events describing the touch point such as wl_touch.down, // wl_touch.motion or wl_touch.orientation may be sent within the // same wl_touch.frame. A client should treat these events as a single // logical touch point update. The order of wl_touch.shape, // wl_touch.orientation and wl_touch.motion is not guaranteed. // A wl_touch.down event is guaranteed to occur before the first // wl_touch.shape event for this touch ID but both events may occur within // the same wl_touch.frame. // // A touchpoint shape is approximated by an ellipse through the major and // minor axis length. The major axis length describes the longer diameter // of the ellipse, while the minor axis length describes the shorter // diameter. Major and minor are orthogonal and both are specified in // surface-local coordinates. The center of the ellipse is always at the // touchpoint location as reported by wl_touch.down or wl_touch.move. // // This event is only sent by the compositor if the touch device supports // shape reports. The client has to make reasonable assumptions about the // shape if it did not receive this event. type TouchShapeEvent struct { Id int32 Major float64 Minor float64 } type TouchShapeHandlerFunc func(TouchShapeEvent) // SetShapeHandler : sets handler for TouchShapeEvent func (i *Touch) SetShapeHandler(f TouchShapeHandlerFunc) { i.shapeHandler = f } // TouchOrientationEvent : update orientation of touch point // // Sent when a touchpoint has changed its orientation. // // This event does not occur on its own. It is sent before a // wl_touch.frame event and carries the new shape information for // any previously reported, or new touch points of that frame. // // Other events describing the touch point such as wl_touch.down, // wl_touch.motion or wl_touch.shape may be sent within the // same wl_touch.frame. A client should treat these events as a single // logical touch point update. The order of wl_touch.shape, // wl_touch.orientation and wl_touch.motion is not guaranteed. // A wl_touch.down event is guaranteed to occur before the first // wl_touch.orientation event for this touch ID but both events may occur // within the same wl_touch.frame. // // The orientation describes the clockwise angle of a touchpoint's major // axis to the positive surface y-axis and is normalized to the -180 to // +180 degree range. The granularity of orientation depends on the touch // device, some devices only support binary rotation values between 0 and // 90 degrees. // // This event is only sent by the compositor if the touch device supports // orientation reports. type TouchOrientationEvent struct { Id int32 Orientation float64 } type TouchOrientationHandlerFunc func(TouchOrientationEvent) // SetOrientationHandler : sets handler for TouchOrientationEvent func (i *Touch) SetOrientationHandler(f TouchOrientationHandlerFunc) { i.orientationHandler = f } func (i *Touch) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.downHandler == nil { return } var e TouchDownEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Time = Uint32(data[l : l+4]) l += 4 e.Surface = i.Context().GetProxy(Uint32(data[l : l+4])).(*Surface) l += 4 e.Id = int32(Uint32(data[l : l+4])) l += 4 e.X = Fixed(data[l : l+4]) l += 4 e.Y = Fixed(data[l : l+4]) l += 4 i.downHandler(e) case 1: if i.upHandler == nil { return } var e TouchUpEvent l := 0 e.Serial = Uint32(data[l : l+4]) l += 4 e.Time = Uint32(data[l : l+4]) l += 4 e.Id = int32(Uint32(data[l : l+4])) l += 4 i.upHandler(e) case 2: if i.motionHandler == nil { return } var e TouchMotionEvent l := 0 e.Time = Uint32(data[l : l+4]) l += 4 e.Id = int32(Uint32(data[l : l+4])) l += 4 e.X = Fixed(data[l : l+4]) l += 4 e.Y = Fixed(data[l : l+4]) l += 4 i.motionHandler(e) case 3: if i.frameHandler == nil { return } var e TouchFrameEvent i.frameHandler(e) case 4: if i.cancelHandler == nil { return } var e TouchCancelEvent i.cancelHandler(e) case 5: if i.shapeHandler == nil { return } var e TouchShapeEvent l := 0 e.Id = int32(Uint32(data[l : l+4])) l += 4 e.Major = Fixed(data[l : l+4]) l += 4 e.Minor = Fixed(data[l : l+4]) l += 4 i.shapeHandler(e) case 6: if i.orientationHandler == nil { return } var e TouchOrientationEvent l := 0 e.Id = int32(Uint32(data[l : l+4])) l += 4 e.Orientation = Fixed(data[l : l+4]) l += 4 i.orientationHandler(e) } } // OutputInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const OutputInterfaceName = "wl_output" // Output : compositor output region // // An output describes part of the compositor geometry. The // compositor works in the 'compositor coordinate system' and an // output corresponds to a rectangular area in that space that is // actually visible. This typically corresponds to a monitor that // displays part of the compositor space. This object is published // as global during start up, or when a monitor is hotplugged. type Output struct { BaseProxy geometryHandler OutputGeometryHandlerFunc modeHandler OutputModeHandlerFunc doneHandler OutputDoneHandlerFunc scaleHandler OutputScaleHandlerFunc nameHandler OutputNameHandlerFunc descriptionHandler OutputDescriptionHandlerFunc } // NewOutput : compositor output region // // An output describes part of the compositor geometry. The // compositor works in the 'compositor coordinate system' and an // output corresponds to a rectangular area in that space that is // actually visible. This typically corresponds to a monitor that // displays part of the compositor space. This object is published // as global during start up, or when a monitor is hotplugged. func NewOutput(ctx *Context) *Output { wlOutput := &Output{} ctx.Register(wlOutput) return wlOutput } // Release : release the output object // // Using this request a client can tell the server that it is not going to // use the output object anymore. func (i *Output) Release() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type OutputSubpixel uint32 // OutputSubpixel : subpixel geometry information // // This enumeration describes how the physical // pixels on an output are laid out. const ( // OutputSubpixelUnknown : unknown geometry OutputSubpixelUnknown OutputSubpixel = 0 // OutputSubpixelNone : no geometry OutputSubpixelNone OutputSubpixel = 1 // OutputSubpixelHorizontalRgb : horizontal RGB OutputSubpixelHorizontalRgb OutputSubpixel = 2 // OutputSubpixelHorizontalBgr : horizontal BGR OutputSubpixelHorizontalBgr OutputSubpixel = 3 // OutputSubpixelVerticalRgb : vertical RGB OutputSubpixelVerticalRgb OutputSubpixel = 4 // OutputSubpixelVerticalBgr : vertical BGR OutputSubpixelVerticalBgr OutputSubpixel = 5 ) func (e OutputSubpixel) Name() string { switch e { case OutputSubpixelUnknown: return "unknown" case OutputSubpixelNone: return "none" case OutputSubpixelHorizontalRgb: return "horizontal_rgb" case OutputSubpixelHorizontalBgr: return "horizontal_bgr" case OutputSubpixelVerticalRgb: return "vertical_rgb" case OutputSubpixelVerticalBgr: return "vertical_bgr" default: return "" } } func (e OutputSubpixel) Value() string { switch e { case OutputSubpixelUnknown: return "0" case OutputSubpixelNone: return "1" case OutputSubpixelHorizontalRgb: return "2" case OutputSubpixelHorizontalBgr: return "3" case OutputSubpixelVerticalRgb: return "4" case OutputSubpixelVerticalBgr: return "5" default: return "" } } func (e OutputSubpixel) String() string { return e.Name() + "=" + e.Value() } type OutputTransform uint32 // OutputTransform : transformation applied to buffer contents // // This describes transformations that clients and compositors apply to // buffer contents. // // The flipped values correspond to an initial flip around a // vertical axis followed by rotation. // // The purpose is mainly to allow clients to render accordingly and // tell the compositor, so that for fullscreen surfaces, the // compositor will still be able to scan out directly from client // surfaces. const ( // OutputTransformNormal : no transform OutputTransformNormal OutputTransform = 0 // OutputTransform90 : 90 degrees counter-clockwise OutputTransform90 OutputTransform = 1 // OutputTransform180 : 180 degrees counter-clockwise OutputTransform180 OutputTransform = 2 // OutputTransform270 : 270 degrees counter-clockwise OutputTransform270 OutputTransform = 3 // OutputTransformFlipped : 180 degree flip around a vertical axis OutputTransformFlipped OutputTransform = 4 // OutputTransformFlipped90 : flip and rotate 90 degrees counter-clockwise OutputTransformFlipped90 OutputTransform = 5 // OutputTransformFlipped180 : flip and rotate 180 degrees counter-clockwise OutputTransformFlipped180 OutputTransform = 6 // OutputTransformFlipped270 : flip and rotate 270 degrees counter-clockwise OutputTransformFlipped270 OutputTransform = 7 ) func (e OutputTransform) Name() string { switch e { case OutputTransformNormal: return "normal" case OutputTransform90: return "90" case OutputTransform180: return "180" case OutputTransform270: return "270" case OutputTransformFlipped: return "flipped" case OutputTransformFlipped90: return "flipped_90" case OutputTransformFlipped180: return "flipped_180" case OutputTransformFlipped270: return "flipped_270" default: return "" } } func (e OutputTransform) Value() string { switch e { case OutputTransformNormal: return "0" case OutputTransform90: return "1" case OutputTransform180: return "2" case OutputTransform270: return "3" case OutputTransformFlipped: return "4" case OutputTransformFlipped90: return "5" case OutputTransformFlipped180: return "6" case OutputTransformFlipped270: return "7" default: return "" } } func (e OutputTransform) String() string { return e.Name() + "=" + e.Value() } type OutputMode uint32 // OutputMode : mode information // // These flags describe properties of an output mode. // They are used in the flags bitfield of the mode event. const ( // OutputModeCurrent : indicates this is the current mode OutputModeCurrent OutputMode = 0x1 // OutputModePreferred : indicates this is the preferred mode OutputModePreferred OutputMode = 0x2 ) func (e OutputMode) Name() string { switch e { case OutputModeCurrent: return "current" case OutputModePreferred: return "preferred" default: return "" } } func (e OutputMode) Value() string { switch e { case OutputModeCurrent: return "0x1" case OutputModePreferred: return "0x2" default: return "" } } func (e OutputMode) String() string { return e.Name() + "=" + e.Value() } // OutputGeometryEvent : properties of the output // // The geometry event describes geometric properties of the output. // The event is sent when binding to the output object and whenever // any of the properties change. // // The physical size can be set to zero if it doesn't make sense for this // output (e.g. for projectors or virtual outputs). // // The geometry event will be followed by a done event (starting from // version 2). // // Clients should use wl_surface.preferred_buffer_transform instead of the // transform advertised by this event to find the preferred buffer // transform to use for a surface. // // Note: wl_output only advertises partial information about the output // position and identification. Some compositors, for instance those not // implementing a desktop-style output layout or those exposing virtual // outputs, might fake this information. Instead of using x and y, clients // should use xdg_output.logical_position. Instead of using make and model, // clients should use name and description. type OutputGeometryEvent struct { X int32 Y int32 PhysicalWidth int32 PhysicalHeight int32 Subpixel int32 Make string Model string Transform int32 } type OutputGeometryHandlerFunc func(OutputGeometryEvent) // SetGeometryHandler : sets handler for OutputGeometryEvent func (i *Output) SetGeometryHandler(f OutputGeometryHandlerFunc) { i.geometryHandler = f } // OutputModeEvent : advertise available modes for the output // // The mode event describes an available mode for the output. // // The event is sent when binding to the output object and there // will always be one mode, the current mode. The event is sent // again if an output changes mode, for the mode that is now // current. In other words, the current mode is always the last // mode that was received with the current flag set. // // Non-current modes are deprecated. A compositor can decide to only // advertise the current mode and never send other modes. Clients // should not rely on non-current modes. // // The size of a mode is given in physical hardware units of // the output device. This is not necessarily the same as // the output size in the global compositor space. For instance, // the output may be scaled, as described in wl_output.scale, // or transformed, as described in wl_output.transform. Clients // willing to retrieve the output size in the global compositor // space should use xdg_output.logical_size instead. // // The vertical refresh rate can be set to zero if it doesn't make // sense for this output (e.g. for virtual outputs). // // The mode event will be followed by a done event (starting from // version 2). // // Clients should not use the refresh rate to schedule frames. Instead, // they should use the wl_surface.frame event or the presentation-time // protocol. // // Note: this information is not always meaningful for all outputs. Some // compositors, such as those exposing virtual outputs, might fake the // refresh rate or the size. type OutputModeEvent struct { Flags uint32 Width int32 Height int32 Refresh int32 } type OutputModeHandlerFunc func(OutputModeEvent) // SetModeHandler : sets handler for OutputModeEvent func (i *Output) SetModeHandler(f OutputModeHandlerFunc) { i.modeHandler = f } // OutputDoneEvent : sent all information about output // // This event is sent after all other properties have been // sent after binding to the output object and after any // other property changes done after that. This allows // changes to the output properties to be seen as // atomic, even if they happen via multiple events. type OutputDoneEvent struct{} type OutputDoneHandlerFunc func(OutputDoneEvent) // SetDoneHandler : sets handler for OutputDoneEvent func (i *Output) SetDoneHandler(f OutputDoneHandlerFunc) { i.doneHandler = f } // OutputScaleEvent : output scaling properties // // This event contains scaling geometry information // that is not in the geometry event. It may be sent after // binding the output object or if the output scale changes // later. The compositor will emit a non-zero, positive // value for scale. If it is not sent, the client should // assume a scale of 1. // // A scale larger than 1 means that the compositor will // automatically scale surface buffers by this amount // when rendering. This is used for very high resolution // displays where applications rendering at the native // resolution would be too small to be legible. // // Clients should use wl_surface.preferred_buffer_scale // instead of this event to find the preferred buffer // scale to use for a surface. // // The scale event will be followed by a done event. type OutputScaleEvent struct { Factor int32 } type OutputScaleHandlerFunc func(OutputScaleEvent) // SetScaleHandler : sets handler for OutputScaleEvent func (i *Output) SetScaleHandler(f OutputScaleHandlerFunc) { i.scaleHandler = f } // OutputNameEvent : name of this output // // Many compositors will assign user-friendly names to their outputs, show // them to the user, allow the user to refer to an output, etc. The client // may wish to know this name as well to offer the user similar behaviors. // // The name is a UTF-8 string with no convention defined for its contents. // Each name is unique among all wl_output globals. The name is only // guaranteed to be unique for the compositor instance. // // The same output name is used for all clients for a given wl_output // global. Thus, the name can be shared across processes to refer to a // specific wl_output global. // // The name is not guaranteed to be persistent across sessions, thus cannot // be used to reliably identify an output in e.g. configuration files. // // Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do // not assume that the name is a reflection of an underlying DRM connector, // X11 connection, etc. // // The name event is sent after binding the output object. This event is // only sent once per output object, and the name does not change over the // lifetime of the wl_output global. // // Compositors may re-use the same output name if the wl_output global is // destroyed and re-created later. Compositors should avoid re-using the // same name if possible. // // The name event will be followed by a done event. type OutputNameEvent struct { Name string } type OutputNameHandlerFunc func(OutputNameEvent) // SetNameHandler : sets handler for OutputNameEvent func (i *Output) SetNameHandler(f OutputNameHandlerFunc) { i.nameHandler = f } // OutputDescriptionEvent : human-readable description of this output // // Many compositors can produce human-readable descriptions of their // outputs. The client may wish to know this description as well, e.g. for // output selection purposes. // // The description is a UTF-8 string with no convention defined for its // contents. The description is not guaranteed to be unique among all // wl_output globals. Examples might include 'Foocorp 11" Display' or // 'Virtual X11 output via :1'. // // The description event is sent after binding the output object and // whenever the description changes. The description is optional, and may // not be sent at all. // // The description event will be followed by a done event. type OutputDescriptionEvent struct { Description string } type OutputDescriptionHandlerFunc func(OutputDescriptionEvent) // SetDescriptionHandler : sets handler for OutputDescriptionEvent func (i *Output) SetDescriptionHandler(f OutputDescriptionHandlerFunc) { i.descriptionHandler = f } func (i *Output) Dispatch(opcode uint32, fd int, data []byte) { switch opcode { case 0: if i.geometryHandler == nil { return } var e OutputGeometryEvent l := 0 e.X = int32(Uint32(data[l : l+4])) l += 4 e.Y = int32(Uint32(data[l : l+4])) l += 4 e.PhysicalWidth = int32(Uint32(data[l : l+4])) l += 4 e.PhysicalHeight = int32(Uint32(data[l : l+4])) l += 4 e.Subpixel = int32(Uint32(data[l : l+4])) l += 4 makeLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Make = String(data[l : l+makeLen]) l += makeLen modelLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Model = String(data[l : l+modelLen]) l += modelLen e.Transform = int32(Uint32(data[l : l+4])) l += 4 i.geometryHandler(e) case 1: if i.modeHandler == nil { return } var e OutputModeEvent l := 0 e.Flags = Uint32(data[l : l+4]) l += 4 e.Width = int32(Uint32(data[l : l+4])) l += 4 e.Height = int32(Uint32(data[l : l+4])) l += 4 e.Refresh = int32(Uint32(data[l : l+4])) l += 4 i.modeHandler(e) case 2: if i.doneHandler == nil { return } var e OutputDoneEvent i.doneHandler(e) case 3: if i.scaleHandler == nil { return } var e OutputScaleEvent l := 0 e.Factor = int32(Uint32(data[l : l+4])) l += 4 i.scaleHandler(e) case 4: if i.nameHandler == nil { return } var e OutputNameEvent l := 0 nameLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Name = String(data[l : l+nameLen]) l += nameLen i.nameHandler(e) case 5: if i.descriptionHandler == nil { return } var e OutputDescriptionEvent l := 0 descriptionLen := PaddedLen(int(Uint32(data[l : l+4]))) l += 4 e.Description = String(data[l : l+descriptionLen]) l += descriptionLen i.descriptionHandler(e) } } // RegionInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const RegionInterfaceName = "wl_region" // Region : region interface // // A region object describes an area. // // Region objects are used to describe the opaque and input // regions of a surface. type Region struct { BaseProxy } // NewRegion : region interface // // A region object describes an area. // // Region objects are used to describe the opaque and input // regions of a surface. func NewRegion(ctx *Context) *Region { wlRegion := &Region{} ctx.Register(wlRegion) return wlRegion } // Destroy : destroy region // // Destroy the region. This will invalidate the object ID. func (i *Region) Destroy() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Add : add rectangle to region // // Add the specified rectangle to the region. // // x: region-local x coordinate // y: region-local y coordinate // width: rectangle width // height: rectangle height func (i *Region) Add(x, y, width, height int32) error { const opcode = 1 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(width)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(height)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // Subtract : subtract rectangle from region // // Subtract the specified rectangle from the region. // // x: region-local x coordinate // y: region-local y coordinate // width: rectangle width // height: rectangle height func (i *Region) Subtract(x, y, width, height int32) error { const opcode = 2 const _reqBufLen = 8 + 4 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(width)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(height)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SubcompositorInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const SubcompositorInterfaceName = "wl_subcompositor" // Subcompositor : sub-surface compositing // // The global interface exposing sub-surface compositing capabilities. // A wl_surface, that has sub-surfaces associated, is called the // parent surface. Sub-surfaces can be arbitrarily nested and create // a tree of sub-surfaces. // // The root surface in a tree of sub-surfaces is the main // surface. The main surface cannot be a sub-surface, because // sub-surfaces must always have a parent. // // A main surface with its sub-surfaces forms a (compound) window. // For window management purposes, this set of wl_surface objects is // to be considered as a single window, and it should also behave as // such. // // The aim of sub-surfaces is to offload some of the compositing work // within a window from clients to the compositor. A prime example is // a video player with decorations and video in separate wl_surface // objects. This should allow the compositor to pass YUV video buffer // processing to dedicated overlay hardware when possible. type Subcompositor struct { BaseProxy } // NewSubcompositor : sub-surface compositing // // The global interface exposing sub-surface compositing capabilities. // A wl_surface, that has sub-surfaces associated, is called the // parent surface. Sub-surfaces can be arbitrarily nested and create // a tree of sub-surfaces. // // The root surface in a tree of sub-surfaces is the main // surface. The main surface cannot be a sub-surface, because // sub-surfaces must always have a parent. // // A main surface with its sub-surfaces forms a (compound) window. // For window management purposes, this set of wl_surface objects is // to be considered as a single window, and it should also behave as // such. // // The aim of sub-surfaces is to offload some of the compositing work // within a window from clients to the compositor. A prime example is // a video player with decorations and video in separate wl_surface // objects. This should allow the compositor to pass YUV video buffer // processing to dedicated overlay hardware when possible. func NewSubcompositor(ctx *Context) *Subcompositor { wlSubcompositor := &Subcompositor{} ctx.Register(wlSubcompositor) return wlSubcompositor } // Destroy : unbind from the subcompositor interface // // Informs the server that the client will not be using this // protocol object anymore. This does not affect any other // objects, wl_subsurface objects included. func (i *Subcompositor) Destroy() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // GetSubsurface : give a surface the role sub-surface // // Create a sub-surface interface for the given surface, and // associate it with the given parent surface. This turns a // plain wl_surface into a sub-surface. // // The to-be sub-surface must not already have another role, and it // must not have an existing wl_subsurface object. Otherwise the // bad_surface protocol error is raised. // // Adding sub-surfaces to a parent is a double-buffered operation on the // parent (see wl_surface.commit). The effect of adding a sub-surface // becomes visible on the next time the state of the parent surface is // applied. // // The parent surface must not be one of the child surface's descendants, // and the parent must be different from the child surface, otherwise the // bad_parent protocol error is raised. // // This request modifies the behaviour of wl_surface.commit request on // the sub-surface, see the documentation on wl_subsurface interface. // // surface: the surface to be turned into a sub-surface // parent: the parent surface func (i *Subcompositor) GetSubsurface(surface, parent *Surface) (*Subsurface, error) { id := NewSubsurface(i.Context()) const opcode = 1 const _reqBufLen = 8 + 4 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], id.ID()) l += 4 PutUint32(_reqBuf[l:l+4], surface.ID()) l += 4 PutUint32(_reqBuf[l:l+4], parent.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return id, err } type SubcompositorError uint32 // SubcompositorError : const ( // SubcompositorErrorBadSurface : the to-be sub-surface is invalid SubcompositorErrorBadSurface SubcompositorError = 0 // SubcompositorErrorBadParent : the to-be sub-surface parent is invalid SubcompositorErrorBadParent SubcompositorError = 1 ) func (e SubcompositorError) Name() string { switch e { case SubcompositorErrorBadSurface: return "bad_surface" case SubcompositorErrorBadParent: return "bad_parent" default: return "" } } func (e SubcompositorError) Value() string { switch e { case SubcompositorErrorBadSurface: return "0" case SubcompositorErrorBadParent: return "1" default: return "" } } func (e SubcompositorError) String() string { return e.Name() + "=" + e.Value() } // SubsurfaceInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const SubsurfaceInterfaceName = "wl_subsurface" // Subsurface : sub-surface interface to a wl_surface // // An additional interface to a wl_surface object, which has been // made a sub-surface. A sub-surface has one parent surface. A // sub-surface's size and position are not limited to that of the parent. // Particularly, a sub-surface is not automatically clipped to its // parent's area. // // A sub-surface becomes mapped, when a non-NULL wl_buffer is applied // and the parent surface is mapped. The order of which one happens // first is irrelevant. A sub-surface is hidden if the parent becomes // hidden, or if a NULL wl_buffer is applied. These rules apply // recursively through the tree of surfaces. // // The behaviour of a wl_surface.commit request on a sub-surface // depends on the sub-surface's mode. The possible modes are // synchronized and desynchronized, see methods // wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized // mode caches the wl_surface state to be applied when the parent's // state gets applied, and desynchronized mode applies the pending // wl_surface state directly. A sub-surface is initially in the // synchronized mode. // // Sub-surfaces also have another kind of state, which is managed by // wl_subsurface requests, as opposed to wl_surface requests. This // state includes the sub-surface position relative to the parent // surface (wl_subsurface.set_position), and the stacking order of // the parent and its sub-surfaces (wl_subsurface.place_above and // .place_below). This state is applied when the parent surface's // wl_surface state is applied, regardless of the sub-surface's mode. // As the exception, set_sync and set_desync are effective immediately. // // The main surface can be thought to be always in desynchronized mode, // since it does not have a parent in the sub-surfaces sense. // // Even if a sub-surface is in desynchronized mode, it will behave as // in synchronized mode, if its parent surface behaves as in // synchronized mode. This rule is applied recursively throughout the // tree of surfaces. This means, that one can set a sub-surface into // synchronized mode, and then assume that all its child and grand-child // sub-surfaces are synchronized, too, without explicitly setting them. // // Destroying a sub-surface takes effect immediately. If you need to // synchronize the removal of a sub-surface to the parent surface update, // unmap the sub-surface first by attaching a NULL wl_buffer, update parent, // and then destroy the sub-surface. // // If the parent wl_surface object is destroyed, the sub-surface is // unmapped. // // A sub-surface never has the keyboard focus of any seat. // // The wl_surface.offset request is ignored: clients must use set_position // instead to move the sub-surface. type Subsurface struct { BaseProxy } // NewSubsurface : sub-surface interface to a wl_surface // // An additional interface to a wl_surface object, which has been // made a sub-surface. A sub-surface has one parent surface. A // sub-surface's size and position are not limited to that of the parent. // Particularly, a sub-surface is not automatically clipped to its // parent's area. // // A sub-surface becomes mapped, when a non-NULL wl_buffer is applied // and the parent surface is mapped. The order of which one happens // first is irrelevant. A sub-surface is hidden if the parent becomes // hidden, or if a NULL wl_buffer is applied. These rules apply // recursively through the tree of surfaces. // // The behaviour of a wl_surface.commit request on a sub-surface // depends on the sub-surface's mode. The possible modes are // synchronized and desynchronized, see methods // wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized // mode caches the wl_surface state to be applied when the parent's // state gets applied, and desynchronized mode applies the pending // wl_surface state directly. A sub-surface is initially in the // synchronized mode. // // Sub-surfaces also have another kind of state, which is managed by // wl_subsurface requests, as opposed to wl_surface requests. This // state includes the sub-surface position relative to the parent // surface (wl_subsurface.set_position), and the stacking order of // the parent and its sub-surfaces (wl_subsurface.place_above and // .place_below). This state is applied when the parent surface's // wl_surface state is applied, regardless of the sub-surface's mode. // As the exception, set_sync and set_desync are effective immediately. // // The main surface can be thought to be always in desynchronized mode, // since it does not have a parent in the sub-surfaces sense. // // Even if a sub-surface is in desynchronized mode, it will behave as // in synchronized mode, if its parent surface behaves as in // synchronized mode. This rule is applied recursively throughout the // tree of surfaces. This means, that one can set a sub-surface into // synchronized mode, and then assume that all its child and grand-child // sub-surfaces are synchronized, too, without explicitly setting them. // // Destroying a sub-surface takes effect immediately. If you need to // synchronize the removal of a sub-surface to the parent surface update, // unmap the sub-surface first by attaching a NULL wl_buffer, update parent, // and then destroy the sub-surface. // // If the parent wl_surface object is destroyed, the sub-surface is // unmapped. // // A sub-surface never has the keyboard focus of any seat. // // The wl_surface.offset request is ignored: clients must use set_position // instead to move the sub-surface. func NewSubsurface(ctx *Context) *Subsurface { wlSubsurface := &Subsurface{} ctx.Register(wlSubsurface) return wlSubsurface } // Destroy : remove sub-surface interface // // The sub-surface interface is removed from the wl_surface object // that was turned into a sub-surface with a // wl_subcompositor.get_subsurface request. The wl_surface's association // to the parent is deleted. The wl_surface is unmapped immediately. func (i *Subsurface) Destroy() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetPosition : reposition the sub-surface // // This schedules a sub-surface position change. // The sub-surface will be moved so that its origin (top left // corner pixel) will be at the location x, y of the parent surface // coordinate system. The coordinates are not restricted to the parent // surface area. Negative values are allowed. // // The scheduled coordinates will take effect whenever the state of the // parent surface is applied. // // If more than one set_position request is invoked by the client before // the commit of the parent surface, the position of a new request always // replaces the scheduled position from any previous request. // // The initial position is 0, 0. // // x: x coordinate in the parent surface // y: y coordinate in the parent surface func (i *Subsurface) SetPosition(x, y int32) error { const opcode = 1 const _reqBufLen = 8 + 4 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(x)) l += 4 PutUint32(_reqBuf[l:l+4], uint32(y)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // PlaceAbove : restack the sub-surface // // This sub-surface is taken from the stack, and put back just // above the reference surface, changing the z-order of the sub-surfaces. // The reference surface must be one of the sibling surfaces, or the // parent surface. Using any other surface, including this sub-surface, // will cause a protocol error. // // The z-order is double-buffered. Requests are handled in order and // applied immediately to a pending state. The final pending state is // copied to the active state the next time the state of the parent // surface is applied. // // A new sub-surface is initially added as the top-most in the stack // of its siblings and parent. // // sibling: the reference surface func (i *Subsurface) PlaceAbove(sibling *Surface) error { const opcode = 2 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], sibling.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // PlaceBelow : restack the sub-surface // // The sub-surface is placed just below the reference surface. // See wl_subsurface.place_above. // // sibling: the reference surface func (i *Subsurface) PlaceBelow(sibling *Surface) error { const opcode = 3 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], sibling.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetSync : set sub-surface to synchronized mode // // Change the commit behaviour of the sub-surface to synchronized // mode, also described as the parent dependent mode. // // In synchronized mode, wl_surface.commit on a sub-surface will // accumulate the committed state in a cache, but the state will // not be applied and hence will not change the compositor output. // The cached state is applied to the sub-surface immediately after // the parent surface's state is applied. This ensures atomic // updates of the parent and all its synchronized sub-surfaces. // Applying the cached state will invalidate the cache, so further // parent surface commits do not (re-)apply old state. // // See wl_subsurface for the recursive effect of this mode. func (i *Subsurface) SetSync() error { const opcode = 4 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // SetDesync : set sub-surface to desynchronized mode // // Change the commit behaviour of the sub-surface to desynchronized // mode, also described as independent or freely running mode. // // In desynchronized mode, wl_surface.commit on a sub-surface will // apply the pending state directly, without caching, as happens // normally with a wl_surface. Calling wl_surface.commit on the // parent surface has no effect on the sub-surface's wl_surface // state. This mode allows a sub-surface to be updated on its own. // // If cached state exists when wl_surface.commit is called in // desynchronized mode, the pending state is added to the cached // state, and applied as a whole. This invalidates the cache. // // Note: even if a sub-surface is set to desynchronized, a parent // sub-surface may override it to behave as synchronized. For details, // see wl_subsurface. // // If a surface's parent surface behaves as desynchronized, then // the cached state is applied on set_desync. func (i *Subsurface) SetDesync() error { const opcode = 5 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } type SubsurfaceError uint32 // SubsurfaceError : const ( // SubsurfaceErrorBadSurface : wl_surface is not a sibling or the parent SubsurfaceErrorBadSurface SubsurfaceError = 0 ) func (e SubsurfaceError) Name() string { switch e { case SubsurfaceErrorBadSurface: return "bad_surface" default: return "" } } func (e SubsurfaceError) Value() string { switch e { case SubsurfaceErrorBadSurface: return "0" default: return "" } } func (e SubsurfaceError) String() string { return e.Name() + "=" + e.Value() } // FixesInterfaceName is the name of the interface as it appears in the [client.Registry]. // It can be used to match the [client.RegistryGlobalEvent.Interface] in the // [Registry.SetGlobalHandler] and can be used in [Registry.Bind] if this applies. const FixesInterfaceName = "wl_fixes" // Fixes : wayland protocol fixes // // This global fixes problems with other core-protocol interfaces that // cannot be fixed in these interfaces themselves. type Fixes struct { BaseProxy } // NewFixes : wayland protocol fixes // // This global fixes problems with other core-protocol interfaces that // cannot be fixed in these interfaces themselves. func NewFixes(ctx *Context) *Fixes { wlFixes := &Fixes{} ctx.Register(wlFixes) return wlFixes } // Destroy : destroys this object func (i *Fixes) Destroy() error { defer i.MarkZombie() const opcode = 0 const _reqBufLen = 8 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err } // DestroyRegistry : destroy a wl_registry // // This request destroys a wl_registry object. // // The client should no longer use the wl_registry after making this // request. // // The compositor will emit a wl_display.delete_id event with the object ID // of the registry and will no longer emit any events on the registry. The // client should re-use the object ID once it receives the // wl_display.delete_id event. // // registry: the registry to destroy func (i *Fixes) DestroyRegistry(registry *Registry) error { const opcode = 1 const _reqBufLen = 8 + 4 var _reqBuf [_reqBufLen]byte l := 0 PutUint32(_reqBuf[l:4], i.ID()) l += 4 PutUint32(_reqBuf[l:l+4], uint32(_reqBufLen<<16|opcode&0x0000ffff)) l += 4 PutUint32(_reqBuf[l:l+4], registry.ID()) l += 4 err := i.Context().WriteMsg(_reqBuf[:], nil) return err }