system/internal/xcb: refactor and clean up
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 1m52s
Test / Hakurei (push) Successful in 3m16s
Test / Hpkg (push) Successful in 3m39s
Test / Sandbox (race detector) (push) Successful in 4m17s
Test / Hakurei (race detector) (push) Successful in 5m22s
Test / Flake checks (push) Successful in 1m36s

This package still does not deserve to be out of internal, but at least it is less haunting now. I am still not handling the xcb error though, the struct is almost entirely undocumented and the implementation is unreadable. Not even going to try.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-08-30 20:02:18 +09:00
parent b12c290f12
commit ddb003e39b
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
2 changed files with 55 additions and 57 deletions

View File

@ -1,21 +1,16 @@
// Package xcb implements X11 ChangeHosts via libxcb.
package xcb package xcb
import ( import "errors"
"errors"
)
var ErrChangeHosts = errors.New("xcb_change_hosts() failed") var ErrChangeHosts = errors.New("xcb_change_hosts() failed")
func ChangeHosts(mode HostMode, family Family, address string) error { func ChangeHosts(mode HostMode, family Family, address string) error {
var conn *connection conn := new(connection)
if err := conn.connect(); err != nil {
if c, err := connect(); err != nil { conn.disconnect()
c.disconnect()
return err return err
} else { } else {
defer c.disconnect() defer conn.disconnect()
conn = c
} }
return conn.changeHostsChecked(mode, family, address) return conn.changeHostsChecked(mode, family, address)

View File

@ -1,3 +1,4 @@
// Package xcb implements X11 ChangeHosts via libxcb.
package xcb package xcb
import ( import (
@ -11,22 +12,28 @@ import (
#include <stdlib.h> #include <stdlib.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
static int _go_xcb_change_hosts_checked(xcb_connection_t *c, uint8_t mode, uint8_t family, uint16_t address_len, const uint8_t *address) { static int hakurei_xcb_change_hosts_checked(xcb_connection_t *c,
xcb_void_cookie_t cookie = xcb_change_hosts_checked(c, mode, family, address_len, address); uint8_t mode, uint8_t family,
free((void *)address); uint16_t address_len, const uint8_t *address) {
int ret;
xcb_generic_error_t *e;
xcb_void_cookie_t cookie;
int errno = xcb_connection_has_error(c); cookie = xcb_change_hosts_checked(c, mode, family, address_len, address);
if (errno != 0) free((void *)address);
return errno;
xcb_generic_error_t *e = xcb_request_check(c, cookie); ret = xcb_connection_has_error(c);
if (e != NULL) { if (ret != 0)
// don't want to deal with xcb errors return ret;
free((void *)e);
return -1;
}
return 0; 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" import "C"
@ -48,49 +55,60 @@ type (
) )
func (conn *connection) changeHostsChecked(mode HostMode, family Family, address string) error { func (conn *connection) changeHostsChecked(mode HostMode, family Family, address string) error {
errno := C._go_xcb_change_hosts_checked( ret := C.hakurei_xcb_change_hosts_checked(
conn.c, conn.c,
C.uint8_t(mode), C.uint8_t(mode),
C.uint8_t(family), C.uint8_t(family),
C.uint16_t(len(address)), C.uint16_t(len(address)),
(*C.uint8_t)(unsafe.Pointer(C.CString(address))), (*C.uint8_t)(unsafe.Pointer(C.CString(address))),
) )
switch errno { switch ret {
case 0: case 0:
return nil return nil
case -1: case -1:
return ErrChangeHosts return ErrChangeHosts
default: default:
return &ConnectionError{errno} return ConnectionError(ret)
} }
} }
type connection struct{ c *C.xcb_connection_t } type connection struct{ c *C.xcb_connection_t }
func connect() (*connection, error) { func (conn *connection) connect() error {
conn := newConnection(C.xcb_connect(nil, nil)) conn.c = C.xcb_connect(nil, nil)
return conn, conn.hasError() runtime.SetFinalizer(conn, (*connection).disconnect)
return conn.hasError()
} }
func newConnection(c *C.xcb_connection_t) *connection { func (conn *connection) hasError() error {
conn := &connection{c} ret := C.xcb_connection_has_error(conn.c)
runtime.SetFinalizer(conn, (*connection).disconnect) if ret == 0 {
return conn 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 ( const (
ConnError = C.XCB_CONN_ERROR ConnError ConnectionError = C.XCB_CONN_ERROR
ConnClosedExtNotSupported = C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED ConnClosedExtNotSupported ConnectionError = C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED
ConnClosedMemInsufficient = C.XCB_CONN_CLOSED_MEM_INSUFFICIENT ConnClosedMemInsufficient ConnectionError = C.XCB_CONN_CLOSED_MEM_INSUFFICIENT
ConnClosedReqLenExceed = C.XCB_CONN_CLOSED_REQ_LEN_EXCEED ConnClosedReqLenExceed ConnectionError = C.XCB_CONN_CLOSED_REQ_LEN_EXCEED
ConnClosedParseErr = C.XCB_CONN_CLOSED_PARSE_ERR ConnClosedParseErr ConnectionError = C.XCB_CONN_CLOSED_PARSE_ERR
ConnClosedInvalidScreen = C.XCB_CONN_CLOSED_INVALID_SCREEN ConnClosedInvalidScreen ConnectionError = C.XCB_CONN_CLOSED_INVALID_SCREEN
) )
type ConnectionError struct{ errno C.int } // ConnectionError represents an error returned by xcb_connection_has_error.
type ConnectionError int
func (ce *ConnectionError) Error() string { func (ce ConnectionError) Error() string {
switch ce.errno { switch ce {
case ConnError: case ConnError:
return "connection error" return "connection error"
case ConnClosedExtNotSupported: case ConnClosedExtNotSupported:
@ -107,18 +125,3 @@ func (ce *ConnectionError) Error() string {
return "generic X11 failure" return "generic X11 failure"
} }
} }
func (conn *connection) hasError() error {
errno := C.xcb_connection_has_error(conn.c)
if errno == 0 {
return nil
}
return &ConnectionError{errno}
}
func (conn *connection) disconnect() {
C.xcb_disconnect(conn.c)
// no need for a finalizer anymore
runtime.SetFinalizer(conn, nil)
}