Further improve XLib code and include go code capable of calling it
This commit is contained in:
parent
0729d9a9ee
commit
9ca48b7bf8
@ -1,5 +0,0 @@
|
||||
get-x-slave-devnodes: get-x-slave-devnodes.c
|
||||
$(CC) -O2 --std=gnu99 -pedantic -Wall get-x-slave-devnodes.c -o get-x-slave-devnodes -lX11 -lXi
|
||||
clean:
|
||||
rm -f get-x-slave-devnodes
|
||||
|
5
xdg/xinput_devnodes/Makefile
Normal file
5
xdg/xinput_devnodes/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
main: main.c
|
||||
$(CC) -O2 --std=gnu99 -pedantic -Wall main.c xslaves.c devnodes.c -o devnodes -lX11 -lXi
|
||||
clean:
|
||||
rm -f devnodes
|
||||
|
@ -8,11 +8,13 @@
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "devnodes.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/Xatom.h>
|
||||
@ -73,6 +75,42 @@ char* get_property_xi2(Display* dpy, int deviceid, Atom property, const char* pr
|
||||
return ret;
|
||||
}
|
||||
|
||||
XSlaves* build_slave_info(Display* disp)
|
||||
{
|
||||
int num_slaves;
|
||||
XIDeviceInfo* all_slaves = XIQueryDevice(disp, XIAllDevices, &num_slaves);
|
||||
XSlaves* slaves = new_xslaves(num_slaves);
|
||||
bool fail = false;
|
||||
|
||||
for (int i = 0; i < num_slaves; i++)
|
||||
{
|
||||
XIDeviceInfo* current_slave = &all_slaves[i];
|
||||
int nprops;
|
||||
Atom* props = XIListProperties(disp, current_slave->deviceid, &nprops);
|
||||
|
||||
while(nprops-- && !fail)
|
||||
{
|
||||
char* devnode = get_property_xi2(disp, current_slave->deviceid, props[nprops], "Device Node");
|
||||
if (current_slave->name != NULL && devnode != NULL)
|
||||
{
|
||||
int success = add_slaveinfo(slaves, current_slave->name, devnode);
|
||||
if (success != 0)
|
||||
fail = true;
|
||||
}
|
||||
free(devnode);
|
||||
}
|
||||
XFree(props);
|
||||
if (fail)
|
||||
{
|
||||
free_xslaves(slaves);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
XIFreeDeviceInfo(all_slaves);
|
||||
return slaves;
|
||||
}
|
||||
|
||||
int is_xinput2_available(Display* disp)
|
||||
{
|
||||
int xiOpcode;
|
||||
@ -99,103 +137,6 @@ int is_xinput2_available(Display* disp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct SlaveInfo
|
||||
{
|
||||
char* slave_names;
|
||||
char* dev_nodes;
|
||||
} SlaveInfo;
|
||||
|
||||
SlaveInfo new_slave_info()
|
||||
{
|
||||
SlaveInfo si;
|
||||
si.slave_names = NULL;
|
||||
si.dev_nodes = NULL;
|
||||
return si;
|
||||
}
|
||||
|
||||
void free_slave_info(SlaveInfo si)
|
||||
{
|
||||
free(si.slave_names);
|
||||
free(si.dev_nodes);
|
||||
si.slave_names = NULL;
|
||||
si.dev_nodes = NULL;
|
||||
}
|
||||
|
||||
bool is_empty_slave_info(SlaveInfo si)
|
||||
{
|
||||
return (si.slave_names == NULL || si.dev_nodes == NULL);
|
||||
}
|
||||
|
||||
void replace(char* str, char old, char new)
|
||||
{
|
||||
int i = 0;
|
||||
while (str[i] != '\0')
|
||||
{
|
||||
if (str[i] == old)
|
||||
str[i] = new;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int append_as_line(char** dst, char* line)
|
||||
{
|
||||
uint len_newstr = strlen(line) + 2;
|
||||
if (*dst != NULL)
|
||||
len_newstr += strlen(*dst);
|
||||
|
||||
char* newstr = (char*)malloc(len_newstr);
|
||||
if (newstr == NULL)
|
||||
return -1;
|
||||
|
||||
newstr[0] = '\0';
|
||||
replace(line, '\n', ' ');
|
||||
if (*dst != NULL)
|
||||
strcat(newstr, *dst);
|
||||
strcat(newstr, line);
|
||||
strcat(newstr, "\n");
|
||||
|
||||
free(*dst);
|
||||
*dst = newstr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SlaveInfo get_slave_info(Display* disp)
|
||||
{
|
||||
int num_slaves;
|
||||
XIDeviceInfo* all_slaves = XIQueryDevice(disp, XIAllDevices, &num_slaves);
|
||||
SlaveInfo slaveinfo = new_slave_info();
|
||||
bool fail = false;
|
||||
|
||||
for (int i = 0; i < num_slaves; i++)
|
||||
{
|
||||
XIDeviceInfo* current_slave = &all_slaves[i];
|
||||
int nprops;
|
||||
Atom* props = XIListProperties(disp, current_slave->deviceid, &nprops);
|
||||
|
||||
while(nprops-- && !fail)
|
||||
{
|
||||
char* devnode = get_property_xi2(disp, current_slave->deviceid, props[nprops], "Device Node");
|
||||
if (current_slave->name != NULL && devnode != NULL)
|
||||
{
|
||||
int append_slave_success = append_as_line(&slaveinfo.slave_names, current_slave->name);
|
||||
int append_devnode_success = append_as_line(&slaveinfo.dev_nodes, devnode);
|
||||
if (append_slave_success != 0 || append_devnode_success != 0)
|
||||
fail = true;
|
||||
}
|
||||
free(devnode);
|
||||
}
|
||||
XFree(props);
|
||||
if (fail)
|
||||
{
|
||||
free_slave_info(slaveinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
XIFreeDeviceInfo(all_slaves);
|
||||
return slaveinfo;
|
||||
}
|
||||
|
||||
Display* connect_to_x(const char* xDisplayName)
|
||||
{
|
||||
Display* disp = XOpenDisplay(xDisplayName);
|
||||
@ -214,8 +155,7 @@ Display* connect_to_x(const char* xDisplayName)
|
||||
return disp;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
XSlaves* get_slave_info()
|
||||
{
|
||||
char* xDisplayName = getenv("DISPLAY");
|
||||
if (xDisplayName == NULL)
|
||||
@ -228,14 +168,21 @@ int main(int argc, char * argv[])
|
||||
if (disp == NULL)
|
||||
exit(1);
|
||||
|
||||
SlaveInfo si = get_slave_info(disp);
|
||||
if (!is_empty_slave_info(si))
|
||||
{
|
||||
printf("%s", si.slave_names);
|
||||
printf("%s", si.dev_nodes);
|
||||
XSlaves* s = build_slave_info(disp);
|
||||
XCloseDisplay(disp);
|
||||
return s;
|
||||
}
|
||||
|
||||
free_slave_info(si);
|
||||
XCloseDisplay(disp);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// int main(int argc, char * argv[])
|
||||
// {
|
||||
// XSlaves* s = get_slave_info();
|
||||
// for (int i = 0; i < s->length; i++)
|
||||
// {
|
||||
// XSlaveInfo si = s->slaves[i];
|
||||
// printf("Name: %s\n", si.name);
|
||||
// printf("Node: %s\n", si.dev_node);
|
||||
// printf("\n");
|
||||
// }
|
||||
// free_xslaves(s);
|
||||
// }
|
6
xdg/xinput_devnodes/devnodes.h
Normal file
6
xdg/xinput_devnodes/devnodes.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "xslaves.h"
|
||||
|
||||
|
||||
XSlaves* get_slave_info();
|
16
xdg/xinput_devnodes/main.c
Normal file
16
xdg/xinput_devnodes/main.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "devnodes.h"
|
||||
#include "xslaves.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
XSlaves* xs = get_slave_info();
|
||||
for (int i=0; i < xs->length; i++)
|
||||
{
|
||||
XSlaveInfo si = xs->slaves[i];
|
||||
printf("%s = %s\n", si.name, si.dev_node);
|
||||
}
|
||||
|
||||
free_xslaves(xs);
|
||||
}
|
51
xdg/xinput_devnodes/xinput_devnodes.go
Normal file
51
xdg/xinput_devnodes/xinput_devnodes.go
Normal file
@ -0,0 +1,51 @@
|
||||
package xinput_devnodes
|
||||
|
||||
// #cgo CFLAGS: -g --std=gnu99 -pedantic -Wall
|
||||
// #cgo LDFLAGS: -lX11 -lXi
|
||||
// #include "devnodes.h"
|
||||
// #include <stdlib.h>
|
||||
// #include <string.h>
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
|
||||
func FindKeyboardDevNode() string {
|
||||
xslaveinfos, freeMethod := GetXSlaveInfo()
|
||||
defer freeMethod()
|
||||
|
||||
re := regexp.MustCompile(`(?i).*keyboard.*`)
|
||||
for _, xslaveinfo := range xslaveinfos {
|
||||
name, devNode := C.GoString(xslaveinfo.name), C.GoString(xslaveinfo.dev_node)
|
||||
if re.MatchString(name) {
|
||||
return devNode
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
func Print() {
|
||||
xslaveinfos, freeMethod := GetXSlaveInfo()
|
||||
defer freeMethod()
|
||||
|
||||
for _, xslaveinfo := range xslaveinfos {
|
||||
fmt.Printf("%s = %s\n", C.GoString(xslaveinfo.name), C.GoString(xslaveinfo.dev_node))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func GetXSlaveInfo() ([]C.XSlaveInfo, func()) {
|
||||
xslaves := C.get_slave_info()
|
||||
arr := (*[1 << 30]C.XSlaveInfo)(unsafe.Pointer(xslaves.slaves))
|
||||
slice := arr[:xslaves.length:xslaves.length]
|
||||
freeMethod := func() {
|
||||
C.free_xslaves(xslaves)
|
||||
}
|
||||
|
||||
return slice, freeMethod
|
||||
}
|
||||
|
55
xdg/xinput_devnodes/xslaves.c
Normal file
55
xdg/xinput_devnodes/xslaves.c
Normal file
@ -0,0 +1,55 @@
|
||||
#include "xslaves.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
XSlaveInfo new_slave_info()
|
||||
{
|
||||
XSlaveInfo si;
|
||||
si.name = NULL;
|
||||
si.dev_node = NULL;
|
||||
return si;
|
||||
}
|
||||
|
||||
void free_slave_info(XSlaveInfo si)
|
||||
{
|
||||
free(si.name);
|
||||
free(si.dev_node);
|
||||
si.name = NULL;
|
||||
si.dev_node = NULL;
|
||||
}
|
||||
|
||||
XSlaves* new_xslaves(size_t capacity)
|
||||
{
|
||||
XSlaves* s = (XSlaves*)malloc(sizeof(XSlaves));
|
||||
s->capacity = capacity;
|
||||
s->length = 0;
|
||||
s->slaves = (XSlaveInfo*)malloc(capacity*sizeof(XSlaveInfo));
|
||||
return s;
|
||||
}
|
||||
|
||||
void free_xslaves(XSlaves* slaves)
|
||||
{
|
||||
for (int i = 0; i < slaves->length; i++)
|
||||
free_slave_info(slaves->slaves[i]);
|
||||
free(slaves->slaves);
|
||||
slaves->slaves = NULL;
|
||||
slaves->length = 0;
|
||||
slaves->capacity = 0;
|
||||
free(slaves);
|
||||
}
|
||||
|
||||
int add_slaveinfo(XSlaves* slaves, char* name, char* dev_node)
|
||||
{
|
||||
XSlaveInfo si = new_slave_info();
|
||||
si.name = strdup(name);
|
||||
si.dev_node = strdup(dev_node);
|
||||
if (slaves->length < slaves->capacity)
|
||||
{
|
||||
slaves->slaves[slaves->length] = si;
|
||||
slaves->length++;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
25
xdg/xinput_devnodes/xslaves.h
Normal file
25
xdg/xinput_devnodes/xslaves.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
typedef struct XSlaveInfo
|
||||
{
|
||||
char* name;
|
||||
char* dev_node;
|
||||
} XSlaveInfo;
|
||||
|
||||
typedef struct XSalves
|
||||
{
|
||||
XSlaveInfo* slaves;
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
} XSlaves;
|
||||
|
||||
|
||||
XSlaveInfo new_slave_info();
|
||||
void free_slave_info(XSlaveInfo si);
|
||||
|
||||
XSlaves* new_xslaves(size_t capacity);
|
||||
void free_xslaves(XSlaves* slaves);
|
||||
int add_slaveinfo(XSlaves* slaves, char* name, char* dev_node);
|
Loading…
Reference in New Issue
Block a user