diff options
Diffstat (limited to 'sway/commands.c')
-rw-r--r-- | sway/commands.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/sway/commands.c b/sway/commands.c index 1c7eb962..5c8653ed 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -11,6 +11,9 @@ | |||
11 | #include <wordexp.h> | 11 | #include <wordexp.h> |
12 | #include <sys/types.h> | 12 | #include <sys/types.h> |
13 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
14 | #include <limits.h> | ||
15 | #include <float.h> | ||
16 | #include <libinput.h> | ||
14 | #include "stringop.h" | 17 | #include "stringop.h" |
15 | #include "layout.h" | 18 | #include "layout.h" |
16 | #include "focus.h" | 19 | #include "focus.h" |
@@ -26,6 +29,8 @@ | |||
26 | #include "input_state.h" | 29 | #include "input_state.h" |
27 | #include "criteria.h" | 30 | #include "criteria.h" |
28 | #include "ipc-server.h" | 31 | #include "ipc-server.h" |
32 | #include "list.h" | ||
33 | #include "input.h" | ||
29 | 34 | ||
30 | typedef struct cmd_results *sway_cmd(int argc, char **argv); | 35 | typedef struct cmd_results *sway_cmd(int argc, char **argv); |
31 | 36 | ||
@@ -49,6 +54,7 @@ static sway_cmd cmd_focus_follows_mouse; | |||
49 | static sway_cmd cmd_for_window; | 54 | static sway_cmd cmd_for_window; |
50 | static sway_cmd cmd_fullscreen; | 55 | static sway_cmd cmd_fullscreen; |
51 | static sway_cmd cmd_gaps; | 56 | static sway_cmd cmd_gaps; |
57 | static sway_cmd cmd_input; | ||
52 | static sway_cmd cmd_kill; | 58 | static sway_cmd cmd_kill; |
53 | static sway_cmd cmd_layout; | 59 | static sway_cmd cmd_layout; |
54 | static sway_cmd cmd_log_colors; | 60 | static sway_cmd cmd_log_colors; |
@@ -866,6 +872,293 @@ static struct cmd_results *cmd_orientation(int argc, char **argv) { | |||
866 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 872 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
867 | } | 873 | } |
868 | 874 | ||
875 | static void input_cmd_apply(struct input_config *input) { | ||
876 | int i; | ||
877 | i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier); | ||
878 | if (i >= 0) { | ||
879 | // merge existing config | ||
880 | struct input_config *ic = config->input_configs->items[i]; | ||
881 | merge_input_config(ic, input); | ||
882 | free_input_config(input); | ||
883 | input = ic; | ||
884 | } else { | ||
885 | list_add(config->input_configs, input); | ||
886 | } | ||
887 | |||
888 | current_input_config = input; | ||
889 | |||
890 | if (input->identifier) { | ||
891 | // Try to find the input device and apply configuration now. If | ||
892 | // this is during startup then there will be no container and config | ||
893 | // will be applied during normal "new input" event from wlc. | ||
894 | struct libinput_device *device = NULL; | ||
895 | for (int i = 0; i < input_devices->length; ++i) { | ||
896 | device = input_devices->items[i]; | ||
897 | char* dev_identifier = libinput_dev_unique_id(device); | ||
898 | int match = dev_identifier && strcmp(dev_identifier, input->identifier) == 0; | ||
899 | free(dev_identifier); | ||
900 | if (match) { | ||
901 | apply_input_config(input, device); | ||
902 | break; | ||
903 | } | ||
904 | } | ||
905 | } | ||
906 | } | ||
907 | |||
908 | static struct cmd_results *input_cmd_click_method(int argc, char **argv) { | ||
909 | sway_log(L_DEBUG, "click_method for device: %d %s", current_input_config==NULL, current_input_config->identifier); | ||
910 | struct cmd_results *error = NULL; | ||
911 | if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) { | ||
912 | return error; | ||
913 | } | ||
914 | if (!current_input_config) { | ||
915 | return cmd_results_new(CMD_FAILURE, "click_method", "No input device defined."); | ||
916 | } | ||
917 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
918 | |||
919 | if (strcasecmp(argv[0], "none") == 0) { | ||
920 | new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; | ||
921 | } else if (strcasecmp(argv[0], "button_areas") == 0) { | ||
922 | new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; | ||
923 | } else if (strcasecmp(argv[0], "clickfinger") == 0) { | ||
924 | new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; | ||
925 | } else { | ||
926 | return cmd_results_new(CMD_INVALID, "click_method", "Expected 'click_method <none|button_areas|clickfinger'"); | ||
927 | } | ||
928 | |||
929 | input_cmd_apply(new_config); | ||
930 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
931 | } | ||
932 | |||
933 | static struct cmd_results *input_cmd_drag_lock(int argc, char **argv) { | ||
934 | struct cmd_results *error = NULL; | ||
935 | if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) { | ||
936 | return error; | ||
937 | } | ||
938 | if (!current_input_config) { | ||
939 | return cmd_results_new(CMD_FAILURE, "drag_lock", "No input device defined."); | ||
940 | } | ||
941 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
942 | |||
943 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
944 | new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; | ||
945 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
946 | new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; | ||
947 | } else { | ||
948 | return cmd_results_new(CMD_INVALID, "drag_lock", "Expected 'drag_lock <enabled|disabled>'"); | ||
949 | } | ||
950 | |||
951 | input_cmd_apply(new_config); | ||
952 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
953 | } | ||
954 | |||
955 | static struct cmd_results *input_cmd_dwt(int argc, char **argv) { | ||
956 | struct cmd_results *error = NULL; | ||
957 | if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) { | ||
958 | return error; | ||
959 | } | ||
960 | if (!current_input_config) { | ||
961 | return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined."); | ||
962 | } | ||
963 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
964 | |||
965 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
966 | new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED; | ||
967 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
968 | new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED; | ||
969 | } else { | ||
970 | return cmd_results_new(CMD_INVALID, "dwt", "Expected 'dwt <enabled|disabled>'"); | ||
971 | } | ||
972 | |||
973 | input_cmd_apply(new_config); | ||
974 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
975 | } | ||
976 | |||
977 | static struct cmd_results *input_cmd_events(int argc, char **argv) { | ||
978 | sway_log(L_DEBUG, "events for device: %s", current_input_config->identifier); | ||
979 | struct cmd_results *error = NULL; | ||
980 | if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { | ||
981 | return error; | ||
982 | } | ||
983 | if (!current_input_config) { | ||
984 | return cmd_results_new(CMD_FAILURE, "events", "No input device defined."); | ||
985 | } | ||
986 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
987 | |||
988 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
989 | new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; | ||
990 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
991 | new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; | ||
992 | } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { | ||
993 | new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; | ||
994 | } else { | ||
995 | return cmd_results_new(CMD_INVALID, "events", "Expected 'events <enabled|disabled|disabled_on_external_mouse>'"); | ||
996 | } | ||
997 | |||
998 | input_cmd_apply(new_config); | ||
999 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1000 | } | ||
1001 | |||
1002 | static struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { | ||
1003 | struct cmd_results *error = NULL; | ||
1004 | if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) { | ||
1005 | return error; | ||
1006 | } | ||
1007 | if (!current_input_config) { | ||
1008 | return cmd_results_new(CMD_FAILURE, "middle_emulation", "No input device defined."); | ||
1009 | } | ||
1010 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
1011 | |||
1012 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
1013 | new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; | ||
1014 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
1015 | new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; | ||
1016 | } else { | ||
1017 | return cmd_results_new(CMD_INVALID, "middle_emulation", "Expected 'middle_emulation <enabled|disabled>'"); | ||
1018 | } | ||
1019 | |||
1020 | input_cmd_apply(new_config); | ||
1021 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1022 | } | ||
1023 | |||
1024 | static struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { | ||
1025 | struct cmd_results *error = NULL; | ||
1026 | if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) { | ||
1027 | return error; | ||
1028 | } | ||
1029 | if (!current_input_config) { | ||
1030 | return cmd_results_new(CMD_FAILURE, "natural_scoll", "No input device defined."); | ||
1031 | } | ||
1032 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
1033 | |||
1034 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
1035 | new_config->natural_scroll = 1; | ||
1036 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
1037 | new_config->natural_scroll = 0; | ||
1038 | } else { | ||
1039 | return cmd_results_new(CMD_INVALID, "natural_scroll", "Expected 'natural_scroll <enabled|disabled>'"); | ||
1040 | } | ||
1041 | |||
1042 | input_cmd_apply(new_config); | ||
1043 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1044 | } | ||
1045 | |||
1046 | static struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { | ||
1047 | struct cmd_results *error = NULL; | ||
1048 | if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) { | ||
1049 | return error; | ||
1050 | } | ||
1051 | if (!current_input_config) { | ||
1052 | return cmd_results_new(CMD_FAILURE, "pointer_accel", "No input device defined."); | ||
1053 | } | ||
1054 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
1055 | |||
1056 | float pointer_accel = atof(argv[0]); | ||
1057 | if (pointer_accel < -1 || pointer_accel > 1) { | ||
1058 | return cmd_results_new(CMD_INVALID, "pointer_accel", "Input out of range [-1, 1]"); | ||
1059 | } | ||
1060 | new_config->pointer_accel = pointer_accel; | ||
1061 | |||
1062 | input_cmd_apply(new_config); | ||
1063 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1064 | } | ||
1065 | |||
1066 | static struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { | ||
1067 | struct cmd_results *error = NULL; | ||
1068 | if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) { | ||
1069 | return error; | ||
1070 | } | ||
1071 | if (!current_input_config) { | ||
1072 | return cmd_results_new(CMD_FAILURE, "scroll_method", "No input device defined."); | ||
1073 | } | ||
1074 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
1075 | |||
1076 | if (strcasecmp(argv[0], "none") == 0) { | ||
1077 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; | ||
1078 | } else if (strcasecmp(argv[0], "two_finger") == 0) { | ||
1079 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; | ||
1080 | } else if (strcasecmp(argv[0], "edge") == 0) { | ||
1081 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE; | ||
1082 | } else if (strcasecmp(argv[0], "on_button_down") == 0) { | ||
1083 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; | ||
1084 | } else { | ||
1085 | return cmd_results_new(CMD_INVALID, "scroll_method", "Expected 'scroll_method <none|two_finger|edge|on_button_down>'"); | ||
1086 | } | ||
1087 | |||
1088 | input_cmd_apply(new_config); | ||
1089 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1090 | } | ||
1091 | |||
1092 | static struct cmd_results *input_cmd_tap(int argc, char **argv) { | ||
1093 | sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); | ||
1094 | struct cmd_results *error = NULL; | ||
1095 | if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) { | ||
1096 | return error; | ||
1097 | } | ||
1098 | if (!current_input_config) { | ||
1099 | return cmd_results_new(CMD_FAILURE, "tap", "No input device defined."); | ||
1100 | } | ||
1101 | struct input_config *new_config = new_input_config(current_input_config->identifier); | ||
1102 | |||
1103 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
1104 | new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED; | ||
1105 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
1106 | new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED; | ||
1107 | } else { | ||
1108 | return cmd_results_new(CMD_INVALID, "tap", "Expected 'tap <enabled|disabled>'"); | ||
1109 | } | ||
1110 | |||
1111 | sway_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); | ||
1112 | input_cmd_apply(new_config); | ||
1113 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
1114 | } | ||
1115 | |||
1116 | static struct cmd_results *cmd_input(int argc, char **argv) { | ||
1117 | struct cmd_results *error = NULL; | ||
1118 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { | ||
1119 | return error; | ||
1120 | } | ||
1121 | |||
1122 | if (config->reading && strcmp("{", argv[1]) == 0) { | ||
1123 | current_input_config = new_input_config(argv[0]); | ||
1124 | sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); | ||
1125 | return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); | ||
1126 | } | ||
1127 | |||
1128 | if (argc > 2) { | ||
1129 | int argc_new = argc-2; | ||
1130 | char **argv_new = argv+2; | ||
1131 | |||
1132 | struct cmd_results *res; | ||
1133 | current_input_config = new_input_config(argv[0]); | ||
1134 | if (strcasecmp("click_method", argv[1]) == 0) { | ||
1135 | res = input_cmd_click_method(argc_new, argv_new); | ||
1136 | } else if (strcasecmp("drag_lock", argv[1]) == 0) { | ||
1137 | res = input_cmd_drag_lock(argc_new, argv_new); | ||
1138 | } else if (strcasecmp("dwt", argv[1]) == 0) { | ||
1139 | res = input_cmd_dwt(argc_new, argv_new); | ||
1140 | } else if (strcasecmp("events", argv[1]) == 0) { | ||
1141 | res = input_cmd_events(argc_new, argv_new); | ||
1142 | } else if (strcasecmp("middle_emulation", argv[1]) == 0) { | ||
1143 | res = input_cmd_middle_emulation(argc_new, argv_new); | ||
1144 | } else if (strcasecmp("natural_scroll", argv[1]) == 0) { | ||
1145 | res = input_cmd_natural_scroll(argc_new, argv_new); | ||
1146 | } else if (strcasecmp("pointer_accel", argv[1]) == 0) { | ||
1147 | res = input_cmd_pointer_accel(argc_new, argv_new); | ||
1148 | } else if (strcasecmp("scroll_method", argv[1]) == 0) { | ||
1149 | res = input_cmd_scroll_method(argc_new, argv_new); | ||
1150 | } else if (strcasecmp("tap", argv[1]) == 0) { | ||
1151 | res = input_cmd_tap(argc_new, argv_new); | ||
1152 | } else { | ||
1153 | res = cmd_results_new(CMD_INVALID, "input <device>", "Unknonwn command %s", argv[1]); | ||
1154 | } | ||
1155 | current_input_config = NULL; | ||
1156 | return res; | ||
1157 | } | ||
1158 | |||
1159 | return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); | ||
1160 | } | ||
1161 | |||
869 | static struct cmd_results *cmd_output(int argc, char **argv) { | 1162 | static struct cmd_results *cmd_output(int argc, char **argv) { |
870 | struct cmd_results *error = NULL; | 1163 | struct cmd_results *error = NULL; |
871 | if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { | 1164 | if ((error = checkarg(argc, "output", EXPECTED_AT_LEAST, 1))) { |
@@ -1683,6 +1976,7 @@ static struct cmd_handler handlers[] = { | |||
1683 | { "for_window", cmd_for_window }, | 1976 | { "for_window", cmd_for_window }, |
1684 | { "fullscreen", cmd_fullscreen }, | 1977 | { "fullscreen", cmd_fullscreen }, |
1685 | { "gaps", cmd_gaps }, | 1978 | { "gaps", cmd_gaps }, |
1979 | { "input", cmd_input }, | ||
1686 | { "kill", cmd_kill }, | 1980 | { "kill", cmd_kill }, |
1687 | { "layout", cmd_layout }, | 1981 | { "layout", cmd_layout }, |
1688 | { "log_colors", cmd_log_colors }, | 1982 | { "log_colors", cmd_log_colors }, |
@@ -2422,6 +2716,18 @@ static struct cmd_results *bar_colors_cmd_urgent_workspace(int argc, char **argv | |||
2422 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 2716 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
2423 | } | 2717 | } |
2424 | 2718 | ||
2719 | static struct cmd_handler input_handlers[] = { | ||
2720 | { "click_method", input_cmd_click_method }, | ||
2721 | { "drag_lock", input_cmd_drag_lock }, | ||
2722 | { "dwt", input_cmd_dwt }, | ||
2723 | { "events", input_cmd_events }, | ||
2724 | { "middle_emulation", input_cmd_middle_emulation }, | ||
2725 | { "natural_scroll", input_cmd_natural_scroll }, | ||
2726 | { "pointer_accel", input_cmd_pointer_accel }, | ||
2727 | { "scroll_method", input_cmd_scroll_method }, | ||
2728 | { "tap", input_cmd_tap }, | ||
2729 | }; | ||
2730 | |||
2425 | static struct cmd_handler bar_colors_handlers[] = { | 2731 | static struct cmd_handler bar_colors_handlers[] = { |
2426 | { "active_workspace", bar_colors_cmd_active_workspace }, | 2732 | { "active_workspace", bar_colors_cmd_active_workspace }, |
2427 | { "background", bar_colors_cmd_background }, | 2733 | { "background", bar_colors_cmd_background }, |
@@ -2442,6 +2748,7 @@ static int handler_compare(const void *_a, const void *_b) { | |||
2442 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { | 2748 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { |
2443 | struct cmd_handler d = { .command=line }; | 2749 | struct cmd_handler d = { .command=line }; |
2444 | struct cmd_handler *res = NULL; | 2750 | struct cmd_handler *res = NULL; |
2751 | sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_INPUT); | ||
2445 | if (block == CMD_BLOCK_BAR) { | 2752 | if (block == CMD_BLOCK_BAR) { |
2446 | res = bsearch(&d, bar_handlers, | 2753 | res = bsearch(&d, bar_handlers, |
2447 | sizeof(bar_handlers) / sizeof(struct cmd_handler), | 2754 | sizeof(bar_handlers) / sizeof(struct cmd_handler), |
@@ -2450,6 +2757,11 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { | |||
2450 | res = bsearch(&d, bar_colors_handlers, | 2757 | res = bsearch(&d, bar_colors_handlers, |
2451 | sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), | 2758 | sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), |
2452 | sizeof(struct cmd_handler), handler_compare); | 2759 | sizeof(struct cmd_handler), handler_compare); |
2760 | } else if (block == CMD_BLOCK_INPUT) { | ||
2761 | sway_log(L_DEBUG, "lookng at input handlers"); | ||
2762 | res = bsearch(&d, input_handlers, | ||
2763 | sizeof(input_handlers) / sizeof(struct cmd_handler), | ||
2764 | sizeof(struct cmd_handler), handler_compare); | ||
2453 | } else { | 2765 | } else { |
2454 | res = bsearch(&d, handlers, | 2766 | res = bsearch(&d, handlers, |
2455 | sizeof(handlers) / sizeof(struct cmd_handler), | 2767 | sizeof(handlers) / sizeof(struct cmd_handler), |