mirror of
https://github.com/robotn/gohook.git
synced 2025-05-20 15:24:25 +08:00
Part 2 of making the lib async
- New event struct mimiking C structs - changed c channel library to eb_chan - changed API to something more palatable
This commit is contained in:
parent
e5d15765a1
commit
11eee3201f
1430
chan/eb_chan.h
Normal file
1430
chan/eb_chan.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,22 +15,66 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "pub.h"
|
#include "pub.h"
|
||||||
#include "../chan/src/chan.h"
|
//#include "../chan/src/chan.h"
|
||||||
|
#include "../chan/eb_chan.h"
|
||||||
|
//chan_t * events = NULL;
|
||||||
|
eb_chan events;
|
||||||
|
|
||||||
chan_t * events = NULL;
|
void go_send(char*);
|
||||||
|
void go_sleep(void);
|
||||||
|
|
||||||
|
bool sending = false;
|
||||||
|
|
||||||
|
void startev(){
|
||||||
|
// events = chan_init(1024);
|
||||||
|
events = eb_chan_create(1024);
|
||||||
|
eb_chan_retain(events);
|
||||||
|
sending = true;
|
||||||
|
add_event("q");
|
||||||
|
}
|
||||||
|
|
||||||
|
//bool done = false;
|
||||||
|
void pollEv(){
|
||||||
|
if(events == NULL) return;
|
||||||
|
for(;eb_chan_buf_len(events)!=0;){
|
||||||
|
char* tmp;
|
||||||
|
if(eb_chan_try_recv(events,(const void**) &tmp) == eb_chan_res_ok){
|
||||||
|
go_send(tmp);
|
||||||
|
free(tmp);
|
||||||
|
}else{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void endPoll(){
|
||||||
|
sending = false;
|
||||||
|
pollEv();//remove last things from channel
|
||||||
|
eb_chan_release(events);
|
||||||
|
}
|
||||||
|
|
||||||
void dispatch_proc(iohook_event * const event) {
|
void dispatch_proc(iohook_event * const event) {
|
||||||
char buffer[256] = { 0 };
|
if(!sending) return;
|
||||||
size_t length = snprintf(buffer, sizeof(buffer),
|
//leaking memory? hope not
|
||||||
"{id:%i,when:%" PRIu64 ",mask=0x%X",
|
char* buffer = calloc(200,sizeof(char));
|
||||||
event->type, event->time, event->mask);
|
// char buffer[256] = { 0 };
|
||||||
|
// size_t length = snprintf(buffer, sizeof(buffer),
|
||||||
|
// "{id:%i,when:%" PRIu64 ",mask=0x%X",
|
||||||
|
// event->type, event->time, event->mask);
|
||||||
|
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
|
case EVENT_HOOK_ENABLED:
|
||||||
|
case EVENT_HOOK_DISABLED:
|
||||||
|
sprintf(buffer,"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu}",
|
||||||
|
event->type, event->time, event->mask,event->reserved);
|
||||||
|
// fprintf(stdout,"hook enabled");
|
||||||
|
break;//send it?
|
||||||
case EVENT_KEY_PRESSED:
|
case EVENT_KEY_PRESSED:
|
||||||
case EVENT_KEY_RELEASED:
|
case EVENT_KEY_RELEASED:
|
||||||
case EVENT_KEY_TYPED:
|
case EVENT_KEY_TYPED:
|
||||||
length = snprintf(buffer + length, sizeof(buffer) - length,
|
sprintf(buffer,
|
||||||
",keycode:%hu,rawcode:%hu,keychar:%hu}",
|
"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu,\"keycode\":%hu,\"rawcode\":%hu,\"keychar\":%hu}",
|
||||||
|
event->type, event->time, event->mask,event->reserved,
|
||||||
event->data.keyboard.keycode,
|
event->data.keyboard.keycode,
|
||||||
event->data.keyboard.rawcode,
|
event->data.keyboard.rawcode,
|
||||||
event->data.keyboard.keychar);
|
event->data.keyboard.keychar);
|
||||||
@ -40,16 +84,18 @@ void dispatch_proc(iohook_event * const event) {
|
|||||||
case EVENT_MOUSE_CLICKED:
|
case EVENT_MOUSE_CLICKED:
|
||||||
case EVENT_MOUSE_MOVED:
|
case EVENT_MOUSE_MOVED:
|
||||||
case EVENT_MOUSE_DRAGGED:
|
case EVENT_MOUSE_DRAGGED:
|
||||||
snprintf(buffer + length, sizeof(buffer) - length,
|
sprintf(buffer,
|
||||||
",x:%u,y:%u,button:%u,clicks:%u}",
|
"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu,\"x\":%hd,\"y\":%hd,\"button\":%u,\"clicks\":%u}",
|
||||||
|
event->type, event->time, event->mask,event->reserved,
|
||||||
event->data.mouse.x,
|
event->data.mouse.x,
|
||||||
event->data.mouse.y,
|
event->data.mouse.y,
|
||||||
event->data.mouse.button,
|
event->data.mouse.button,
|
||||||
event->data.mouse.clicks);
|
event->data.mouse.clicks);
|
||||||
break;
|
break;
|
||||||
case EVENT_MOUSE_WHEEL:
|
case EVENT_MOUSE_WHEEL:
|
||||||
snprintf(buffer + length, sizeof(buffer) - length,
|
sprintf(buffer,
|
||||||
",clicks:%hu,x:%hd,y:%hd,type:%hu,ammount:%hu,rotation:%hd,direction:%hu}",
|
"{\"id\":%i,\"time\":%" PRIu64 ",\"mask\":%hu,\"reserved\":%hu,\"clicks\":%hu,\"x\":%hd,\"y\":%hd,\"type\":%hu,\"ammount\":%hu,\"rotation\":%hd,\"direction\":%hu}",
|
||||||
|
event->type, event->time, event->mask, event->reserved,
|
||||||
event->data.wheel.clicks,
|
event->data.wheel.clicks,
|
||||||
event->data.wheel.x,
|
event->data.wheel.x,
|
||||||
event->data.wheel.y,
|
event->data.wheel.y,
|
||||||
@ -59,21 +105,29 @@ void dispatch_proc(iohook_event * const event) {
|
|||||||
event->data.wheel.direction);
|
event->data.wheel.direction);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"\nError on file: %s, unusual event->type\n",__FILE__);
|
fprintf(stderr,"\nError on file: %s, unusual event->type: %i\n",__FILE__,event->type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//to-do remove this for
|
//to-do remove this for
|
||||||
for(int i = 0; i < 5; i++){
|
for(int i = 0; i < 5; i++){
|
||||||
switch(chan_select(NULL,0,NULL,&events,1,(void**) &buffer)){
|
switch(eb_chan_try_send(events,buffer)){
|
||||||
case 0:
|
// switch(chan_select(NULL,0,NULL,&events,1,(void**) &buffer)){
|
||||||
fprintf(stdout,"\nitem sent: %s",buffer);
|
case eb_chan_res_ok:
|
||||||
|
// case 0:
|
||||||
|
// fprintf(stdout,"\nlen:%i,item sent: %s",chan_size(events),buffer);
|
||||||
|
// fprintf(stdout,"\nlen:%i,item sent: %s",eb_chan_buf_len(events),buffer);
|
||||||
|
i=5;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
chan_dispose(events);
|
if (i == 4) {//let's not leak memory
|
||||||
fprintf(stdout,"\n%i",i);
|
free(buffer);
|
||||||
|
}
|
||||||
|
// chan_dispose(events);
|
||||||
|
// fprintf(stdout,"%i",i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fprintf(stdout, "----%s\n", buffer);
|
// fprintf(stdout, "----%s\n", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
extern.go
32
extern.go
@ -6,16 +6,32 @@ package hook
|
|||||||
// #include "event/hook_async.h"
|
// #include "event/hook_async.h"
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import "time"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
//export go_send
|
//export go_send
|
||||||
func go_send(s *C.char) {
|
func go_send(s *C.char) {
|
||||||
str := C.GoString(s)
|
str := []byte(C.GoString(s))
|
||||||
ev <- str
|
fmt.Println(string(str))
|
||||||
|
out := Event{}
|
||||||
|
err := json.Unmarshal(str, &out)
|
||||||
|
if err != nil{
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
out.When = time.Now() //at least it's consistent
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
//todo: maybe make non-bloking
|
||||||
|
ev <- out
|
||||||
}
|
}
|
||||||
|
|
||||||
//export go_sleep
|
////export go_sleep
|
||||||
func go_sleep(){
|
//func go_sleep(){
|
||||||
//todo: find smallest time that does not destroy the cpu utilization
|
//
|
||||||
time.Sleep(time.Millisecond*50)
|
// time.Sleep(time.Millisecond*50)
|
||||||
}
|
//}
|
||||||
|
101
hook.go
101
hook.go
@ -20,64 +20,79 @@ package hook
|
|||||||
//#cgo windows LDFLAGS: -lgdi32 -luser32
|
//#cgo windows LDFLAGS: -lgdi32 -luser32
|
||||||
|
|
||||||
// #include "event/hook_async.h"
|
// #include "event/hook_async.h"
|
||||||
#include "chan/src/chan.h"
|
|
||||||
#include "event/goEvent.h"
|
#include "event/goEvent.h"
|
||||||
|
|
||||||
void go_send(char*);
|
|
||||||
void go_sleep(void);
|
|
||||||
extern chan_t* events;
|
|
||||||
|
|
||||||
void startev(){
|
|
||||||
events = chan_init(1024);
|
|
||||||
add_event("q");
|
|
||||||
}
|
|
||||||
bool done = false;
|
|
||||||
void pollEv(){
|
|
||||||
while(!done){
|
|
||||||
for(int i=chan_size(events); i >0;i--){
|
|
||||||
char* tmp;
|
|
||||||
chan_recv(events,(void**) &tmp);
|
|
||||||
go_send(tmp);
|
|
||||||
}
|
|
||||||
//go_sleep();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void endPoll(){
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
"time"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ev chan string = make(chan string,128)
|
//todo: add enums
|
||||||
|
const (
|
||||||
|
HOOK_ENABLED = 1 //iota
|
||||||
|
HOOK_DISABLED = 2
|
||||||
|
KEY_TYPED = 3
|
||||||
|
KEY_PRESSED = 4
|
||||||
|
KEY_RELEASED = 5
|
||||||
|
MOUSE_CLICKED = 6
|
||||||
|
MOUSE_PRESSED = 7
|
||||||
|
MOUSE_RELEASED = 8
|
||||||
|
MOUSE_MOVED = 9
|
||||||
|
MOUSE_DRAGGED = 10
|
||||||
|
MOUSE_WHEEL = 11
|
||||||
|
)
|
||||||
|
|
||||||
// AddEvent add event listener
|
type Event struct {
|
||||||
func AddEvent(key string) int {
|
Kind uint8 `json:"id"`
|
||||||
cs := C.CString(key)
|
When time.Time
|
||||||
defer C.free(unsafe.Pointer(cs))
|
Mask uint16 `json:"mask"`
|
||||||
|
Reserved uint16 `json:"reserved"`
|
||||||
eve := C.add_event(cs)
|
Keycode uint16 `json:"keycode"`
|
||||||
geve := int(eve)
|
Rawcode uint16 `json:"rawcode"`
|
||||||
|
Keychar uint16 `json:"keychar"`
|
||||||
return geve
|
Button uint16 `json:"button"`
|
||||||
|
Clicks uint16 `json:"clicks"`
|
||||||
|
X int16 `json:"x"`
|
||||||
|
Y int16 `json:"y"`
|
||||||
|
Ammount uint16 `json:"ammount"`
|
||||||
|
Rotation int16 `json:"rotation"`
|
||||||
|
Direction uint8 `json:"direction"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartEvent() chan string{
|
var (
|
||||||
C.startev()
|
ev chan Event = make(chan Event, 1024)
|
||||||
go C.pollEv()
|
asyncon bool = false
|
||||||
|
)
|
||||||
|
|
||||||
|
func Start() chan Event {
|
||||||
|
//fmt.Print("Here1")
|
||||||
|
asyncon = true
|
||||||
|
go C.startev()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
C.pollEv()
|
||||||
|
time.Sleep(time.Millisecond * 50)
|
||||||
|
//todo: find smallest time that does not destroy the cpu utilization
|
||||||
|
//fmt.Println("_here_")
|
||||||
|
if ! asyncon {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//fmt.Print("WOOOOOOOOOT")
|
||||||
|
}()
|
||||||
|
//fmt.Print("Here2")
|
||||||
return ev
|
return ev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// StopEvent stop event listener
|
// StopEvent stop event listener
|
||||||
func StopEvent() {
|
func End() {
|
||||||
C.endPoll()
|
C.endPoll()
|
||||||
C.stop_event()
|
C.stop_event()
|
||||||
C.chan_close(C.events);
|
for len(ev) != 0 {
|
||||||
|
<-ev
|
||||||
|
}
|
||||||
|
asyncon = false
|
||||||
|
//C.chan_close(C.events);
|
||||||
}
|
}
|
||||||
|
30
test/main.go
30
test/main.go
@ -2,22 +2,28 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/robotn/gohook"
|
"github.com/cauefcr/gohook"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
s := hook.StartEvent()
|
s := hook.Start()
|
||||||
|
tout := time.After(time.Second * 10)
|
||||||
go func() {
|
done := false
|
||||||
fmt.Print("woo!")
|
for !done {
|
||||||
for i:=range s {
|
select {
|
||||||
fmt.Println(i)
|
case i := <-s:
|
||||||
|
if i.Keychar == uint16('q') {
|
||||||
|
tout = time.After(1 * time.Millisecond)
|
||||||
|
}
|
||||||
|
fmt.Printf("%+v\n", i)
|
||||||
|
case <-tout:
|
||||||
|
fmt.Print("Done.")
|
||||||
|
done = true
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
// hook.AsyncHook()
|
|
||||||
veve := hook.AddEvent("v")
|
|
||||||
if veve == 0 {
|
|
||||||
fmt.Println("v...")
|
|
||||||
}
|
}
|
||||||
|
hook.End()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user