mirror of
https://github.com/swaywm/sway.git
synced 2024-12-29 16:36:26 +01:00
Merge pull request #1793 from PyroLagus/input-simulation
Cursor input simulation with sway commands.
This commit is contained in:
commit
96118be241
8 changed files with 105 additions and 2 deletions
|
@ -204,8 +204,9 @@ sway_cmd input_cmd_xkb_options;
|
||||||
sway_cmd input_cmd_xkb_rules;
|
sway_cmd input_cmd_xkb_rules;
|
||||||
sway_cmd input_cmd_xkb_variant;
|
sway_cmd input_cmd_xkb_variant;
|
||||||
|
|
||||||
sway_cmd seat_cmd_fallback;
|
|
||||||
sway_cmd seat_cmd_attach;
|
sway_cmd seat_cmd_attach;
|
||||||
|
sway_cmd seat_cmd_fallback;
|
||||||
|
sway_cmd seat_cmd_cursor;
|
||||||
|
|
||||||
sway_cmd cmd_ipc_cmd;
|
sway_cmd cmd_ipc_cmd;
|
||||||
sway_cmd cmd_ipc_events;
|
sway_cmd cmd_ipc_events;
|
||||||
|
|
|
@ -30,5 +30,7 @@ struct sway_cursor {
|
||||||
void sway_cursor_destroy(struct sway_cursor *cursor);
|
void sway_cursor_destroy(struct sway_cursor *cursor);
|
||||||
struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
|
struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
|
||||||
void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time);
|
void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time);
|
||||||
|
void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec,
|
||||||
|
uint32_t button, enum wlr_button_state state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -203,6 +203,7 @@ static struct cmd_handler input_handlers[] = {
|
||||||
// must be in order for the bsearch
|
// must be in order for the bsearch
|
||||||
static struct cmd_handler seat_handlers[] = {
|
static struct cmd_handler seat_handlers[] = {
|
||||||
{ "attach", seat_cmd_attach },
|
{ "attach", seat_cmd_attach },
|
||||||
|
{ "cursor", seat_cmd_cursor },
|
||||||
{ "fallback", seat_cmd_fallback },
|
{ "fallback", seat_cmd_fallback },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ struct cmd_results *cmd_seat(int argc, char **argv) {
|
||||||
struct cmd_results *res;
|
struct cmd_results *res;
|
||||||
if (strcasecmp("attach", argv[1]) == 0) {
|
if (strcasecmp("attach", argv[1]) == 0) {
|
||||||
res = seat_cmd_attach(argc_new, argv_new);
|
res = seat_cmd_attach(argc_new, argv_new);
|
||||||
|
} else if (strcasecmp("cursor", argv[1]) == 0) {
|
||||||
|
res = seat_cmd_cursor(argc_new, argv_new);
|
||||||
} else if (strcasecmp("fallback", argv[1]) == 0) {
|
} else if (strcasecmp("fallback", argv[1]) == 0) {
|
||||||
res = seat_cmd_fallback(argc_new, argv_new);
|
res = seat_cmd_fallback(argc_new, argv_new);
|
||||||
} else {
|
} else {
|
||||||
|
|
89
sway/commands/seat/cursor.c
Normal file
89
sway/commands/seat/cursor.c
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
#define _XOPEN_SOURCE 700
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#elif __FreeBSD__
|
||||||
|
#include <dev/evdev/input-event-codes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
#include <wlr/types/wlr_cursor.h>
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/input/cursor.h"
|
||||||
|
|
||||||
|
static struct cmd_results *press_or_release(struct sway_cursor *cursor,
|
||||||
|
char *action, char *button_str, uint32_t time);
|
||||||
|
|
||||||
|
static const char *expected_syntax = "Expected 'cursor <move> <x> <y>' or "
|
||||||
|
"'cursor <set> <x> <y>' or "
|
||||||
|
"'curor <press|release> <left|right|1|2|3...>'";
|
||||||
|
|
||||||
|
struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "cursor", EXPECTED_AT_LEAST, 2))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
struct sway_seat *seat = config->handler_context.seat;
|
||||||
|
if (!seat) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "cursor", "No seat defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sway_cursor *cursor = seat->cursor;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
uint32_t time = now.tv_nsec / 1000;
|
||||||
|
|
||||||
|
if (strcasecmp(argv[0], "move") == 0) {
|
||||||
|
if (argc < 3) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
|
||||||
|
}
|
||||||
|
int delta_x = strtol(argv[1], NULL, 10);
|
||||||
|
int delta_y = strtol(argv[2], NULL, 10);
|
||||||
|
wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y);
|
||||||
|
cursor_send_pointer_motion(cursor, time);
|
||||||
|
} else if (strcasecmp(argv[0], "set") == 0) {
|
||||||
|
if (argc < 3) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
|
||||||
|
}
|
||||||
|
// map absolute coords (0..1,0..1) to root container coords
|
||||||
|
float x = strtof(argv[1], NULL) / root_container.width;
|
||||||
|
float y = strtof(argv[2], NULL) / root_container.height;
|
||||||
|
wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y);
|
||||||
|
cursor_send_pointer_motion(cursor, time);
|
||||||
|
} else {
|
||||||
|
if (argc < 2) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
|
||||||
|
}
|
||||||
|
if ((error = press_or_release(cursor, argv[0], argv[1], time))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmd_results *press_or_release(struct sway_cursor *cursor,
|
||||||
|
char *action, char *button_str, uint32_t time) {
|
||||||
|
enum wlr_button_state state;
|
||||||
|
uint32_t button;
|
||||||
|
if (strcasecmp(action, "press") == 0) {
|
||||||
|
state = WLR_BUTTON_PRESSED;
|
||||||
|
} else if (strcasecmp(action, "release") == 0) {
|
||||||
|
state = WLR_BUTTON_RELEASED;
|
||||||
|
} else {
|
||||||
|
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(button_str, "left") == 0) {
|
||||||
|
button = BTN_LEFT;
|
||||||
|
} else if (strcasecmp(button_str, "right") == 0) {
|
||||||
|
button = BTN_RIGHT;
|
||||||
|
} else {
|
||||||
|
button = strtol(button_str, NULL, 10);
|
||||||
|
if (button == 0) {
|
||||||
|
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatch_cursor_button(cursor, time, button, state);
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
|
||||||
|
}
|
|
@ -166,7 +166,7 @@ static void handle_cursor_motion_absolute(
|
||||||
cursor_send_pointer_motion(cursor, event->time_msec);
|
cursor_send_pointer_motion(cursor, event->time_msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dispatch_cursor_button(struct sway_cursor *cursor,
|
void dispatch_cursor_button(struct sway_cursor *cursor,
|
||||||
uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
|
uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
|
||||||
struct wlr_surface *surface = NULL;
|
struct wlr_surface *surface = NULL;
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
|
|
|
@ -47,6 +47,7 @@ sway_sources = files(
|
||||||
'commands/resize.c',
|
'commands/resize.c',
|
||||||
'commands/seat.c',
|
'commands/seat.c',
|
||||||
'commands/seat/attach.c',
|
'commands/seat/attach.c',
|
||||||
|
'commands/seat/cursor.c',
|
||||||
'commands/seat/fallback.c',
|
'commands/seat/fallback.c',
|
||||||
'commands/set.c',
|
'commands/set.c',
|
||||||
'commands/split.c',
|
'commands/split.c',
|
||||||
|
|
|
@ -328,6 +328,13 @@ The default colors are:
|
||||||
the named seat, and _}_ on its own line will close the block.
|
the named seat, and _}_ on its own line will close the block.
|
||||||
See **sway-input**(5) for details.
|
See **sway-input**(5) for details.
|
||||||
|
|
||||||
|
**seat** <seat_name> cursor <move|set> <x> <y>::
|
||||||
|
Move cursor relatively to current position or set to absolute screen position.
|
||||||
|
A value of 0 causes the axis to be ignored in both commands.
|
||||||
|
|
||||||
|
**seat** <seat_name> cursor <press|release> <left|right|1|2|3...>::
|
||||||
|
Simulate press of mouse button specified by left, right, or numerical code.
|
||||||
|
|
||||||
**kill**::
|
**kill**::
|
||||||
Kills (force-closes) the currently-focused container and all of its children.
|
Kills (force-closes) the currently-focused container and all of its children.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue