From 518fd54ff3c7fe718f81a995f75913d1fdd6fc31 Mon Sep 17 00:00:00 2001 From: Ophestra Umiker Date: Sun, 14 Jul 2024 18:31:53 +0900 Subject: [PATCH] x11: wrap libxcb ChangeHosts request Even though many pure Go libxcb implementations exist, it is at least as complex and unreadable as libxcb, if not more. Since well known libraries like SDL, qt and gtk uses libxcb, and they somehow understand how to use it, I can only assume these people have read enough code to make sure it's correct enough. Call it wishful thinking. I don't care anymore. Signed-off-by: Ophestra Umiker --- acl.go | 1 - x11.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 x11.go diff --git a/acl.go b/acl.go index f1f496e..d176d81 100644 --- a/acl.go +++ b/acl.go @@ -1,6 +1,5 @@ package main -import "C" import ( "errors" "fmt" diff --git a/x11.go b/x11.go new file mode 100644 index 0000000..d25155e --- /dev/null +++ b/x11.go @@ -0,0 +1,72 @@ +package main + +import "C" +import ( + "errors" + "unsafe" +) + +//#include +//#include +//#cgo linux LDFLAGS: -lxcb +import "C" + +const ( + xcbHostModeInsert = C.XCB_HOST_MODE_INSERT + xcbHostModeDelete = C.XCB_HOST_MODE_DELETE + + xcbFamilyInternet = C.XCB_FAMILY_INTERNET + xcbFamilyDecnet = C.XCB_FAMILY_DECNET + xcbFamilyChaos = C.XCB_FAMILY_CHAOS + xcbFamilyServerInterpreted = C.XCB_FAMILY_SERVER_INTERPRETED + xcbFamilyInternet6 = C.XCB_FAMILY_INTERNET_6 +) + +func changeHosts(mode, family C.uint8_t, address string) error { + var c *C.xcb_connection_t + c = C.xcb_connect(nil, nil) + defer C.xcb_disconnect(c) + + if err := xcbHandleConnectionError(c); err != nil { + return err + } + + addr := C.CString(address) + cookie := C.xcb_change_hosts_checked(c, mode, family, C.ushort(len(address)), (*C.uchar)(unsafe.Pointer(addr))) + C.free(unsafe.Pointer(addr)) + + if err := xcbHandleConnectionError(c); err != nil { + return err + } + + e := C.xcb_request_check(c, cookie) + if e != nil { + defer C.free(unsafe.Pointer(e)) + return errors.New("xcb_change_hosts() failed") + } + + return nil +} + +func xcbHandleConnectionError(c *C.xcb_connection_t) error { + if errno := C.xcb_connection_has_error(c); errno != 0 { + switch errno { + case C.XCB_CONN_ERROR: + return errors.New("connection error") + case C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED: + return errors.New("extension not supported") + case C.XCB_CONN_CLOSED_MEM_INSUFFICIENT: + return errors.New("memory not available") + case C.XCB_CONN_CLOSED_REQ_LEN_EXCEED: + return errors.New("request length exceeded") + case C.XCB_CONN_CLOSED_PARSE_ERR: + return errors.New("invalid display string") + case C.XCB_CONN_CLOSED_INVALID_SCREEN: + return errors.New("server has no screen matching display") + default: + return errors.New("generic X11 failure") + } + } else { + return nil + } +}