aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-07-14 18:31:53 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-07-14 18:31:53 +0900
commit518fd54ff3c7fe718f81a995f75913d1fdd6fc31 (patch)
treed7bf81b9fe4aad134993fe74694b8a96b9ea314d
parent65c02b540d616b3752a2eb5da110541f728d6cbe (diff)
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 <cat@ophivana.moe>
-rw-r--r--acl.go1
-rw-r--r--x11.go72
2 files changed, 72 insertions, 1 deletions
diff --git a/acl.go b/acl.go
index f1f496e5..d176d813 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 00000000..d25155e3
--- /dev/null
+++ b/x11.go
@@ -0,0 +1,72 @@
+package main
+
+import "C"
+import (
+ "errors"
+ "unsafe"
+)
+
+//#include <stdlib.h>
+//#include <xcb/xcb.h>
+//#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
+ }
+}