-- import "github.com/jackdoe/go-gpmctl"
general purpose mouse daemon(gpm) (https://linux.die.net/man/8/gpm) gives mouse support to the linux console
it exposes /dev/gpmctl to which you can connect, send your current vc and pid and receive mouse events
example:
package main
import (
"log"
gpmctl "github.com/jackdoe/go-gpmctl"
)
func main() {
g, err := gpmctl.NewGPM(gpmctl.DefaultConf)
if err != nil {
panic(err)
}
for {
event, err := g.Read()
if err != nil {
panic(err)
}
log.Printf("%s", event)
}
}
..
2020/03/16 23:18:57 type:move[buttons:, modifiers:0, vc:4] x:190[dx:0] y:28[dy:1], clicks:0 margin:, wdx:0, wdy:0
2020/03/16 23:18:57 type:move[buttons:, modifiers:0, vc:4] x:189[dx:-1] y:28[dy:0], clicks:0 margin:, wdx:0, wdy:0
2020/03/16 23:18:57 type:down,single[buttons:, modifiers:0, vc:4] x:189[dx:0] y:28[dy:0], clicks:0 margin:, wdx:0, wdy:0
2020/03/16 23:18:57 type:drag,single,mflag[buttons:, modifiers:0, vc:4] x:189[dx:0] y:29[dy:1], clicks:0 margin:, wdx:0, wdy:0
..
const (
TOP = 1 << iota
BOT
LFT
RGT
)
var DefaultConf = GPMConnect{
EventMask: EventType(^uint16(0)),
DefaultMask: EventType(^uint16(0)),
MinMod: 0,
MaxMod: ^uint16(0),
}
type Buttons uint8
const (
B_NONE Buttons = 0
B_RIGHT Buttons = 1
B_MIDDLE Buttons = 2
B_LEFT Buttons = 4
B_FOURTH Buttons = 8
B_UP Buttons = 16
B_DOWN Buttons = 32
)
func (b Buttons) String() string
type Event struct {
Buttons Buttons
Modifiers uint8
VC uint16
DX int16
DY int16
X int16
Y int16
Type EventType
Clicks int32
Margin Margin
WDX int16
WDY int16
}
Event defined as per gpm.h
typedef struct Gpm_Event {
unsigned char buttons, modifiers; /* try to be a multiple of 4 */
unsigned short vc;
short dx, dy, x, y; /* displacement x,y for this event, and absolute x,y */
enum Gpm_Etype type;
/* clicks e.g. double click are determined by time-based processing */
int clicks;
enum Gpm_Margin margin;
/* wdx/y: displacement of wheels in this event. Absolute values are not
* required, because wheel movement is typically used for scrolling
* or selecting fields, not for cursor positioning. The application
* can determine when the end of file or form is reached, and not
* go any further.
* A single mouse will use wdy, "vertical scroll" wheel. */
short wdx, wdy;
} Gpm_Event;
func (event Event) String() string
type EventType uint16
Gpm Event Type - as per gpm.h
enum Gpm_Etype {
GPM_MOVE=1,
GPM_DRAG=2, /* exactly one of the bare ones is active at a time */
GPM_DOWN=4
GPM_UP= 8,
#define GPM_BARE_EVENTS(type) ((type)&(0x0f|GPM_ENTER|GPM_LEAVE))
GPM_SINGLE=16, /* at most one in three is set */
GPM_DOUBLE=32,
GPM_TRIPLE=64, /* WARNING: I depend on the values */
GPM_MFLAG=128, /* motion during click? */
GPM_HARD=256, /* if set in the defaultMask, force an already
used event to pass over to another handler */
GPM_ENTER=512, /* enter event, user in Roi's */
GPM_LEAVE=1024 /* leave event, used in Roi's */
};
const (
MOVE EventType = 1 << iota
DRAG
DOWN
UP
SINGLE
DOUBLE
TRIPLE
MFLAG
HARD
ENTER
LEAVE
)
const ANY EventType = EventType(^uint16(0))
func (e EventType) String() string
type GPM struct {
}
GPM connection
func NewGPM(conf GPMConnect) (*GPM, error)
Create new gpm connection, it will detect current tty from "/proc/self/fd/0" and it will use the current pid, then it will connect the /dev/gpmctl stream unix socket nd send Gpm_Connect struct
func (g *GPM) Close()
close the gpm connection
func (g *GPM) Read() (Event, error)
Reads one event mouse, or blocks if there are no events NB: some gpm's could
have #define GPM_MAGIC 0x47706D4C
in every message, at the moment that is not
supported
type GPMConnect struct {
EventMask EventType
DefaultMask EventType
MinMod uint16
MaxMod uint16
}
Struct sent via the socket after connecting
typedef struct Gpm_Connect {
unsigned short eventMask, defaultMask; // 4
unsigned short minMod, maxMod; // 4
int pid; // 4
int vc; // 4
} Gpm_Connect;
type Margin int
Gpm Margin Enum as per gpm.h
enum Gpm_Margin {GPM_TOP=1, GPM_BOT=2, GPM_LFT=4, GPM_RGT=8};
func (m Margin) String() string