neko/server/internal/xorg/xorg.go

248 lines
4.5 KiB
Go
Raw Normal View History

2020-02-11 18:15:59 +13:00
package xorg
2020-01-19 12:30:09 +13:00
/*
2020-02-12 10:10:10 +13:00
#cgo linux CFLAGS: -I/usr/src -I/usr/local/include/
#cgo linux LDFLAGS: /usr/local/lib/libclipboard.a -L/usr/src -L/usr/local/lib -lX11 -lXtst -lXrandr -lxcb
2020-01-19 12:30:09 +13:00
2020-02-11 18:15:59 +13:00
#include "xorg.h"
2020-01-19 12:30:09 +13:00
*/
import "C"
import (
"fmt"
"sync"
2020-01-19 12:30:09 +13:00
"time"
2020-02-11 18:15:59 +13:00
"unsafe"
2020-06-16 12:39:15 +12:00
"regexp"
2020-01-19 12:30:09 +13:00
2020-02-11 18:15:59 +13:00
"n.eko.moe/neko/internal/types"
2020-01-19 12:30:09 +13:00
)
2020-02-11 18:15:59 +13:00
var ScreenConfigurations = make(map[int]types.ScreenConfiguration)
2020-06-16 04:57:28 +12:00
var debounce_button = make(map[int]time.Time)
var debounce_key = make(map[uint64]time.Time)
var mu = sync.Mutex{}
2020-01-19 12:30:09 +13:00
func init() {
2020-02-11 18:15:59 +13:00
C.XGetScreenConfigurations()
2020-01-19 12:30:09 +13:00
}
func Display(display string) {
mu.Lock()
defer mu.Unlock()
2020-02-11 18:15:59 +13:00
displayUnsafe := C.CString(display)
defer C.free(unsafe.Pointer(displayUnsafe))
C.XDisplaySet(displayUnsafe)
2020-01-19 12:30:09 +13:00
}
func Move(x, y int) {
mu.Lock()
defer mu.Unlock()
2020-01-26 03:29:52 +13:00
C.XMove(C.int(x), C.int(y))
2020-01-19 12:30:09 +13:00
}
func Scroll(x, y int) {
mu.Lock()
defer mu.Unlock()
2020-01-26 03:29:52 +13:00
C.XScroll(C.int(x), C.int(y))
2020-01-19 12:30:09 +13:00
}
2020-06-14 02:21:11 +12:00
func ButtonDown(code int) error {
mu.Lock()
defer mu.Unlock()
2020-06-16 04:57:28 +12:00
if _, ok := debounce_button[code]; ok {
2020-06-14 02:21:11 +12:00
return fmt.Errorf("debounced button %v", code)
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
debounce_button[code] = time.Now()
2020-01-19 12:30:09 +13:00
2020-06-14 02:21:11 +12:00
C.XButton(C.uint(code), C.int(1))
return nil
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
func KeyDown(code uint64) error {
mu.Lock()
defer mu.Unlock()
2020-06-16 04:57:28 +12:00
if _, ok := debounce_key[code]; ok {
2020-06-14 02:21:11 +12:00
return fmt.Errorf("debounced key %v", code)
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
debounce_key[code] = time.Now()
2020-01-26 03:29:52 +13:00
2020-06-14 02:21:11 +12:00
C.XKey(C.ulong(code), C.int(1))
return nil
2020-01-19 12:30:09 +13:00
}
2020-06-14 02:21:11 +12:00
func ButtonUp(code int) error {
mu.Lock()
defer mu.Unlock()
2020-06-16 04:57:28 +12:00
if _, ok := debounce_button[code]; !ok {
2020-06-14 02:21:11 +12:00
return fmt.Errorf("debounced button %v", code)
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
delete(debounce_button, code)
2020-01-19 12:30:09 +13:00
2020-06-14 02:21:11 +12:00
C.XButton(C.uint(code), C.int(0))
return nil
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
func KeyUp(code uint64) error {
mu.Lock()
defer mu.Unlock()
2020-06-16 04:57:28 +12:00
if _, ok := debounce_key[code]; !ok {
2020-06-14 02:21:11 +12:00
return fmt.Errorf("debounced key %v", code)
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
delete(debounce_key, code)
2020-01-19 12:30:09 +13:00
2020-06-14 02:21:11 +12:00
C.XKey(C.ulong(code), C.int(0))
return nil
2020-01-19 12:30:09 +13:00
}
func ReadClipboard() string {
mu.Lock()
defer mu.Unlock()
2020-02-11 18:15:59 +13:00
clipboardUnsafe := C.XClipboardGet()
defer C.free(unsafe.Pointer(clipboardUnsafe))
return C.GoString(clipboardUnsafe)
}
func WriteClipboard(data string) {
mu.Lock()
defer mu.Unlock()
2020-02-11 18:15:59 +13:00
clipboardUnsafe := C.CString(data)
defer C.free(unsafe.Pointer(clipboardUnsafe))
C.XClipboardSet(clipboardUnsafe)
}
2020-02-11 18:15:59 +13:00
func ResetKeys() {
2020-06-16 04:57:28 +12:00
for code := range debounce_button {
ButtonUp(code)
delete(debounce_button, code)
}
for code := range debounce_key {
KeyUp(code)
2020-01-19 12:30:09 +13:00
2020-06-16 04:57:28 +12:00
delete(debounce_key, code)
2020-01-19 12:30:09 +13:00
}
}
2020-02-11 18:15:59 +13:00
func CheckKeys(duration time.Duration) {
2020-01-19 12:30:09 +13:00
t := time.Now()
2020-06-16 04:57:28 +12:00
for code, start := range debounce_button {
2020-01-19 12:30:09 +13:00
if t.Sub(start) < duration {
continue
}
2020-06-16 04:57:28 +12:00
ButtonUp(code)
2020-01-19 12:30:09 +13:00
2020-06-16 04:57:28 +12:00
delete(debounce_button, code)
}
for code, start := range debounce_key {
if t.Sub(start) < duration {
continue
2020-01-19 12:30:09 +13:00
}
2020-06-16 04:57:28 +12:00
KeyUp(code)
2020-01-19 12:30:09 +13:00
2020-06-16 04:57:28 +12:00
delete(debounce_key, code)
2020-01-19 12:30:09 +13:00
}
}
2020-02-11 18:15:59 +13:00
2020-02-11 19:10:36 +13:00
func ValidScreenSize(width int, height int, rate int) bool {
for _, size := range ScreenConfigurations {
if size.Width == width && size.Height == height {
for _, fps := range size.Rates {
if int16(rate) == fps {
return true
}
}
}
}
return false
}
2020-02-11 18:15:59 +13:00
func ChangeScreenSize(width int, height int, rate int) error {
mu.Lock()
defer mu.Unlock()
for index, size := range ScreenConfigurations {
if size.Width == width && size.Height == height {
2020-02-11 19:10:36 +13:00
for _, fps := range size.Rates {
if int16(rate) == fps {
C.XSetScreenConfiguration(C.int(index), C.short(fps))
2020-02-11 18:15:59 +13:00
return nil
}
}
}
}
return fmt.Errorf("unknown configuration")
}
func GetScreenSize() *types.ScreenSize {
mu.Lock()
defer mu.Unlock()
index := int(C.XGetScreenSize())
rate := int16(C.XGetScreenRate())
if conf, ok := ScreenConfigurations[index]; ok {
return &types.ScreenSize{
Width: conf.Width,
Height: conf.Height,
Rate: rate,
}
}
return nil
}
2020-06-21 13:05:58 +12:00
func SetKeyboardLayout(layout string) {
2020-06-16 09:14:23 +12:00
mu.Lock()
defer mu.Unlock()
2020-06-16 12:39:15 +12:00
if !regexp.MustCompile(`^[a-zA-Z]+$`).MatchString(layout) {
return
}
2020-06-16 09:14:23 +12:00
layoutUnsafe := C.CString(layout)
defer C.free(unsafe.Pointer(layoutUnsafe))
2020-06-21 13:05:58 +12:00
C.SetKeyboardLayout(layoutUnsafe)
2020-06-16 09:14:23 +12:00
}
2020-06-20 12:15:38 +12:00
func SetKeyboardModifiers(num_lock int, caps_lock int, scroll_lock int) {
mu.Lock()
defer mu.Unlock()
C.SetKeyboardModifiers(C.int(num_lock), C.int(caps_lock), C.int(scroll_lock))
}
2020-02-11 18:15:59 +13:00
//export goCreateScreenSize
func goCreateScreenSize(index C.int, width C.int, height C.int, mwidth C.int, mheight C.int) {
ScreenConfigurations[int(index)] = types.ScreenConfiguration{
Width: int(width),
Height: int(height),
Rates: make(map[int]int16),
}
}
//export goSetScreenRates
func goSetScreenRates(index C.int, rate_index C.int, rate C.short) {
ScreenConfigurations[int(index)].Rates[int(rate_index)] = int16(rate)
}