I'm trying to emulate a key combination of Left Windows Key (Super) + S under wayland to perform a screenshot automatically (this key combination properly starts weston-screenshooter that saves a screenshot to the home directory, but it cannot be executed from terminal). I found out about using uinput to do this, I found a few examples and came up with this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#define die(str) do { \
perror(str); \
exit(EXIT_FAILURE); \
} while(0)
void emitEvent(int fd, uint16_t type, uint16_t code, int val)
{
struct input_event ie;
ie.type = type;
ie.code = code;
ie.value = val;
/* timestamp values below are ignored */
ie.time.tv_sec = 0;
ie.time.tv_usec = 0;
write(fd, &ie, sizeof(ie));
}
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
int main(int argc, char *argv[])
{
int fd;
struct uinput_user_dev uidev;
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if(fd < 0)
die("error: open");
if(ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_KEYBIT, KEY_S) < 0)
die("error: ioctl");
if(ioctl(fd, UI_SET_KEYBIT, 133) < 0)
die("error: ioctl");
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1234; // random stuff
uidev.id.product = 0x6433;
uidev.id.version = 1;
if(write(fd, &uidev, sizeof(uidev)) < 0)
die("error: write");
if(ioctl(fd, UI_DEV_CREATE) < 0)
die("error: ioctl");
sleep(1);
// srand(time(NULL));
emitEvent(fd, EV_KEY, 133, 1);
emitEvent(fd, EV_KEY, KEY_S, 1);
emitEvent(fd, EV_SYN, SYN_REPORT, 0);
usleep(300);
emitEvent(fd, EV_KEY, KEY_S, 0);
emitEvent(fd, EV_KEY, 133, 0);
emitEvent(fd, EV_SYN, SYN_REPORT, 0);
sleep(1);
if(ioctl(fd, UI_DEV_DESTROY) < 0)
die("error: ioctl");
close(fd);
return 0;
}
My biggest problem is that I don't know which KEY_ is the Left Win/Left Super key, the key definitons aren't showing me anything related to win or super or mod_s at all, using xev on x11 i found that LWIN should be 133, but I think it's not correct because KEY_S = 31 in code but in xev it's 39.
When running the application I can see the device is being registered in the system:
[ 6278.405013] input: uinput-sample as /devices/virtual/input/input23
[14:02:17.556] event2 - [14:02:17.556] uinput-sample: [14:02:17.556] is tagged by udev as: Keyboard
[14:02:17.556] event2 - [14:02:17.557] uinput-sample: [14:02:17.557] device is a keyboard
[14:02:19.549] event2 - [14:02:19.550] uinput-sample: [14:02:19.550] device removed
but nothing else is happening.
What is the proper key definition for Left Windows key? Is the code above valid for sending a key combination (2 keys pressed at once)? Is it even possible to achieve what I want? I have full root access in the system.