mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
7542 lines
237 KiB
Go
7542 lines
237 KiB
Go
// 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.Context().Unregister(i)
|
|
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:
|
|
if i.deleteIdHandler == nil {
|
|
return
|
|
}
|
|
var e DisplayDeleteIdEvent
|
|
l := 0
|
|
e.Id = Uint32(data[l : l+4])
|
|
l += 4
|
|
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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.Context().Unregister(i)
|
|
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
|
|
}
|