diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-11-15 13:47:09 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-11-15 13:58:34 +0900 |
| commit | a91920310d20e1fc472dea044fce8fd9438835df (patch) | |
| tree | 378cba47d8586e798130a2855f91a685e05244a3 /internal/xcb | |
| parent | 16e674782abbda8c85eac2e7d0c5c22e8cfbf5de (diff) | |
internal: relocate packages
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/xcb')
| -rw-r--r-- | internal/xcb/changehosts.go | 17 | ||||
| -rw-r--r-- | internal/xcb/xcb.go | 127 |
2 files changed, 144 insertions, 0 deletions
diff --git a/internal/xcb/changehosts.go b/internal/xcb/changehosts.go new file mode 100644 index 00000000..8b05614b --- /dev/null +++ b/internal/xcb/changehosts.go @@ -0,0 +1,17 @@ +package xcb + +import "errors" + +var ErrChangeHosts = errors.New("xcb_change_hosts() failed") + +func ChangeHosts(mode HostMode, family Family, address string) error { + conn := new(connection) + if err := conn.connect(); err != nil { + conn.disconnect() + return err + } else { + defer conn.disconnect() + } + + return conn.changeHostsChecked(mode, family, address) +} diff --git a/internal/xcb/xcb.go b/internal/xcb/xcb.go new file mode 100644 index 00000000..3dc62c3f --- /dev/null +++ b/internal/xcb/xcb.go @@ -0,0 +1,127 @@ +// Package xcb implements X11 ChangeHosts via libxcb. +package xcb + +import ( + "runtime" + "unsafe" +) + +/* +#cgo linux pkg-config: --static xcb + +#include <stdlib.h> +#include <xcb/xcb.h> + +static int hakurei_xcb_change_hosts_checked(xcb_connection_t *c, + uint8_t mode, uint8_t family, + uint16_t address_len, const uint8_t *address) { + int ret; + xcb_generic_error_t *e; + xcb_void_cookie_t cookie; + + cookie = xcb_change_hosts_checked(c, mode, family, address_len, address); + free((void *)address); + + ret = xcb_connection_has_error(c); + if (ret != 0) + return ret; + + e = xcb_request_check(c, cookie); + if (e != NULL) { + // don't want to deal with xcb errors + free((void *)e); + ret = -1; + } + + return ret; +} +*/ +import "C" + +const ( + HostModeInsert = C.XCB_HOST_MODE_INSERT + HostModeDelete = C.XCB_HOST_MODE_DELETE + + FamilyInternet = C.XCB_FAMILY_INTERNET + FamilyDecnet = C.XCB_FAMILY_DECNET + FamilyChaos = C.XCB_FAMILY_CHAOS + FamilyServerInterpreted = C.XCB_FAMILY_SERVER_INTERPRETED + FamilyInternet6 = C.XCB_FAMILY_INTERNET_6 +) + +type ( + HostMode = C.xcb_host_mode_t + Family = C.xcb_family_t +) + +func (conn *connection) changeHostsChecked(mode HostMode, family Family, address string) error { + ret := C.hakurei_xcb_change_hosts_checked( + conn.c, + C.uint8_t(mode), + C.uint8_t(family), + C.uint16_t(len(address)), + (*C.uint8_t)(unsafe.Pointer(C.CString(address))), + ) + switch ret { + case 0: + return nil + case -1: + return ErrChangeHosts + default: + return ConnectionError(ret) + } +} + +type connection struct{ c *C.xcb_connection_t } + +func (conn *connection) connect() error { + conn.c = C.xcb_connect(nil, nil) + runtime.SetFinalizer(conn, (*connection).disconnect) + return conn.hasError() +} + +func (conn *connection) hasError() error { + ret := C.xcb_connection_has_error(conn.c) + if ret == 0 { + return nil + } + return ConnectionError(ret) +} + +func (conn *connection) disconnect() { + C.xcb_disconnect(conn.c) + + // no need for a finalizer anymore + runtime.SetFinalizer(conn, nil) +} + +const ( + ConnError ConnectionError = C.XCB_CONN_ERROR + ConnClosedExtNotSupported ConnectionError = C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED + ConnClosedMemInsufficient ConnectionError = C.XCB_CONN_CLOSED_MEM_INSUFFICIENT + ConnClosedReqLenExceed ConnectionError = C.XCB_CONN_CLOSED_REQ_LEN_EXCEED + ConnClosedParseErr ConnectionError = C.XCB_CONN_CLOSED_PARSE_ERR + ConnClosedInvalidScreen ConnectionError = C.XCB_CONN_CLOSED_INVALID_SCREEN +) + +// ConnectionError represents an error returned by xcb_connection_has_error. +type ConnectionError int + +func (ce ConnectionError) Error() string { + switch ce { + case ConnError: + return "connection error" + case ConnClosedExtNotSupported: + return "extension not supported" + case ConnClosedMemInsufficient: + return "memory not available" + case ConnClosedReqLenExceed: + return "request length exceeded" + case ConnClosedParseErr: + return "invalid display string" + case ConnClosedInvalidScreen: + return "server has no screen matching display" + default: + return "generic X11 failure" + } +} |
