diff --git a/internal/desktop/xevent/xevent.c b/internal/desktop/xevent/xevent.c new file mode 100644 index 00000000..d7dfe5f1 --- /dev/null +++ b/internal/desktop/xevent/xevent.c @@ -0,0 +1,45 @@ +#include "xevent.h" + +static int XEventError(Display *display, XErrorEvent *event) { + char message[100]; + + int error; + error = XGetErrorText(display, event->error_code, message, sizeof(message)); + if (error) { + goXEventError(event, "Could not get error message."); + } else { + goXEventError(event, message); + } + + return 1; +} + +void XEventLoop(char *name) { + Display *display = XOpenDisplay(name); + Window root = RootWindow(display, 0); + + int xfixes_event_base, xfixes_error_base; + if (!XFixesQueryExtension(display, &xfixes_event_base, &xfixes_error_base)) { + return; + } + + XFixesSelectCursorInput(display, root, XFixesDisplayCursorNotifyMask); + XSync(display, 0); + XSetErrorHandler(XEventError); + + while (goXEventActive()) { + XEvent event; + XNextEvent(display, &event); + + // XFixesDisplayCursorNotify + if (event.type == xfixes_event_base + 1) { + XFixesCursorNotifyEvent notifyEvent = *((XFixesCursorNotifyEvent *) &event); + if (notifyEvent.subtype == XFixesDisplayCursorNotify) { + goXEventCursorChanged(notifyEvent); + continue; + } + } + } + + XCloseDisplay(display); +} diff --git a/internal/desktop/xevent/xevent.go b/internal/desktop/xevent/xevent.go new file mode 100644 index 00000000..6a6fb4c0 --- /dev/null +++ b/internal/desktop/xevent/xevent.go @@ -0,0 +1,55 @@ +package xevent + +/* +#cgo linux CFLAGS: -I/usr/src -I/usr/local/include/ +#cgo linux LDFLAGS: -L/usr/src -L/usr/local/lib -lX11 -lxcb -lXfixes + +#include "xevent.h" +*/ +import "C" + +import ( + "unsafe" + + "github.com/kataras/go-events" +) + +var emmiter events.EventEmmiter + +func init() { + emmiter = events.New() +} + +func EventLoop(display string) { + displayUnsafe := C.CString(display) + defer C.free(unsafe.Pointer(displayUnsafe)) + + C.XEventLoop(displayUnsafe) +} + +func OnCursorChanged(listener func(serial uint64)) { + emmiter.On("cursor-changed", func(payload ...interface{}) { + listener(payload[0].(uint64)) + }) +} + +func OnEventError(listener func(error_code uint8, message string, request_code uint8, minor_code uint8)) { + emmiter.On("event-error", func(payload ...interface{}) { + listener(payload[0].(uint8), payload[1].(string), payload[2].(uint8), payload[3].(uint8)) + }) +} + +//export goXEventCursorChanged +func goXEventCursorChanged(event C.XFixesCursorNotifyEvent) { + emmiter.Emit("cursor-changed", uint64(event.cursor_serial)) +} + +//export goXEventError +func goXEventError(event *C.XErrorEvent, message *C.char) { + emmiter.Emit("event-error", uint8(event.error_code), C.GoString(message), uint8(event.request_code), uint8(event.minor_code)) +} + +//export goXEventActive +func goXEventActive() C.int { + return C.int(1) +} diff --git a/internal/desktop/xevent/xevent.h b/internal/desktop/xevent/xevent.h new file mode 100644 index 00000000..24949f45 --- /dev/null +++ b/internal/desktop/xevent/xevent.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include +#include +#include + +extern void goXEventCursorChanged(XFixesCursorNotifyEvent event); +extern void goXEventError(XErrorEvent *event, char *message); +extern int goXEventActive(); + +static int XEventError(Display *display, XErrorEvent *event); +void XEventLoop(char *display); +