diff options
43 files changed, 2045 insertions, 124 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index b1f0423d..61950d0d 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _SWAY_COMMANDS_H | 1 | #ifndef _SWAY_COMMANDS_H |
2 | #define _SWAY_COMMANDS_H | 2 | #define _SWAY_COMMANDS_H |
3 | 3 | ||
4 | #include "config.h" | ||
5 | |||
4 | /** | 6 | /** |
5 | * Indicates the result of a command's execution. | 7 | * Indicates the result of a command's execution. |
6 | */ | 8 | */ |
@@ -15,6 +17,7 @@ enum cmd_status { | |||
15 | CMD_BLOCK_BAR, | 17 | CMD_BLOCK_BAR, |
16 | CMD_BLOCK_BAR_COLORS, | 18 | CMD_BLOCK_BAR_COLORS, |
17 | CMD_BLOCK_INPUT, | 19 | CMD_BLOCK_INPUT, |
20 | CMD_BLOCK_SEAT, | ||
18 | CMD_BLOCK_COMMANDS, | 21 | CMD_BLOCK_COMMANDS, |
19 | CMD_BLOCK_IPC, | 22 | CMD_BLOCK_IPC, |
20 | CMD_BLOCK_IPC_EVENTS, | 23 | CMD_BLOCK_IPC_EVENTS, |
@@ -39,6 +42,9 @@ enum expected_args { | |||
39 | EXPECTED_EQUAL_TO | 42 | EXPECTED_EQUAL_TO |
40 | }; | 43 | }; |
41 | 44 | ||
45 | void input_cmd_apply(struct input_config *input); | ||
46 | void seat_cmd_apply(struct seat_config *seat); | ||
47 | |||
42 | struct cmd_results *checkarg(int argc, const char *name, | 48 | struct cmd_results *checkarg(int argc, const char *name, |
43 | enum expected_args type, int val); | 49 | enum expected_args type, int val); |
44 | 50 | ||
@@ -107,6 +113,7 @@ sway_cmd cmd_gaps; | |||
107 | sway_cmd cmd_hide_edge_borders; | 113 | sway_cmd cmd_hide_edge_borders; |
108 | sway_cmd cmd_include; | 114 | sway_cmd cmd_include; |
109 | sway_cmd cmd_input; | 115 | sway_cmd cmd_input; |
116 | sway_cmd cmd_seat; | ||
110 | sway_cmd cmd_ipc; | 117 | sway_cmd cmd_ipc; |
111 | sway_cmd cmd_kill; | 118 | sway_cmd cmd_kill; |
112 | sway_cmd cmd_layout; | 119 | sway_cmd cmd_layout; |
@@ -176,6 +183,7 @@ sway_cmd bar_colors_cmd_statusline; | |||
176 | sway_cmd bar_colors_cmd_focused_statusline; | 183 | sway_cmd bar_colors_cmd_focused_statusline; |
177 | sway_cmd bar_colors_cmd_urgent_workspace; | 184 | sway_cmd bar_colors_cmd_urgent_workspace; |
178 | 185 | ||
186 | sway_cmd input_cmd_seat; | ||
179 | sway_cmd input_cmd_accel_profile; | 187 | sway_cmd input_cmd_accel_profile; |
180 | sway_cmd input_cmd_click_method; | 188 | sway_cmd input_cmd_click_method; |
181 | sway_cmd input_cmd_drag_lock; | 189 | sway_cmd input_cmd_drag_lock; |
@@ -187,6 +195,13 @@ sway_cmd input_cmd_natural_scroll; | |||
187 | sway_cmd input_cmd_pointer_accel; | 195 | sway_cmd input_cmd_pointer_accel; |
188 | sway_cmd input_cmd_scroll_method; | 196 | sway_cmd input_cmd_scroll_method; |
189 | sway_cmd input_cmd_tap; | 197 | sway_cmd input_cmd_tap; |
198 | sway_cmd input_cmd_xkb_layout; | ||
199 | sway_cmd input_cmd_xkb_model; | ||
200 | sway_cmd input_cmd_xkb_options; | ||
201 | sway_cmd input_cmd_xkb_rules; | ||
202 | sway_cmd input_cmd_xkb_variant; | ||
203 | |||
204 | sway_cmd seat_cmd_attach; | ||
190 | 205 | ||
191 | sway_cmd cmd_ipc_cmd; | 206 | sway_cmd cmd_ipc_cmd; |
192 | sway_cmd cmd_ipc_events; | 207 | sway_cmd cmd_ipc_events; |
diff --git a/include/sway/config.h b/include/sway/config.h index 139d7800..777fb5a8 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -67,11 +67,33 @@ struct input_config { | |||
67 | int send_events; | 67 | int send_events; |
68 | int tap; | 68 | int tap; |
69 | 69 | ||
70 | char *xkb_layout; | ||
71 | char *xkb_model; | ||
72 | char *xkb_options; | ||
73 | char *xkb_rules; | ||
74 | char *xkb_variant; | ||
75 | |||
70 | bool capturable; | 76 | bool capturable; |
71 | struct wlr_box region; | 77 | struct wlr_box region; |
72 | }; | 78 | }; |
73 | 79 | ||
74 | /** | 80 | /** |
81 | * Options for misc device configurations that happen in the seat block | ||
82 | */ | ||
83 | struct seat_attachment_config { | ||
84 | char *identifier; | ||
85 | // TODO other things are configured here for some reason | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * Options for multiseat and other misc device configurations | ||
90 | */ | ||
91 | struct seat_config { | ||
92 | char *name; | ||
93 | list_t *attachments; // list of seat_attachment configs | ||
94 | }; | ||
95 | |||
96 | /** | ||
75 | * Size and position configuration for a particular output. | 97 | * Size and position configuration for a particular output. |
76 | * | 98 | * |
77 | * This is set via the `output` command. | 99 | * This is set via the `output` command. |
@@ -262,6 +284,7 @@ struct sway_config { | |||
262 | list_t *pid_workspaces; | 284 | list_t *pid_workspaces; |
263 | list_t *output_configs; | 285 | list_t *output_configs; |
264 | list_t *input_configs; | 286 | list_t *input_configs; |
287 | list_t *seat_configs; | ||
265 | list_t *criteria; | 288 | list_t *criteria; |
266 | list_t *no_focus; | 289 | list_t *no_focus; |
267 | list_t *active_bar_modifiers; | 290 | list_t *active_bar_modifiers; |
@@ -358,10 +381,18 @@ char *do_var_replacement(char *str); | |||
358 | struct cmd_results *check_security_config(); | 381 | struct cmd_results *check_security_config(); |
359 | 382 | ||
360 | int input_identifier_cmp(const void *item, const void *data); | 383 | int input_identifier_cmp(const void *item, const void *data); |
384 | struct input_config *new_input_config(const char* identifier); | ||
361 | void merge_input_config(struct input_config *dst, struct input_config *src); | 385 | void merge_input_config(struct input_config *dst, struct input_config *src); |
362 | void apply_input_config(struct input_config *ic, struct libinput_device *dev); | ||
363 | void free_input_config(struct input_config *ic); | 386 | void free_input_config(struct input_config *ic); |
364 | 387 | ||
388 | int seat_name_cmp(const void *item, const void *data); | ||
389 | struct seat_config *new_seat_config(const char* name); | ||
390 | void merge_seat_config(struct seat_config *dst, struct seat_config *src); | ||
391 | void free_seat_config(struct seat_config *ic); | ||
392 | struct seat_attachment_config *seat_attachment_config_new(); | ||
393 | struct seat_attachment_config *seat_config_get_attachment( | ||
394 | struct seat_config *seat_config, char *identifier); | ||
395 | |||
365 | int output_name_cmp(const void *item, const void *data); | 396 | int output_name_cmp(const void *item, const void *data); |
366 | struct output_config *new_output_config(); | 397 | struct output_config *new_output_config(); |
367 | void merge_output_config(struct output_config *dst, struct output_config *src); | 398 | void merge_output_config(struct output_config *dst, struct output_config *src); |
diff --git a/include/sway/container.h b/include/sway/container.h index b15e0428..9a5e312b 100644 --- a/include/sway/container.h +++ b/include/sway/container.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <stdint.h> | 3 | #include <stdint.h> |
4 | #include <sys/types.h> | 4 | #include <sys/types.h> |
5 | #include <wlr/types/wlr_box.h> | 5 | #include <wlr/types/wlr_box.h> |
6 | #include <wlr/types/wlr_surface.h> | ||
6 | #include "list.h" | 7 | #include "list.h" |
7 | 8 | ||
8 | typedef struct sway_container swayc_t; | 9 | typedef struct sway_container swayc_t; |
@@ -123,6 +124,10 @@ struct sway_container { | |||
123 | * Marks applied to the container, list_t of char*. | 124 | * Marks applied to the container, list_t of char*. |
124 | */ | 125 | */ |
125 | list_t *marks; | 126 | list_t *marks; |
127 | |||
128 | struct { | ||
129 | struct wl_signal destroy; | ||
130 | } events; | ||
126 | }; | 131 | }; |
127 | 132 | ||
128 | void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, | 133 | void swayc_descendants_of_type(swayc_t *root, enum swayc_types type, |
@@ -137,4 +142,7 @@ swayc_t *destroy_view(swayc_t *view); | |||
137 | 142 | ||
138 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); | 143 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); |
139 | 144 | ||
145 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, | ||
146 | struct wlr_surface **surface, double *sx, double *sy); | ||
147 | |||
140 | #endif | 148 | #endif |
diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h new file mode 100644 index 00000000..cc529de6 --- /dev/null +++ b/include/sway/input/cursor.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef _SWAY_CURSOR_H | ||
2 | #define _SWAY_CURSOR_H | ||
3 | |||
4 | #include "sway/input/seat.h" | ||
5 | |||
6 | struct sway_cursor { | ||
7 | struct sway_seat *seat; | ||
8 | struct wlr_cursor *cursor; | ||
9 | struct wlr_xcursor_manager *xcursor_manager; | ||
10 | |||
11 | double x, y; | ||
12 | |||
13 | struct wl_listener motion; | ||
14 | struct wl_listener motion_absolute; | ||
15 | struct wl_listener button; | ||
16 | struct wl_listener axis; | ||
17 | |||
18 | struct wl_listener touch_down; | ||
19 | struct wl_listener touch_up; | ||
20 | struct wl_listener touch_motion; | ||
21 | |||
22 | struct wl_listener tool_axis; | ||
23 | struct wl_listener tool_tip; | ||
24 | |||
25 | struct wl_listener request_set_cursor; | ||
26 | }; | ||
27 | |||
28 | struct sway_cursor *sway_cursor_create(struct sway_seat *seat); | ||
29 | |||
30 | #endif | ||
diff --git a/include/sway/input/input-manager.h b/include/sway/input/input-manager.h new file mode 100644 index 00000000..cdcffab6 --- /dev/null +++ b/include/sway/input/input-manager.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef _SWAY_INPUT_MANAGER_H | ||
2 | #define _SWAY_INPUT_MANAGER_H | ||
3 | #include <libinput.h> | ||
4 | #include "sway/server.h" | ||
5 | #include "sway/config.h" | ||
6 | #include "list.h" | ||
7 | |||
8 | extern struct input_config *current_input_config; | ||
9 | extern struct seat_config *current_seat_config; | ||
10 | |||
11 | /** | ||
12 | * The global singleton input manager | ||
13 | * TODO: make me not a global | ||
14 | */ | ||
15 | extern struct sway_input_manager *input_manager; | ||
16 | |||
17 | struct sway_input_device { | ||
18 | char *identifier; | ||
19 | struct wlr_input_device *wlr_device; | ||
20 | struct input_config *config; | ||
21 | struct wl_list link; | ||
22 | }; | ||
23 | |||
24 | struct sway_input_manager { | ||
25 | struct wl_listener input_add; | ||
26 | struct wl_listener input_remove; | ||
27 | struct sway_server *server; | ||
28 | struct wl_list devices; | ||
29 | struct wl_list seats; | ||
30 | }; | ||
31 | |||
32 | struct sway_input_manager *sway_input_manager_create( | ||
33 | struct sway_server *server); | ||
34 | |||
35 | bool sway_input_manager_has_focus(struct sway_input_manager *input, | ||
36 | swayc_t *container); | ||
37 | |||
38 | void sway_input_manager_set_focus(struct sway_input_manager *input, | ||
39 | swayc_t *container); | ||
40 | |||
41 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input); | ||
42 | |||
43 | void sway_input_manager_apply_input_config(struct sway_input_manager *input, | ||
44 | struct input_config *input_config); | ||
45 | |||
46 | void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | ||
47 | struct seat_config *seat_config); | ||
48 | |||
49 | #endif | ||
diff --git a/include/sway/input/keyboard.h b/include/sway/input/keyboard.h new file mode 100644 index 00000000..89cde3fa --- /dev/null +++ b/include/sway/input/keyboard.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #include "sway/input/seat.h" | ||
2 | |||
3 | struct sway_keyboard { | ||
4 | struct sway_seat_device *seat_device; | ||
5 | struct wl_list link; // sway_seat::keyboards | ||
6 | |||
7 | struct xkb_keymap *keymap; | ||
8 | |||
9 | struct wl_listener keyboard_key; | ||
10 | struct wl_listener keyboard_modifiers; | ||
11 | }; | ||
12 | |||
13 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | ||
14 | struct sway_seat_device *device); | ||
15 | |||
16 | void sway_keyboard_configure(struct sway_keyboard *keyboard); | ||
17 | |||
18 | void sway_keyboard_destroy(struct sway_keyboard *keyboard); | ||
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h new file mode 100644 index 00000000..db69f83e --- /dev/null +++ b/include/sway/input/seat.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef _SWAY_SEAT_H | ||
2 | #define _SWAY_SEAT_H | ||
3 | |||
4 | #include <wlr/types/wlr_seat.h> | ||
5 | #include "sway/input/input-manager.h" | ||
6 | |||
7 | struct sway_seat_device { | ||
8 | struct sway_seat *sway_seat; | ||
9 | struct sway_input_device *input_device; | ||
10 | struct sway_keyboard *keyboard; | ||
11 | struct seat_attachment_config *attachment_config; | ||
12 | struct wl_list link; // sway_seat::devices | ||
13 | }; | ||
14 | |||
15 | struct sway_seat { | ||
16 | struct wlr_seat *wlr_seat; | ||
17 | struct seat_config *config; | ||
18 | struct sway_cursor *cursor; | ||
19 | struct sway_input_manager *input; | ||
20 | swayc_t *focus; | ||
21 | |||
22 | struct wl_listener focus_destroy; | ||
23 | |||
24 | struct wl_list devices; // sway_seat_device::link | ||
25 | |||
26 | struct wl_list link; // input_manager::seats | ||
27 | }; | ||
28 | |||
29 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | ||
30 | const char *seat_name); | ||
31 | |||
32 | void sway_seat_add_device(struct sway_seat *seat, | ||
33 | struct sway_input_device *device); | ||
34 | |||
35 | void sway_seat_configure_device(struct sway_seat *seat, | ||
36 | struct sway_input_device *device); | ||
37 | |||
38 | void sway_seat_remove_device(struct sway_seat *seat, | ||
39 | struct sway_input_device *device); | ||
40 | |||
41 | void sway_seat_configure_xcursor(struct sway_seat *seat); | ||
42 | |||
43 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container); | ||
44 | |||
45 | void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config); | ||
46 | |||
47 | #endif | ||
diff --git a/include/sway/server.h b/include/sway/server.h index 3fa72e84..76a05476 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -22,7 +22,7 @@ struct sway_server { | |||
22 | struct wlr_compositor *compositor; | 22 | struct wlr_compositor *compositor; |
23 | struct wlr_data_device_manager *data_device_manager; | 23 | struct wlr_data_device_manager *data_device_manager; |
24 | 24 | ||
25 | struct sway_input *input; | 25 | struct sway_input_manager *input; |
26 | 26 | ||
27 | struct wl_listener output_add; | 27 | struct wl_listener output_add; |
28 | struct wl_listener output_remove; | 28 | struct wl_listener output_remove; |
diff --git a/meson.build b/meson.build index 8e7b98ed..029aea46 100644 --- a/meson.build +++ b/meson.build | |||
@@ -29,6 +29,7 @@ xkbcommon = dependency('xkbcommon') | |||
29 | pango = dependency('pango') | 29 | pango = dependency('pango') |
30 | pixman = dependency('pixman-1') | 30 | pixman = dependency('pixman-1') |
31 | libcap = dependency('libcap') | 31 | libcap = dependency('libcap') |
32 | libinput = dependency('libinput') | ||
32 | math = cc.find_library('m') | 33 | math = cc.find_library('m') |
33 | git = find_program('git', required: false) | 34 | git = find_program('git', required: false) |
34 | a2x = find_program('a2x', required: false) | 35 | a2x = find_program('a2x', required: false) |
diff --git a/sway/commands.c b/sway/commands.c index d6cf7a64..7485f2f6 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "sway/commands.h" | 9 | #include "sway/commands.h" |
10 | #include "sway/config.h" | 10 | #include "sway/config.h" |
11 | #include "sway/security.h" | 11 | #include "sway/security.h" |
12 | #include "sway/input/input-manager.h" | ||
12 | #include "stringop.h" | 13 | #include "stringop.h" |
13 | #include "log.h" | 14 | #include "log.h" |
14 | 15 | ||
@@ -56,6 +57,40 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type | |||
56 | return error; | 57 | return error; |
57 | } | 58 | } |
58 | 59 | ||
60 | void input_cmd_apply(struct input_config *input) { | ||
61 | int i; | ||
62 | i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier); | ||
63 | if (i >= 0) { | ||
64 | // merge existing config | ||
65 | struct input_config *ic = config->input_configs->items[i]; | ||
66 | merge_input_config(ic, input); | ||
67 | free_input_config(input); | ||
68 | input = ic; | ||
69 | } else { | ||
70 | list_add(config->input_configs, input); | ||
71 | } | ||
72 | |||
73 | current_input_config = input; | ||
74 | sway_input_manager_apply_input_config(input_manager, input); | ||
75 | } | ||
76 | |||
77 | void seat_cmd_apply(struct seat_config *seat) { | ||
78 | int i; | ||
79 | i = list_seq_find(config->seat_configs, seat_name_cmp, seat->name); | ||
80 | if (i >= 0) { | ||
81 | // merge existing config | ||
82 | struct seat_config *sc = config->seat_configs->items[i]; | ||
83 | merge_seat_config(sc, seat); | ||
84 | free_seat_config(seat); | ||
85 | seat = sc; | ||
86 | } else { | ||
87 | list_add(config->seat_configs, seat); | ||
88 | } | ||
89 | |||
90 | current_seat_config = seat; | ||
91 | sway_input_manager_apply_seat_config(input_manager, seat); | ||
92 | } | ||
93 | |||
59 | /** | 94 | /** |
60 | * Check and add color to buffer. | 95 | * Check and add color to buffer. |
61 | * | 96 | * |
@@ -96,7 +131,9 @@ static struct cmd_handler handlers[] = { | |||
96 | { "exec_always", cmd_exec_always }, | 131 | { "exec_always", cmd_exec_always }, |
97 | { "exit", cmd_exit }, | 132 | { "exit", cmd_exit }, |
98 | { "include", cmd_include }, | 133 | { "include", cmd_include }, |
134 | { "input", cmd_input }, | ||
99 | { "output", cmd_output }, | 135 | { "output", cmd_output }, |
136 | { "seat", cmd_seat }, | ||
100 | }; | 137 | }; |
101 | 138 | ||
102 | static int handler_compare(const void *_a, const void *_b) { | 139 | static int handler_compare(const void *_a, const void *_b) { |
@@ -105,37 +142,50 @@ static int handler_compare(const void *_a, const void *_b) { | |||
105 | return strcasecmp(a->command, b->command); | 142 | return strcasecmp(a->command, b->command); |
106 | } | 143 | } |
107 | 144 | ||
145 | // must be in order for the bsearch | ||
146 | static struct cmd_handler input_handlers[] = { | ||
147 | { "accel_profile", input_cmd_accel_profile }, | ||
148 | { "click_method", input_cmd_click_method }, | ||
149 | { "drag_lock", input_cmd_drag_lock }, | ||
150 | { "dwt", input_cmd_dwt }, | ||
151 | { "events", input_cmd_events }, | ||
152 | { "left_handed", input_cmd_left_handed }, | ||
153 | { "middle_emulation", input_cmd_middle_emulation }, | ||
154 | { "natural_scroll", input_cmd_natural_scroll }, | ||
155 | { "pointer_accel", input_cmd_pointer_accel }, | ||
156 | { "scroll_method", input_cmd_scroll_method }, | ||
157 | { "tap", input_cmd_tap }, | ||
158 | { "xkb_layout", input_cmd_xkb_layout }, | ||
159 | { "xkb_model", input_cmd_xkb_model }, | ||
160 | { "xkb_options", input_cmd_xkb_options }, | ||
161 | { "xkb_rules", input_cmd_xkb_rules }, | ||
162 | { "xkb_variant", input_cmd_xkb_variant }, | ||
163 | }; | ||
164 | |||
165 | // must be in order for the bsearch | ||
166 | static struct cmd_handler seat_handlers[] = { | ||
167 | { "attach", seat_cmd_attach }, | ||
168 | }; | ||
169 | |||
108 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { | 170 | static struct cmd_handler *find_handler(char *line, enum cmd_status block) { |
109 | struct cmd_handler d = { .command=line }; | 171 | struct cmd_handler d = { .command=line }; |
110 | struct cmd_handler *res = NULL; | 172 | struct cmd_handler *res = NULL; |
111 | sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_INPUT); | 173 | sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); |
112 | /* TODO | 174 | |
113 | if (block == CMD_BLOCK_BAR) { | 175 | if (block == CMD_BLOCK_INPUT) { |
114 | res = bsearch(&d, bar_handlers, | ||
115 | sizeof(bar_handlers) / sizeof(struct cmd_handler), | ||
116 | sizeof(struct cmd_handler), handler_compare); | ||
117 | } else if (block == CMD_BLOCK_BAR_COLORS){ | ||
118 | res = bsearch(&d, bar_colors_handlers, | ||
119 | sizeof(bar_colors_handlers) / sizeof(struct cmd_handler), | ||
120 | sizeof(struct cmd_handler), handler_compare); | ||
121 | } else if (block == CMD_BLOCK_INPUT) { | ||
122 | res = bsearch(&d, input_handlers, | 176 | res = bsearch(&d, input_handlers, |
123 | sizeof(input_handlers) / sizeof(struct cmd_handler), | 177 | sizeof(input_handlers) / sizeof(struct cmd_handler), |
124 | sizeof(struct cmd_handler), handler_compare); | 178 | sizeof(struct cmd_handler), handler_compare); |
125 | } else if (block == CMD_BLOCK_IPC) { | 179 | } else if (block == CMD_BLOCK_SEAT) { |
126 | res = bsearch(&d, ipc_handlers, | 180 | res = bsearch(&d, seat_handlers, |
127 | sizeof(ipc_handlers) / sizeof(struct cmd_handler), | 181 | sizeof(seat_handlers) / sizeof(struct cmd_handler), |
128 | sizeof(struct cmd_handler), handler_compare); | 182 | sizeof(struct cmd_handler), handler_compare); |
129 | } else if (block == CMD_BLOCK_IPC_EVENTS) { | ||
130 | res = bsearch(&d, ipc_event_handlers, | ||
131 | sizeof(ipc_event_handlers) / sizeof(struct cmd_handler), | ||
132 | sizeof(struct cmd_handler), handler_compare); | ||
133 | } else { | 183 | } else { |
134 | */ | ||
135 | res = bsearch(&d, handlers, | 184 | res = bsearch(&d, handlers, |
136 | sizeof(handlers) / sizeof(struct cmd_handler), | 185 | sizeof(handlers) / sizeof(struct cmd_handler), |
137 | sizeof(struct cmd_handler), handler_compare); | 186 | sizeof(struct cmd_handler), handler_compare); |
138 | //} | 187 | } |
188 | |||
139 | return res; | 189 | return res; |
140 | } | 190 | } |
141 | 191 | ||
@@ -239,8 +289,8 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { | |||
239 | argv[i] = do_var_replacement(argv[i]); | 289 | argv[i] = do_var_replacement(argv[i]); |
240 | unescape_string(argv[i]); | 290 | unescape_string(argv[i]); |
241 | } | 291 | } |
242 | /* Strip quotes for first argument. | 292 | // Strip quotes for first argument. |
243 | * TODO This part needs to be handled much better */ | 293 | // TODO This part needs to be handled much better |
244 | if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) { | 294 | if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) { |
245 | strip_quotes(argv[1]); | 295 | strip_quotes(argv[1]); |
246 | } | 296 | } |
diff --git a/sway/commands/input.c b/sway/commands/input.c new file mode 100644 index 00000000..5ca9c2e6 --- /dev/null +++ b/sway/commands/input.c | |||
@@ -0,0 +1,55 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "log.h" | ||
6 | |||
7 | struct cmd_results *cmd_input(int argc, char **argv) { | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "input", EXPECTED_AT_LEAST, 2))) { | ||
10 | return error; | ||
11 | } | ||
12 | |||
13 | if (config->reading && strcmp("{", argv[1]) == 0) { | ||
14 | current_input_config = new_input_config(argv[0]); | ||
15 | sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); | ||
16 | return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); | ||
17 | } | ||
18 | |||
19 | if (argc > 2) { | ||
20 | int argc_new = argc-2; | ||
21 | char **argv_new = argv+2; | ||
22 | |||
23 | struct cmd_results *res; | ||
24 | current_input_config = new_input_config(argv[0]); | ||
25 | if (strcasecmp("accel_profile", argv[1]) == 0) { | ||
26 | res = input_cmd_accel_profile(argc_new, argv_new); | ||
27 | } else if (strcasecmp("click_method", argv[1]) == 0) { | ||
28 | res = input_cmd_click_method(argc_new, argv_new); | ||
29 | } else if (strcasecmp("drag_lock", argv[1]) == 0) { | ||
30 | res = input_cmd_drag_lock(argc_new, argv_new); | ||
31 | } else if (strcasecmp("dwt", argv[1]) == 0) { | ||
32 | res = input_cmd_dwt(argc_new, argv_new); | ||
33 | } else if (strcasecmp("events", argv[1]) == 0) { | ||
34 | res = input_cmd_events(argc_new, argv_new); | ||
35 | } else if (strcasecmp("left_handed", argv[1]) == 0) { | ||
36 | res = input_cmd_left_handed(argc_new, argv_new); | ||
37 | } else if (strcasecmp("middle_emulation", argv[1]) == 0) { | ||
38 | res = input_cmd_middle_emulation(argc_new, argv_new); | ||
39 | } else if (strcasecmp("natural_scroll", argv[1]) == 0) { | ||
40 | res = input_cmd_natural_scroll(argc_new, argv_new); | ||
41 | } else if (strcasecmp("pointer_accel", argv[1]) == 0) { | ||
42 | res = input_cmd_pointer_accel(argc_new, argv_new); | ||
43 | } else if (strcasecmp("scroll_method", argv[1]) == 0) { | ||
44 | res = input_cmd_scroll_method(argc_new, argv_new); | ||
45 | } else if (strcasecmp("tap", argv[1]) == 0) { | ||
46 | res = input_cmd_tap(argc_new, argv_new); | ||
47 | } else { | ||
48 | res = cmd_results_new(CMD_INVALID, "input <device>", "Unknown command %s", argv[1]); | ||
49 | } | ||
50 | current_input_config = NULL; | ||
51 | return res; | ||
52 | } | ||
53 | |||
54 | return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); | ||
55 | } | ||
diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c new file mode 100644 index 00000000..9b5fb7a2 --- /dev/null +++ b/sway/commands/input/accel_profile.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_accel_profile(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "accel_profile", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, "accel_profile", | ||
13 | "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | if (strcasecmp(argv[0], "adaptive") == 0) { | ||
19 | new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; | ||
20 | } else if (strcasecmp(argv[0], "flat") == 0) { | ||
21 | new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; | ||
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, "accel_profile", | ||
24 | "Expected 'accel_profile <adaptive|flat>'"); | ||
25 | } | ||
26 | |||
27 | input_cmd_apply(new_config); | ||
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
29 | } | ||
diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c new file mode 100644 index 00000000..a0e3bddf --- /dev/null +++ b/sway/commands/input/click_method.c | |||
@@ -0,0 +1,34 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "log.h" | ||
6 | |||
7 | struct cmd_results *input_cmd_click_method(int argc, char **argv) { | ||
8 | sway_log(L_DEBUG, "click_method for device: %d %s", | ||
9 | current_input_config==NULL, current_input_config->identifier); | ||
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) { | ||
12 | return error; | ||
13 | } | ||
14 | if (!current_input_config) { | ||
15 | return cmd_results_new(CMD_FAILURE, "click_method", | ||
16 | "No input device defined."); | ||
17 | } | ||
18 | struct input_config *new_config = | ||
19 | new_input_config(current_input_config->identifier); | ||
20 | |||
21 | if (strcasecmp(argv[0], "none") == 0) { | ||
22 | new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; | ||
23 | } else if (strcasecmp(argv[0], "button_areas") == 0) { | ||
24 | new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; | ||
25 | } else if (strcasecmp(argv[0], "clickfinger") == 0) { | ||
26 | new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; | ||
27 | } else { | ||
28 | return cmd_results_new(CMD_INVALID, "click_method", | ||
29 | "Expected 'click_method <none|button_areas|clickfinger'"); | ||
30 | } | ||
31 | |||
32 | input_cmd_apply(new_config); | ||
33 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
34 | } | ||
diff --git a/sway/commands/input/drag_lock.c b/sway/commands/input/drag_lock.c new file mode 100644 index 00000000..149a6183 --- /dev/null +++ b/sway/commands/input/drag_lock.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_drag_lock(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, | ||
13 | "drag_lock", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
19 | new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED; | ||
20 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
21 | new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; | ||
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, "drag_lock", | ||
24 | "Expected 'drag_lock <enabled|disabled>'"); | ||
25 | } | ||
26 | |||
27 | input_cmd_apply(new_config); | ||
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
29 | } | ||
diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c new file mode 100644 index 00000000..0954575c --- /dev/null +++ b/sway/commands/input/dwt.c | |||
@@ -0,0 +1,28 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_dwt(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined."); | ||
13 | } | ||
14 | struct input_config *new_config = | ||
15 | new_input_config(current_input_config->identifier); | ||
16 | |||
17 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
18 | new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED; | ||
19 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
20 | new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED; | ||
21 | } else { | ||
22 | return cmd_results_new(CMD_INVALID, "dwt", | ||
23 | "Expected 'dwt <enabled|disabled>'"); | ||
24 | } | ||
25 | |||
26 | input_cmd_apply(new_config); | ||
27 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
28 | } | ||
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c new file mode 100644 index 00000000..f44c0ec7 --- /dev/null +++ b/sway/commands/input/events.c | |||
@@ -0,0 +1,35 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "log.h" | ||
6 | |||
7 | struct cmd_results *input_cmd_events(int argc, char **argv) { | ||
8 | sway_log(L_DEBUG, "events for device: %s", | ||
9 | current_input_config->identifier); | ||
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { | ||
12 | return error; | ||
13 | } | ||
14 | if (!current_input_config) { | ||
15 | return cmd_results_new(CMD_FAILURE, "events", | ||
16 | "No input device defined."); | ||
17 | } | ||
18 | struct input_config *new_config = | ||
19 | new_input_config(current_input_config->identifier); | ||
20 | |||
21 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
22 | new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; | ||
23 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
24 | new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; | ||
25 | } else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) { | ||
26 | new_config->send_events = | ||
27 | LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; | ||
28 | } else { | ||
29 | return cmd_results_new(CMD_INVALID, "events", | ||
30 | "Expected 'events <enabled|disabled|disabled_on_external_mouse>'"); | ||
31 | } | ||
32 | |||
33 | input_cmd_apply(new_config); | ||
34 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
35 | } | ||
diff --git a/sway/commands/input/left_handed.c b/sway/commands/input/left_handed.c new file mode 100644 index 00000000..dc8fcd56 --- /dev/null +++ b/sway/commands/input/left_handed.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_left_handed(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "left_handed", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, "left_handed", | ||
13 | "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
19 | new_config->left_handed = 1; | ||
20 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
21 | new_config->left_handed = 0; | ||
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, "left_handed", | ||
24 | "Expected 'left_handed <enabled|disabled>'"); | ||
25 | } | ||
26 | |||
27 | input_cmd_apply(new_config); | ||
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
29 | } | ||
diff --git a/sway/commands/input/middle_emulation.c b/sway/commands/input/middle_emulation.c new file mode 100644 index 00000000..e19964d8 --- /dev/null +++ b/sway/commands/input/middle_emulation.c | |||
@@ -0,0 +1,30 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, "middle_emulation", | ||
13 | "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
19 | new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED; | ||
20 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
21 | new_config->middle_emulation = | ||
22 | LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; | ||
23 | } else { | ||
24 | return cmd_results_new(CMD_INVALID, "middle_emulation", | ||
25 | "Expected 'middle_emulation <enabled|disabled>'"); | ||
26 | } | ||
27 | |||
28 | input_cmd_apply(new_config); | ||
29 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
30 | } | ||
diff --git a/sway/commands/input/natural_scroll.c b/sway/commands/input/natural_scroll.c new file mode 100644 index 00000000..8272c5b3 --- /dev/null +++ b/sway/commands/input/natural_scroll.c | |||
@@ -0,0 +1,29 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, "natural_scoll", | ||
13 | "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
19 | new_config->natural_scroll = 1; | ||
20 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
21 | new_config->natural_scroll = 0; | ||
22 | } else { | ||
23 | return cmd_results_new(CMD_INVALID, "natural_scroll", | ||
24 | "Expected 'natural_scroll <enabled|disabled>'"); | ||
25 | } | ||
26 | |||
27 | input_cmd_apply(new_config); | ||
28 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
29 | } | ||
diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c new file mode 100644 index 00000000..2c9db5bf --- /dev/null +++ b/sway/commands/input/pointer_accel.c | |||
@@ -0,0 +1,27 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, | ||
13 | "pointer_accel", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | float pointer_accel = atof(argv[0]); | ||
19 | if (pointer_accel < -1 || pointer_accel > 1) { | ||
20 | return cmd_results_new(CMD_INVALID, "pointer_accel", | ||
21 | "Input out of range [-1, 1]"); | ||
22 | } | ||
23 | new_config->pointer_accel = pointer_accel; | ||
24 | |||
25 | input_cmd_apply(new_config); | ||
26 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
27 | } | ||
diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c new file mode 100644 index 00000000..40277155 --- /dev/null +++ b/sway/commands/input/scroll_method.c | |||
@@ -0,0 +1,33 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_scroll_method(int argc, char **argv) { | ||
7 | struct cmd_results *error = NULL; | ||
8 | if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) { | ||
9 | return error; | ||
10 | } | ||
11 | if (!current_input_config) { | ||
12 | return cmd_results_new(CMD_FAILURE, "scroll_method", | ||
13 | "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | if (strcasecmp(argv[0], "none") == 0) { | ||
19 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; | ||
20 | } else if (strcasecmp(argv[0], "two_finger") == 0) { | ||
21 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; | ||
22 | } else if (strcasecmp(argv[0], "edge") == 0) { | ||
23 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE; | ||
24 | } else if (strcasecmp(argv[0], "on_button_down") == 0) { | ||
25 | new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; | ||
26 | } else { | ||
27 | return cmd_results_new(CMD_INVALID, "scroll_method", | ||
28 | "Expected 'scroll_method <none|two_finger|edge|on_button_down>'"); | ||
29 | } | ||
30 | |||
31 | input_cmd_apply(new_config); | ||
32 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
33 | } | ||
diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c new file mode 100644 index 00000000..18a54087 --- /dev/null +++ b/sway/commands/input/tap.c | |||
@@ -0,0 +1,32 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "log.h" | ||
6 | |||
7 | struct cmd_results *input_cmd_tap(int argc, char **argv) { | ||
8 | sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); | ||
9 | struct cmd_results *error = NULL; | ||
10 | if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) { | ||
11 | return error; | ||
12 | } | ||
13 | if (!current_input_config) { | ||
14 | return cmd_results_new(CMD_FAILURE, "tap", "No input device defined."); | ||
15 | } | ||
16 | struct input_config *new_config = | ||
17 | new_input_config(current_input_config->identifier); | ||
18 | |||
19 | if (strcasecmp(argv[0], "enabled") == 0) { | ||
20 | new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED; | ||
21 | } else if (strcasecmp(argv[0], "disabled") == 0) { | ||
22 | new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED; | ||
23 | } else { | ||
24 | return cmd_results_new(CMD_INVALID, "tap", | ||
25 | "Expected 'tap <enabled|disabled>'"); | ||
26 | } | ||
27 | |||
28 | sway_log(L_DEBUG, "apply-tap for device: %s", | ||
29 | current_input_config->identifier); | ||
30 | input_cmd_apply(new_config); | ||
31 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
32 | } | ||
diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c new file mode 100644 index 00000000..9a9ce044 --- /dev/null +++ b/sway/commands/input/xkb_layout.c | |||
@@ -0,0 +1,24 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/input/input-manager.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { | ||
7 | sway_log(L_DEBUG, "xkb layout for device: %s", current_input_config->identifier); | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_layout", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | if (!current_input_config) { | ||
13 | return cmd_results_new(CMD_FAILURE, "xkb_layout", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | new_config->xkb_layout = strdup(argv[0]); | ||
19 | |||
20 | sway_log(L_DEBUG, "apply-xkb_layout for device: %s", | ||
21 | current_input_config->identifier); | ||
22 | input_cmd_apply(new_config); | ||
23 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
24 | } | ||
diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c new file mode 100644 index 00000000..14a50ffb --- /dev/null +++ b/sway/commands/input/xkb_model.c | |||
@@ -0,0 +1,24 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/input/input-manager.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { | ||
7 | sway_log(L_DEBUG, "xkb model for device: %s", current_input_config->identifier); | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_model", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | if (!current_input_config) { | ||
13 | return cmd_results_new(CMD_FAILURE, "xkb_model", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | new_config->xkb_model = strdup(argv[0]); | ||
19 | |||
20 | sway_log(L_DEBUG, "apply-xkb_model for device: %s", | ||
21 | current_input_config->identifier); | ||
22 | input_cmd_apply(new_config); | ||
23 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
24 | } | ||
diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c new file mode 100644 index 00000000..67eb5342 --- /dev/null +++ b/sway/commands/input/xkb_options.c | |||
@@ -0,0 +1,24 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/input/input-manager.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { | ||
7 | sway_log(L_DEBUG, "xkb options for device: %s", current_input_config->identifier); | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_options", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | if (!current_input_config) { | ||
13 | return cmd_results_new(CMD_FAILURE, "xkb_options", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | new_config->xkb_options = strdup(argv[0]); | ||
19 | |||
20 | sway_log(L_DEBUG, "apply-xkb_options for device: %s", | ||
21 | current_input_config->identifier); | ||
22 | input_cmd_apply(new_config); | ||
23 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
24 | } | ||
diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c new file mode 100644 index 00000000..3eda0bdd --- /dev/null +++ b/sway/commands/input/xkb_rules.c | |||
@@ -0,0 +1,24 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/input/input-manager.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { | ||
7 | sway_log(L_DEBUG, "xkb rules for device: %s", current_input_config->identifier); | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_rules", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | if (!current_input_config) { | ||
13 | return cmd_results_new(CMD_FAILURE, "xkb_rules", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | new_config->xkb_rules = strdup(argv[0]); | ||
19 | |||
20 | sway_log(L_DEBUG, "apply-xkb_rules for device: %s", | ||
21 | current_input_config->identifier); | ||
22 | input_cmd_apply(new_config); | ||
23 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
24 | } | ||
diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c new file mode 100644 index 00000000..c7f93ad4 --- /dev/null +++ b/sway/commands/input/xkb_variant.c | |||
@@ -0,0 +1,24 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include "sway/commands.h" | ||
3 | #include "sway/input/input-manager.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { | ||
7 | sway_log(L_DEBUG, "xkb variant for device: %s", current_input_config->identifier); | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "xkb_variant", EXPECTED_AT_LEAST, 1))) { | ||
10 | return error; | ||
11 | } | ||
12 | if (!current_input_config) { | ||
13 | return cmd_results_new(CMD_FAILURE, "xkb_variant", "No input device defined."); | ||
14 | } | ||
15 | struct input_config *new_config = | ||
16 | new_input_config(current_input_config->identifier); | ||
17 | |||
18 | new_config->xkb_variant = strdup(argv[0]); | ||
19 | |||
20 | sway_log(L_DEBUG, "apply-xkb_variant for device: %s", | ||
21 | current_input_config->identifier); | ||
22 | input_cmd_apply(new_config); | ||
23 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
24 | } | ||
diff --git a/sway/commands/seat.c b/sway/commands/seat.c new file mode 100644 index 00000000..4f9e259b --- /dev/null +++ b/sway/commands/seat.c | |||
@@ -0,0 +1,35 @@ | |||
1 | #include <string.h> | ||
2 | #include <strings.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "log.h" | ||
6 | |||
7 | struct cmd_results *cmd_seat(int argc, char **argv) { | ||
8 | struct cmd_results *error = NULL; | ||
9 | if ((error = checkarg(argc, "seat", EXPECTED_AT_LEAST, 2))) { | ||
10 | return error; | ||
11 | } | ||
12 | |||
13 | if (config->reading && strcmp("{", argv[1]) == 0) { | ||
14 | current_seat_config = new_seat_config(argv[0]); | ||
15 | sway_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); | ||
16 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); | ||
17 | } | ||
18 | |||
19 | if (argc > 2) { | ||
20 | int argc_new = argc-2; | ||
21 | char **argv_new = argv+2; | ||
22 | |||
23 | struct cmd_results *res; | ||
24 | current_seat_config = new_seat_config(argv[0]); | ||
25 | if (strcasecmp("attach", argv[1]) == 0) { | ||
26 | res = seat_cmd_attach(argc_new, argv_new); | ||
27 | } else { | ||
28 | res = cmd_results_new(CMD_INVALID, "seat <name>", "Unknown command %s", argv[1]); | ||
29 | } | ||
30 | current_seat_config = NULL; | ||
31 | return res; | ||
32 | } | ||
33 | |||
34 | return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); | ||
35 | } | ||
diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c new file mode 100644 index 00000000..996c1bda --- /dev/null +++ b/sway/commands/seat/attach.c | |||
@@ -0,0 +1,26 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <string.h> | ||
3 | #include <strings.h> | ||
4 | #include "sway/input/input-manager.h" | ||
5 | #include "sway/commands.h" | ||
6 | #include "sway/config.h" | ||
7 | #include "log.h" | ||
8 | #include "stringop.h" | ||
9 | |||
10 | struct cmd_results *seat_cmd_attach(int argc, char **argv) { | ||
11 | struct cmd_results *error = NULL; | ||
12 | if ((error = checkarg(argc, "attach", EXPECTED_AT_LEAST, 1))) { | ||
13 | return error; | ||
14 | } | ||
15 | if (!current_seat_config) { | ||
16 | return cmd_results_new(CMD_FAILURE, "attach", "No seat defined"); | ||
17 | } | ||
18 | |||
19 | struct seat_config *new_config = new_seat_config(current_seat_config->name); | ||
20 | struct seat_attachment_config *new_attachment = seat_attachment_config_new(); | ||
21 | new_attachment->identifier = strdup(argv[0]); | ||
22 | list_add(new_config->attachments, new_attachment); | ||
23 | |||
24 | seat_cmd_apply(new_config); | ||
25 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
26 | } | ||
diff --git a/sway/config.c b/sway/config.c index 61131845..4e34aa8c 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <dev/evdev/input-event-codes.h> | 21 | #include <dev/evdev/input-event-codes.h> |
22 | #endif | 22 | #endif |
23 | #include <wlr/types/wlr_output.h> | 23 | #include <wlr/types/wlr_output.h> |
24 | #include "sway/input/input-manager.h" | ||
24 | #include "sway/commands.h" | 25 | #include "sway/commands.h" |
25 | #include "sway/config.h" | 26 | #include "sway/config.h" |
26 | #include "sway/layout.h" | 27 | #include "sway/layout.h" |
@@ -44,11 +45,13 @@ static void config_defaults(struct sway_config *config) { | |||
44 | if (!(config->criteria = create_list())) goto cleanup; | 45 | if (!(config->criteria = create_list())) goto cleanup; |
45 | if (!(config->no_focus = create_list())) goto cleanup; | 46 | if (!(config->no_focus = create_list())) goto cleanup; |
46 | if (!(config->input_configs = create_list())) goto cleanup; | 47 | if (!(config->input_configs = create_list())) goto cleanup; |
48 | if (!(config->seat_configs = create_list())) goto cleanup; | ||
47 | if (!(config->output_configs = create_list())) goto cleanup; | 49 | if (!(config->output_configs = create_list())) goto cleanup; |
48 | 50 | ||
49 | if (!(config->cmd_queue = create_list())) goto cleanup; | 51 | if (!(config->cmd_queue = create_list())) goto cleanup; |
50 | 52 | ||
51 | if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) goto cleanup; | 53 | if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) |
54 | goto cleanup; | ||
52 | if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; | 55 | if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; |
53 | strcpy(config->current_mode->name, "default"); | 56 | strcpy(config->current_mode->name, "default"); |
54 | if (!(config->current_mode->bindings = create_list())) goto cleanup; | 57 | if (!(config->current_mode->bindings = create_list())) goto cleanup; |
@@ -226,6 +229,227 @@ static int qstrcmp(const void* a, const void* b) { | |||
226 | return strcmp(*((char**) a), *((char**) b)); | 229 | return strcmp(*((char**) a), *((char**) b)); |
227 | } | 230 | } |
228 | 231 | ||
232 | struct input_config *new_input_config(const char* identifier) { | ||
233 | struct input_config *input = calloc(1, sizeof(struct input_config)); | ||
234 | if (!input) { | ||
235 | sway_log(L_DEBUG, "Unable to allocate input config"); | ||
236 | return NULL; | ||
237 | } | ||
238 | sway_log(L_DEBUG, "new_input_config(%s)", identifier); | ||
239 | if (!(input->identifier = strdup(identifier))) { | ||
240 | free(input); | ||
241 | sway_log(L_DEBUG, "Unable to allocate input config"); | ||
242 | return NULL; | ||
243 | } | ||
244 | |||
245 | input->tap = INT_MIN; | ||
246 | input->drag_lock = INT_MIN; | ||
247 | input->dwt = INT_MIN; | ||
248 | input->send_events = INT_MIN; | ||
249 | input->click_method = INT_MIN; | ||
250 | input->middle_emulation = INT_MIN; | ||
251 | input->natural_scroll = INT_MIN; | ||
252 | input->accel_profile = INT_MIN; | ||
253 | input->pointer_accel = FLT_MIN; | ||
254 | input->scroll_method = INT_MIN; | ||
255 | input->left_handed = INT_MIN; | ||
256 | |||
257 | return input; | ||
258 | } | ||
259 | |||
260 | void merge_input_config(struct input_config *dst, struct input_config *src) { | ||
261 | if (src->identifier) { | ||
262 | free(dst->identifier); | ||
263 | dst->identifier = strdup(src->identifier); | ||
264 | } | ||
265 | if (src->accel_profile != INT_MIN) { | ||
266 | dst->accel_profile = src->accel_profile; | ||
267 | } | ||
268 | if (src->click_method != INT_MIN) { | ||
269 | dst->click_method = src->click_method; | ||
270 | } | ||
271 | if (src->drag_lock != INT_MIN) { | ||
272 | dst->drag_lock = src->drag_lock; | ||
273 | } | ||
274 | if (src->dwt != INT_MIN) { | ||
275 | dst->dwt = src->dwt; | ||
276 | } | ||
277 | if (src->middle_emulation != INT_MIN) { | ||
278 | dst->middle_emulation = src->middle_emulation; | ||
279 | } | ||
280 | if (src->natural_scroll != INT_MIN) { | ||
281 | dst->natural_scroll = src->natural_scroll; | ||
282 | } | ||
283 | if (src->pointer_accel != FLT_MIN) { | ||
284 | dst->pointer_accel = src->pointer_accel; | ||
285 | } | ||
286 | if (src->scroll_method != INT_MIN) { | ||
287 | dst->scroll_method = src->scroll_method; | ||
288 | } | ||
289 | if (src->send_events != INT_MIN) { | ||
290 | dst->send_events = src->send_events; | ||
291 | } | ||
292 | if (src->tap != INT_MIN) { | ||
293 | dst->tap = src->tap; | ||
294 | } | ||
295 | if (src->xkb_layout) { | ||
296 | free(dst->xkb_layout); | ||
297 | dst->xkb_layout = strdup(src->xkb_layout); | ||
298 | } | ||
299 | if (src->xkb_model) { | ||
300 | free(dst->xkb_model); | ||
301 | dst->xkb_model = strdup(src->xkb_model); | ||
302 | } | ||
303 | if (src->xkb_options) { | ||
304 | free(dst->xkb_options); | ||
305 | dst->xkb_options = strdup(src->xkb_options); | ||
306 | } | ||
307 | if (src->xkb_rules) { | ||
308 | free(dst->xkb_rules); | ||
309 | dst->xkb_rules = strdup(src->xkb_rules); | ||
310 | } | ||
311 | if (src->xkb_variant) { | ||
312 | free(dst->xkb_variant); | ||
313 | dst->xkb_variant = strdup(src->xkb_variant); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | void free_input_config(struct input_config *ic) { | ||
318 | if (!ic) { | ||
319 | return; | ||
320 | } | ||
321 | free(ic->identifier); | ||
322 | free(ic); | ||
323 | } | ||
324 | |||
325 | int input_identifier_cmp(const void *item, const void *data) { | ||
326 | const struct input_config *ic = item; | ||
327 | const char *identifier = data; | ||
328 | return strcmp(ic->identifier, identifier); | ||
329 | } | ||
330 | |||
331 | struct seat_config *new_seat_config(const char* name) { | ||
332 | struct seat_config *seat = calloc(1, sizeof(struct seat_config)); | ||
333 | if (!seat) { | ||
334 | sway_log(L_DEBUG, "Unable to allocate seat config"); | ||
335 | return NULL; | ||
336 | } | ||
337 | |||
338 | sway_log(L_DEBUG, "new_seat_config(%s)", name); | ||
339 | seat->name = strdup(name); | ||
340 | if (!sway_assert(seat->name, "could not allocate name for seat")) { | ||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | seat->attachments = create_list(); | ||
345 | if (!sway_assert(seat->attachments, | ||
346 | "could not allocate seat attachments list")) { | ||
347 | return NULL; | ||
348 | } | ||
349 | |||
350 | return seat; | ||
351 | } | ||
352 | |||
353 | struct seat_attachment_config *seat_attachment_config_new() { | ||
354 | struct seat_attachment_config *attachment = | ||
355 | calloc(1, sizeof(struct seat_attachment_config)); | ||
356 | if (!attachment) { | ||
357 | sway_log(L_DEBUG, "cannot allocate attachment config"); | ||
358 | return NULL; | ||
359 | } | ||
360 | return attachment; | ||
361 | } | ||
362 | |||
363 | static void seat_attachment_config_free( | ||
364 | struct seat_attachment_config *attachment) { | ||
365 | free(attachment->identifier); | ||
366 | free(attachment); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | static struct seat_attachment_config *seat_attachment_config_copy( | ||
371 | struct seat_attachment_config *attachment) { | ||
372 | struct seat_attachment_config *copy = seat_attachment_config_new(); | ||
373 | if (!copy) { | ||
374 | return NULL; | ||
375 | } | ||
376 | |||
377 | copy->identifier = strdup(attachment->identifier); | ||
378 | |||
379 | return copy; | ||
380 | } | ||
381 | |||
382 | static void merge_seat_attachment_config(struct seat_attachment_config *dest, | ||
383 | struct seat_attachment_config *source) { | ||
384 | // nothing to merge yet, but there will be some day | ||
385 | } | ||
386 | |||
387 | void merge_seat_config(struct seat_config *dest, struct seat_config *source) { | ||
388 | if (source->name) { | ||
389 | free(dest->name); | ||
390 | dest->name = strdup(source->name); | ||
391 | } | ||
392 | |||
393 | for (int i = 0; i < source->attachments->length; ++i) { | ||
394 | struct seat_attachment_config *source_attachment = | ||
395 | source->attachments->items[i]; | ||
396 | bool found = false; | ||
397 | for (int j = 0; j < dest->attachments->length; ++j) { | ||
398 | struct seat_attachment_config *dest_attachment = | ||
399 | dest->attachments->items[j]; | ||
400 | if (strcmp(source_attachment->identifier, | ||
401 | dest_attachment->identifier) == 0) { | ||
402 | merge_seat_attachment_config(dest_attachment, | ||
403 | source_attachment); | ||
404 | found = true; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | if (!found) { | ||
409 | struct seat_attachment_config *copy = | ||
410 | seat_attachment_config_copy(source_attachment); | ||
411 | if (copy) { | ||
412 | list_add(dest->attachments, copy); | ||
413 | } | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 | |||
418 | void free_seat_config(struct seat_config *seat) { | ||
419 | if (!seat) { | ||
420 | return; | ||
421 | } | ||
422 | |||
423 | free(seat->name); | ||
424 | for (int i = 0; i < seat->attachments->length; ++i) { | ||
425 | struct seat_attachment_config *attachment = | ||
426 | seat->attachments->items[i]; | ||
427 | seat_attachment_config_free(attachment); | ||
428 | } | ||
429 | |||
430 | list_free(seat->attachments); | ||
431 | free(seat); | ||
432 | } | ||
433 | |||
434 | int seat_name_cmp(const void *item, const void *data) { | ||
435 | const struct seat_config *sc = item; | ||
436 | const char *name = data; | ||
437 | return strcmp(sc->name, name); | ||
438 | } | ||
439 | |||
440 | struct seat_attachment_config *seat_config_get_attachment( | ||
441 | struct seat_config *seat_config, char *identifier) { | ||
442 | for (int i = 0; i < seat_config->attachments->length; ++i) { | ||
443 | struct seat_attachment_config *attachment = | ||
444 | seat_config->attachments->items[i]; | ||
445 | if (strcmp(attachment->identifier, identifier) == 0) { | ||
446 | return attachment; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | return NULL; | ||
451 | } | ||
452 | |||
229 | bool load_main_config(const char *file, bool is_active) { | 453 | bool load_main_config(const char *file, bool is_active) { |
230 | char *path; | 454 | char *path; |
231 | if (file != NULL) { | 455 | if (file != NULL) { |
@@ -256,8 +480,9 @@ bool load_main_config(const char *file, bool is_active) { | |||
256 | bool success = true; | 480 | bool success = true; |
257 | DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); | 481 | DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); |
258 | if (!dir) { | 482 | if (!dir) { |
259 | sway_log(L_ERROR, "%s does not exist, sway will have no security configuration" | 483 | sway_log(L_ERROR, |
260 | " and will probably be broken", SYSCONFDIR "/sway/security.d"); | 484 | "%s does not exist, sway will have no security configuration" |
485 | " and will probably be broken", SYSCONFDIR "/sway/security.d"); | ||
261 | } else { | 486 | } else { |
262 | list_t *secconfigs = create_list(); | 487 | list_t *secconfigs = create_list(); |
263 | char *base = SYSCONFDIR "/sway/security.d/"; | 488 | char *base = SYSCONFDIR "/sway/security.d/"; |
@@ -281,8 +506,12 @@ bool load_main_config(const char *file, bool is_active) { | |||
281 | list_qsort(secconfigs, qstrcmp); | 506 | list_qsort(secconfigs, qstrcmp); |
282 | for (int i = 0; i < secconfigs->length; ++i) { | 507 | for (int i = 0; i < secconfigs->length; ++i) { |
283 | char *_path = secconfigs->items[i]; | 508 | char *_path = secconfigs->items[i]; |
284 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { | 509 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || |
285 | sway_log(L_ERROR, "Refusing to load %s - it must be owned by root and mode 644 or 444", _path); | 510 | (((s.st_mode & 0777) != 0644) && |
511 | (s.st_mode & 0777) != 0444)) { | ||
512 | sway_log(L_ERROR, | ||
513 | "Refusing to load %s - it must be owned by root " | ||
514 | "and mode 644 or 444", _path); | ||
286 | success = false; | 515 | success = false; |
287 | } else { | 516 | } else { |
288 | success = success && load_config(_path, config); | 517 | success = success && load_config(_path, config); |
@@ -311,7 +540,8 @@ bool load_main_config(const char *file, bool is_active) { | |||
311 | return success; | 540 | return success; |
312 | } | 541 | } |
313 | 542 | ||
314 | static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { | 543 | static bool load_include_config(const char *path, const char *parent_dir, |
544 | struct sway_config *config) { | ||
315 | // save parent config | 545 | // save parent config |
316 | const char *parent_config = config->current_config; | 546 | const char *parent_config = config->current_config; |
317 | 547 | ||
@@ -321,7 +551,8 @@ static bool load_include_config(const char *path, const char *parent_dir, struct | |||
321 | len = len + strlen(parent_dir) + 2; | 551 | len = len + strlen(parent_dir) + 2; |
322 | full_path = malloc(len * sizeof(char)); | 552 | full_path = malloc(len * sizeof(char)); |
323 | if (!full_path) { | 553 | if (!full_path) { |
324 | sway_log(L_ERROR, "Unable to allocate full path to included config"); | 554 | sway_log(L_ERROR, |
555 | "Unable to allocate full path to included config"); | ||
325 | return false; | 556 | return false; |
326 | } | 557 | } |
327 | snprintf(full_path, len, "%s/%s", parent_dir, path); | 558 | snprintf(full_path, len, "%s/%s", parent_dir, path); |
@@ -340,7 +571,9 @@ static bool load_include_config(const char *path, const char *parent_dir, struct | |||
340 | for (j = 0; j < config->config_chain->length; ++j) { | 571 | for (j = 0; j < config->config_chain->length; ++j) { |
341 | char *old_path = config->config_chain->items[j]; | 572 | char *old_path = config->config_chain->items[j]; |
342 | if (strcmp(real_path, old_path) == 0) { | 573 | if (strcmp(real_path, old_path) == 0) { |
343 | sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); | 574 | sway_log(L_DEBUG, |
575 | "%s already included once, won't be included again.", | ||
576 | real_path); | ||
344 | free(real_path); | 577 | free(real_path); |
345 | return false; | 578 | return false; |
346 | } | 579 | } |
@@ -400,6 +633,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { | |||
400 | return true; | 633 | return true; |
401 | } | 634 | } |
402 | 635 | ||
636 | |||
403 | bool read_config(FILE *file, struct sway_config *config) { | 637 | bool read_config(FILE *file, struct sway_config *config) { |
404 | bool success = true; | 638 | bool success = true; |
405 | enum cmd_status block = CMD_BLOCK_END; | 639 | enum cmd_status block = CMD_BLOCK_END; |
@@ -427,8 +661,8 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
427 | switch(res->status) { | 661 | switch(res->status) { |
428 | case CMD_FAILURE: | 662 | case CMD_FAILURE: |
429 | case CMD_INVALID: | 663 | case CMD_INVALID: |
430 | sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, | 664 | sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, |
431 | res->error, config->current_config); | 665 | line, res->error, config->current_config); |
432 | success = false; | 666 | success = false; |
433 | break; | 667 | break; |
434 | 668 | ||
@@ -453,6 +687,14 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
453 | } | 687 | } |
454 | break; | 688 | break; |
455 | 689 | ||
690 | case CMD_BLOCK_SEAT: | ||
691 | if (block == CMD_BLOCK_END) { | ||
692 | block = CMD_BLOCK_SEAT; | ||
693 | } else { | ||
694 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
695 | } | ||
696 | break; | ||
697 | |||
456 | case CMD_BLOCK_BAR: | 698 | case CMD_BLOCK_BAR: |
457 | if (block == CMD_BLOCK_END) { | 699 | if (block == CMD_BLOCK_END) { |
458 | block = CMD_BLOCK_BAR; | 700 | block = CMD_BLOCK_BAR; |
@@ -503,8 +745,13 @@ bool read_config(FILE *file, struct sway_config *config) { | |||
503 | 745 | ||
504 | case CMD_BLOCK_INPUT: | 746 | case CMD_BLOCK_INPUT: |
505 | sway_log(L_DEBUG, "End of input block"); | 747 | sway_log(L_DEBUG, "End of input block"); |
506 | // TODO: input | 748 | current_input_config = NULL; |
507 | //current_input_config = NULL; | 749 | block = CMD_BLOCK_END; |
750 | break; | ||
751 | |||
752 | case CMD_BLOCK_SEAT: | ||
753 | sway_log(L_DEBUG, "End of seat block"); | ||
754 | current_seat_config = NULL; | ||
508 | block = CMD_BLOCK_END; | 755 | block = CMD_BLOCK_END; |
509 | break; | 756 | break; |
510 | 757 | ||
@@ -569,7 +816,8 @@ char *do_var_replacement(char *str) { | |||
569 | char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); | 816 | char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); |
570 | if (!newstr) { | 817 | if (!newstr) { |
571 | sway_log(L_ERROR, | 818 | sway_log(L_ERROR, |
572 | "Unable to allocate replacement during variable expansion"); | 819 | "Unable to allocate replacement " |
820 | "during variable expansion"); | ||
573 | break; | 821 | break; |
574 | } | 822 | } |
575 | char *newptr = newstr; | 823 | char *newptr = newstr; |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index ad843b31..3b87c2e7 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include "sway/output.h" | 12 | #include "sway/output.h" |
13 | #include "sway/server.h" | 13 | #include "sway/server.h" |
14 | #include "sway/view.h" | 14 | #include "sway/view.h" |
15 | #include "sway/input/input-manager.h" | ||
16 | #include "sway/input/seat.h" | ||
15 | 17 | ||
16 | static void output_frame_view(swayc_t *view, void *data) { | 18 | static void output_frame_view(swayc_t *view, void *data) { |
17 | struct sway_output *output = data; | 19 | struct sway_output *output = data; |
@@ -23,8 +25,8 @@ static void output_frame_view(swayc_t *view, void *data) { | |||
23 | } | 25 | } |
24 | // TODO | 26 | // TODO |
25 | // - Deal with wlr_output_layout | 27 | // - Deal with wlr_output_layout |
26 | int width = sway_view->width; | 28 | int width = sway_view->surface->current->width; |
27 | int height = sway_view->height; | 29 | int height = sway_view->surface->current->height; |
28 | int render_width = width * wlr_output->scale; | 30 | int render_width = width * wlr_output->scale; |
29 | int render_height = height * wlr_output->scale; | 31 | int render_height = height * wlr_output->scale; |
30 | double ox = view->x, oy = view->y; | 32 | double ox = view->x, oy = view->y; |
@@ -38,19 +40,33 @@ static void output_frame_view(swayc_t *view, void *data) { | |||
38 | // return; | 40 | // return; |
39 | //} | 41 | //} |
40 | 42 | ||
43 | // if the shell specifies window geometry, make the top left corner of the | ||
44 | // window in the top left corner of the container to avoid arbitrarily | ||
45 | // sized gaps based on the attached buffer size | ||
46 | int window_offset_x = 0; | ||
47 | int window_offset_y = 0; | ||
48 | |||
49 | if (view->sway_view->type == SWAY_XDG_SHELL_V6_VIEW) { | ||
50 | window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry->x; | ||
51 | window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry->y; | ||
52 | } | ||
53 | |||
41 | // TODO | 54 | // TODO |
42 | double rotation = 0; | 55 | double rotation = 0; |
43 | float matrix[16]; | 56 | float matrix[16]; |
44 | 57 | ||
45 | float translate_origin[16]; | 58 | float translate_origin[16]; |
46 | wlr_matrix_translate(&translate_origin, | 59 | wlr_matrix_translate(&translate_origin, |
47 | (int)ox + render_width / 2, (int)oy + render_height / 2, 0); | 60 | (int)ox + render_width / 2 - window_offset_x, |
61 | (int)oy + render_height / 2 - window_offset_y, | ||
62 | 0); | ||
48 | 63 | ||
49 | float rotate[16]; | 64 | float rotate[16]; |
50 | wlr_matrix_rotate(&rotate, rotation); | 65 | wlr_matrix_rotate(&rotate, rotation); |
51 | 66 | ||
52 | float translate_center[16]; | 67 | float translate_center[16]; |
53 | wlr_matrix_translate(&translate_center, -render_width / 2, | 68 | wlr_matrix_translate(&translate_center, |
69 | -render_width / 2, | ||
54 | -render_height / 2, 0); | 70 | -render_height / 2, 0); |
55 | 71 | ||
56 | float scale[16]; | 72 | float scale[16]; |
@@ -115,6 +131,8 @@ void output_add_notify(struct wl_listener *listener, void *data) { | |||
115 | return; | 131 | return; |
116 | } | 132 | } |
117 | 133 | ||
134 | sway_input_manager_configure_xcursor(input_manager); | ||
135 | |||
118 | output->frame.notify = output_frame_notify; | 136 | output->frame.notify = output_frame_notify; |
119 | wl_signal_add(&wlr_output->events.frame, &output->frame); | 137 | wl_signal_add(&wlr_output->events.frame, &output->frame); |
120 | } | 138 | } |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 3f5a358a..df81d5be 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include "sway/layout.h" | 7 | #include "sway/layout.h" |
8 | #include "sway/server.h" | 8 | #include "sway/server.h" |
9 | #include "sway/view.h" | 9 | #include "sway/view.h" |
10 | #include "sway/input/seat.h" | ||
11 | #include "sway/input/input-manager.h" | ||
10 | #include "log.h" | 12 | #include "log.h" |
11 | 13 | ||
12 | static bool assert_wl_shell(struct sway_view *view) { | 14 | static bool assert_wl_shell(struct sway_view *view) { |
@@ -126,4 +128,6 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
126 | sway_view->swayc = cont; | 128 | sway_view->swayc = cont; |
127 | 129 | ||
128 | arrange_windows(cont->parent, -1, -1); | 130 | arrange_windows(cont->parent, -1, -1); |
131 | |||
132 | sway_input_manager_set_focus(input_manager, cont); | ||
129 | } | 133 | } |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 2435c256..82775e2f 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include "sway/layout.h" | 7 | #include "sway/layout.h" |
8 | #include "sway/server.h" | 8 | #include "sway/server.h" |
9 | #include "sway/view.h" | 9 | #include "sway/view.h" |
10 | #include "sway/input/seat.h" | ||
11 | #include "sway/input/input-manager.h" | ||
10 | #include "log.h" | 12 | #include "log.h" |
11 | 13 | ||
12 | static bool assert_xdg(struct sway_view *view) { | 14 | static bool assert_xdg(struct sway_view *view) { |
@@ -132,4 +134,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
132 | sway_view->swayc = cont; | 134 | sway_view->swayc = cont; |
133 | 135 | ||
134 | arrange_windows(cont->parent, -1, -1); | 136 | arrange_windows(cont->parent, -1, -1); |
137 | |||
138 | sway_input_manager_set_focus(input_manager, cont); | ||
135 | } | 139 | } |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index e3799d2d..29bed955 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include "sway/server.h" | 10 | #include "sway/server.h" |
11 | #include "sway/view.h" | 11 | #include "sway/view.h" |
12 | #include "sway/output.h" | 12 | #include "sway/output.h" |
13 | #include "sway/input/seat.h" | ||
14 | #include "sway/input/input-manager.h" | ||
13 | #include "log.h" | 15 | #include "log.h" |
14 | 16 | ||
15 | static bool assert_xwayland(struct sway_view *view) { | 17 | static bool assert_xwayland(struct sway_view *view) { |
@@ -171,4 +173,5 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
171 | sway_view->swayc = cont; | 173 | sway_view->swayc = cont; |
172 | 174 | ||
173 | arrange_windows(cont->parent, -1, -1); | 175 | arrange_windows(cont->parent, -1, -1); |
176 | sway_input_manager_set_focus(input_manager, cont); | ||
174 | } | 177 | } |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c new file mode 100644 index 00000000..24d4642d --- /dev/null +++ b/sway/input/cursor.c | |||
@@ -0,0 +1,184 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #ifdef __linux__ | ||
3 | #include <linux/input-event-codes.h> | ||
4 | #elif __FreeBSD__ | ||
5 | #include <dev/evdev/input-event-codes.h> | ||
6 | #endif | ||
7 | #include <wlr/types/wlr_cursor.h> | ||
8 | #include <wlr/types/wlr_xcursor_manager.h> | ||
9 | #include "sway/input/cursor.h" | ||
10 | #include "sway/view.h" | ||
11 | #include "list.h" | ||
12 | #include "log.h" | ||
13 | |||
14 | static void cursor_update_position(struct sway_cursor *cursor) { | ||
15 | double x = cursor->cursor->x; | ||
16 | double y = cursor->cursor->y; | ||
17 | |||
18 | wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, | ||
19 | "left_ptr", cursor->cursor); | ||
20 | |||
21 | cursor->x = x; | ||
22 | cursor->y = y; | ||
23 | } | ||
24 | |||
25 | static void cursor_send_pointer_motion(struct sway_cursor *cursor, | ||
26 | uint32_t time) { | ||
27 | struct wlr_seat *seat = cursor->seat->wlr_seat; | ||
28 | struct wlr_surface *surface = NULL; | ||
29 | double sx, sy; | ||
30 | swayc_t *swayc = | ||
31 | swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); | ||
32 | if (swayc) { | ||
33 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | ||
34 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | ||
35 | } else { | ||
36 | wlr_seat_pointer_clear_focus(seat); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { | ||
41 | struct sway_cursor *cursor = | ||
42 | wl_container_of(listener, cursor, motion); | ||
43 | struct wlr_event_pointer_motion *event = data; | ||
44 | wlr_cursor_move(cursor->cursor, event->device, | ||
45 | event->delta_x, event->delta_y); | ||
46 | cursor_update_position(cursor); | ||
47 | cursor_send_pointer_motion(cursor, event->time_msec); | ||
48 | } | ||
49 | |||
50 | static void handle_cursor_motion_absolute(struct wl_listener *listener, | ||
51 | void *data) { | ||
52 | struct sway_cursor *cursor = | ||
53 | wl_container_of(listener, cursor, motion_absolute); | ||
54 | struct wlr_event_pointer_motion_absolute *event = data; | ||
55 | wlr_cursor_warp_absolute(cursor->cursor, event->device, | ||
56 | event->x_mm / event->width_mm, event->y_mm / event->height_mm); | ||
57 | cursor_update_position(cursor); | ||
58 | cursor_send_pointer_motion(cursor, event->time_msec); | ||
59 | } | ||
60 | |||
61 | static void handle_cursor_button(struct wl_listener *listener, void *data) { | ||
62 | struct sway_cursor *cursor = | ||
63 | wl_container_of(listener, cursor, button); | ||
64 | struct wlr_event_pointer_button *event = data; | ||
65 | |||
66 | if (event->button == BTN_LEFT) { | ||
67 | struct wlr_surface *surface = NULL; | ||
68 | double sx, sy; | ||
69 | swayc_t *swayc = | ||
70 | swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); | ||
71 | |||
72 | sway_seat_set_focus(cursor->seat, swayc); | ||
73 | } | ||
74 | |||
75 | wlr_seat_pointer_notify_button(cursor->seat->wlr_seat, event->time_msec, | ||
76 | event->button, event->state); | ||
77 | } | ||
78 | |||
79 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { | ||
80 | struct sway_cursor *cursor = | ||
81 | wl_container_of(listener, cursor, axis); | ||
82 | struct wlr_event_pointer_axis *event = data; | ||
83 | wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, | ||
84 | event->orientation, event->delta); | ||
85 | } | ||
86 | |||
87 | static void handle_touch_down(struct wl_listener *listener, void *data) { | ||
88 | struct sway_cursor *cursor = | ||
89 | wl_container_of(listener, cursor, touch_down); | ||
90 | struct wlr_event_touch_down *event = data; | ||
91 | sway_log(L_DEBUG, "TODO: handle touch down event: %p", event); | ||
92 | } | ||
93 | |||
94 | static void handle_touch_up(struct wl_listener *listener, void *data) { | ||
95 | struct sway_cursor *cursor = | ||
96 | wl_container_of(listener, cursor, touch_up); | ||
97 | struct wlr_event_touch_up *event = data; | ||
98 | sway_log(L_DEBUG, "TODO: handle touch up event: %p", event); | ||
99 | } | ||
100 | |||
101 | static void handle_touch_motion(struct wl_listener *listener, void *data) { | ||
102 | struct sway_cursor *cursor = | ||
103 | wl_container_of(listener, cursor, touch_motion); | ||
104 | struct wlr_event_touch_motion *event = data; | ||
105 | sway_log(L_DEBUG, "TODO: handle touch motion event: %p", event); | ||
106 | } | ||
107 | |||
108 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | ||
109 | struct sway_cursor *cursor = | ||
110 | wl_container_of(listener, cursor, tool_axis); | ||
111 | struct wlr_event_tablet_tool_axis *event = data; | ||
112 | sway_log(L_DEBUG, "TODO: handle tool axis event: %p", event); | ||
113 | } | ||
114 | |||
115 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | ||
116 | struct sway_cursor *cursor = | ||
117 | wl_container_of(listener, cursor, tool_tip); | ||
118 | struct wlr_event_tablet_tool_tip *event = data; | ||
119 | sway_log(L_DEBUG, "TODO: handle tool tip event: %p", event); | ||
120 | } | ||
121 | |||
122 | static void handle_request_set_cursor(struct wl_listener *listener, | ||
123 | void *data) { | ||
124 | struct sway_cursor *cursor = | ||
125 | wl_container_of(listener, cursor, request_set_cursor); | ||
126 | struct wlr_seat_pointer_request_set_cursor_event *event = data; | ||
127 | sway_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); | ||
128 | } | ||
129 | |||
130 | struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | ||
131 | struct sway_cursor *cursor = calloc(1, sizeof(struct sway_cursor)); | ||
132 | if (!sway_assert(cursor, "could not allocate sway cursor")) { | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
136 | struct wlr_cursor *wlr_cursor = wlr_cursor_create(); | ||
137 | if (!sway_assert(wlr_cursor, "could not allocate wlr cursor")) { | ||
138 | free(cursor); | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | cursor->seat = seat; | ||
143 | wlr_cursor_attach_output_layout(wlr_cursor, | ||
144 | root_container.sway_root->output_layout); | ||
145 | |||
146 | // input events | ||
147 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); | ||
148 | cursor->motion.notify = handle_cursor_motion; | ||
149 | |||
150 | wl_signal_add(&wlr_cursor->events.motion_absolute, | ||
151 | &cursor->motion_absolute); | ||
152 | cursor->motion_absolute.notify = handle_cursor_motion_absolute; | ||
153 | |||
154 | wl_signal_add(&wlr_cursor->events.button, &cursor->button); | ||
155 | cursor->button.notify = handle_cursor_button; | ||
156 | |||
157 | wl_signal_add(&wlr_cursor->events.axis, &cursor->axis); | ||
158 | cursor->axis.notify = handle_cursor_axis; | ||
159 | |||
160 | wl_signal_add(&wlr_cursor->events.touch_down, &cursor->touch_down); | ||
161 | cursor->touch_down.notify = handle_touch_down; | ||
162 | |||
163 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); | ||
164 | cursor->touch_up.notify = handle_touch_up; | ||
165 | |||
166 | wl_signal_add(&wlr_cursor->events.touch_motion, | ||
167 | &cursor->touch_motion); | ||
168 | cursor->touch_motion.notify = handle_touch_motion; | ||
169 | |||
170 | wl_signal_add(&wlr_cursor->events.tablet_tool_axis, | ||
171 | &cursor->tool_axis); | ||
172 | cursor->tool_axis.notify = handle_tool_axis; | ||
173 | |||
174 | wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &cursor->tool_tip); | ||
175 | cursor->tool_tip.notify = handle_tool_tip; | ||
176 | |||
177 | wl_signal_add(&seat->wlr_seat->events.request_set_cursor, | ||
178 | &cursor->request_set_cursor); | ||
179 | cursor->request_set_cursor.notify = handle_request_set_cursor; | ||
180 | |||
181 | cursor->cursor = wlr_cursor; | ||
182 | |||
183 | return cursor; | ||
184 | } | ||
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c new file mode 100644 index 00000000..1950b6d9 --- /dev/null +++ b/sway/input/input-manager.c | |||
@@ -0,0 +1,266 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <ctype.h> | ||
3 | #include <float.h> | ||
4 | #include <limits.h> | ||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | #include <libinput.h> | ||
8 | #include "sway/config.h" | ||
9 | #include "sway/input/input-manager.h" | ||
10 | #include "sway/input/seat.h" | ||
11 | #include "sway/server.h" | ||
12 | #include "list.h" | ||
13 | #include "log.h" | ||
14 | |||
15 | static const char *default_seat = "seat0"; | ||
16 | |||
17 | // TODO make me not global | ||
18 | struct sway_input_manager *input_manager; | ||
19 | |||
20 | struct input_config *current_input_config = NULL; | ||
21 | struct seat_config *current_seat_config = NULL; | ||
22 | |||
23 | static struct sway_seat *input_manager_get_seat( | ||
24 | struct sway_input_manager *input, const char *seat_name) { | ||
25 | struct sway_seat *seat = NULL; | ||
26 | wl_list_for_each(seat, &input->seats, link) { | ||
27 | if (strcmp(seat->wlr_seat->name, seat_name) == 0) { | ||
28 | return seat; | ||
29 | } | ||
30 | } | ||
31 | |||
32 | return sway_seat_create(input, seat_name); | ||
33 | } | ||
34 | |||
35 | static char *get_device_identifier(struct wlr_input_device *device) { | ||
36 | int vendor = device->vendor; | ||
37 | int product = device->product; | ||
38 | char *name = strdup(device->name); | ||
39 | |||
40 | char *p = name; | ||
41 | for (; *p; ++p) { | ||
42 | if (*p == ' ') { | ||
43 | *p = '_'; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | sway_log(L_DEBUG, "rewritten name %s", name); | ||
48 | |||
49 | int len = strlen(name) + sizeof(char) * 6; | ||
50 | char *identifier = malloc(len); | ||
51 | if (!identifier) { | ||
52 | sway_log(L_ERROR, "Unable to allocate unique input device name"); | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | const char *fmt = "%d:%d:%s"; | ||
57 | snprintf(identifier, len, fmt, vendor, product, name); | ||
58 | free(name); | ||
59 | return identifier; | ||
60 | } | ||
61 | |||
62 | static struct sway_input_device *input_sway_device_from_wlr( | ||
63 | struct sway_input_manager *input, struct wlr_input_device *device) { | ||
64 | struct sway_input_device *input_device = NULL; | ||
65 | wl_list_for_each(input_device, &input->devices, link) { | ||
66 | if (input_device->wlr_device == device) { | ||
67 | return input_device; | ||
68 | } | ||
69 | } | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
73 | static struct sway_input_device *input_sway_device_from_config( | ||
74 | struct sway_input_manager *input, struct input_config *config) { | ||
75 | struct sway_input_device *input_device = NULL; | ||
76 | wl_list_for_each(input_device, &input->devices, link) { | ||
77 | if (strcmp(input_device->identifier, config->identifier) == 0) { | ||
78 | return input_device; | ||
79 | } | ||
80 | } | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | static struct sway_input_device *input_sway_device_from_identifier( | ||
85 | struct sway_input_manager *input, char *identifier) { | ||
86 | struct sway_input_device *input_device = NULL; | ||
87 | wl_list_for_each(input_device, &input->devices, link) { | ||
88 | if (strcmp(input_device->identifier, identifier) == 0) { | ||
89 | return input_device; | ||
90 | } | ||
91 | } | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | static bool input_has_seat_configuration(struct sway_input_manager *input) { | ||
96 | struct sway_seat *seat = NULL; | ||
97 | wl_list_for_each(seat, &input->seats, link) { | ||
98 | if (seat->config) { | ||
99 | return true; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | return false; | ||
104 | } | ||
105 | |||
106 | static void input_add_notify(struct wl_listener *listener, void *data) { | ||
107 | struct sway_input_manager *input = | ||
108 | wl_container_of(listener, input, input_add); | ||
109 | struct wlr_input_device *device = data; | ||
110 | |||
111 | struct sway_input_device *input_device = | ||
112 | calloc(1, sizeof(struct sway_input_device)); | ||
113 | if (!sway_assert(input_device, "could not allocate input device")) { | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | input_device->wlr_device = device; | ||
118 | input_device->identifier = get_device_identifier(device); | ||
119 | wl_list_insert(&input->devices, &input_device->link); | ||
120 | |||
121 | // find config | ||
122 | for (int i = 0; i < config->input_configs->length; ++i) { | ||
123 | struct input_config *input_config = config->input_configs->items[i]; | ||
124 | if (strcmp(input_config->identifier, input_device->identifier) == 0) { | ||
125 | input_device->config = input_config; | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | struct sway_seat *seat = NULL; | ||
131 | if (!input_has_seat_configuration(input)) { | ||
132 | seat = input_manager_get_seat(input, default_seat); | ||
133 | sway_seat_add_device(seat, input_device); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | wl_list_for_each(seat, &input->seats, link) { | ||
138 | if (seat->config && | ||
139 | (seat_config_get_attachment(seat->config, input_device->identifier) || | ||
140 | seat_config_get_attachment(seat->config, "*"))) { | ||
141 | sway_seat_add_device(seat, input_device); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static void input_remove_notify(struct wl_listener *listener, void *data) { | ||
147 | struct sway_input_manager *input = | ||
148 | wl_container_of(listener, input, input_remove); | ||
149 | struct wlr_input_device *device = data; | ||
150 | |||
151 | struct sway_input_device *input_device = | ||
152 | input_sway_device_from_wlr(input, device); | ||
153 | |||
154 | if (!sway_assert(input_device, "could not find sway device")) { | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | struct sway_seat *seat = NULL; | ||
159 | wl_list_for_each(seat, &input->seats, link) { | ||
160 | sway_seat_remove_device(seat, input_device); | ||
161 | } | ||
162 | |||
163 | wl_list_remove(&input_device->link); | ||
164 | free(input_device->identifier); | ||
165 | free(input_device); | ||
166 | } | ||
167 | |||
168 | struct sway_input_manager *sway_input_manager_create( | ||
169 | struct sway_server *server) { | ||
170 | struct sway_input_manager *input = | ||
171 | calloc(1, sizeof(struct sway_input_manager)); | ||
172 | if (!input) { | ||
173 | return NULL; | ||
174 | } | ||
175 | input->server = server; | ||
176 | |||
177 | wl_list_init(&input->devices); | ||
178 | wl_list_init(&input->seats); | ||
179 | |||
180 | // create the default seat | ||
181 | input_manager_get_seat(input, default_seat); | ||
182 | |||
183 | input->input_add.notify = input_add_notify; | ||
184 | wl_signal_add(&server->backend->events.input_add, &input->input_add); | ||
185 | |||
186 | input->input_remove.notify = input_remove_notify; | ||
187 | wl_signal_add(&server->backend->events.input_remove, &input->input_remove); | ||
188 | |||
189 | return input; | ||
190 | } | ||
191 | |||
192 | bool sway_input_manager_has_focus(struct sway_input_manager *input, | ||
193 | swayc_t *container) { | ||
194 | struct sway_seat *seat = NULL; | ||
195 | wl_list_for_each(seat, &input->seats, link) { | ||
196 | if (seat->focus == container) { | ||
197 | return true; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | return false; | ||
202 | } | ||
203 | |||
204 | void sway_input_manager_set_focus(struct sway_input_manager *input, | ||
205 | swayc_t *container) { | ||
206 | struct sway_seat *seat ; | ||
207 | wl_list_for_each(seat, &input->seats, link) { | ||
208 | sway_seat_set_focus(seat, container); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | void sway_input_manager_apply_input_config(struct sway_input_manager *input, | ||
213 | struct input_config *input_config) { | ||
214 | struct sway_input_device *input_device = | ||
215 | input_sway_device_from_config(input, input_config); | ||
216 | if (!input_device) { | ||
217 | return; | ||
218 | } | ||
219 | input_device->config = input_config; | ||
220 | |||
221 | struct sway_seat *seat = NULL; | ||
222 | wl_list_for_each(seat, &input->seats, link) { | ||
223 | sway_seat_configure_device(seat, input_device); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | void sway_input_manager_apply_seat_config(struct sway_input_manager *input, | ||
228 | struct seat_config *seat_config) { | ||
229 | struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); | ||
230 | // the old config is invalid so clear it | ||
231 | sway_seat_set_config(seat, NULL); | ||
232 | |||
233 | // clear devices | ||
234 | struct sway_input_device *input_device = NULL; | ||
235 | wl_list_for_each(input_device, &input->devices, link) { | ||
236 | sway_seat_remove_device(seat, input_device); | ||
237 | } | ||
238 | |||
239 | if (seat_config_get_attachment(seat_config, "*")) { | ||
240 | wl_list_for_each(input_device, &input->devices, link) { | ||
241 | sway_seat_add_device(seat, input_device); | ||
242 | } | ||
243 | } else { | ||
244 | for (int i = 0; i < seat_config->attachments->length; ++i) { | ||
245 | struct seat_attachment_config *attachment = | ||
246 | seat_config->attachments->items[i]; | ||
247 | |||
248 | struct sway_input_device *device = | ||
249 | input_sway_device_from_identifier(input, | ||
250 | attachment->identifier); | ||
251 | |||
252 | if (device) { | ||
253 | sway_seat_add_device(seat, device); | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | sway_seat_set_config(seat, seat_config); | ||
259 | } | ||
260 | |||
261 | void sway_input_manager_configure_xcursor(struct sway_input_manager *input) { | ||
262 | struct sway_seat *seat = NULL; | ||
263 | wl_list_for_each(seat, &input->seats, link) { | ||
264 | sway_seat_configure_xcursor(seat); | ||
265 | } | ||
266 | } | ||
diff --git a/sway/input/input.c b/sway/input/input.c deleted file mode 100644 index 02b4995e..00000000 --- a/sway/input/input.c +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <ctype.h> | ||
3 | #include <float.h> | ||
4 | #include <limits.h> | ||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | #include <libinput.h> | ||
8 | #include "sway/config.h" | ||
9 | #include "sway/input.h" | ||
10 | #include "sway/server.h" | ||
11 | #include "list.h" | ||
12 | #include "log.h" | ||
13 | |||
14 | struct input_config *current_input_config = NULL; | ||
15 | |||
16 | struct sway_input *sway_input_create(struct sway_server *server) { | ||
17 | struct sway_input *input = calloc(1, sizeof(struct sway_input)); | ||
18 | if (!input) { | ||
19 | return NULL; | ||
20 | } | ||
21 | return input; | ||
22 | } | ||
23 | |||
24 | struct input_config *new_input_config(const char* identifier) { | ||
25 | struct input_config *input = calloc(1, sizeof(struct input_config)); | ||
26 | if (!input) { | ||
27 | sway_log(L_DEBUG, "Unable to allocate input config"); | ||
28 | return NULL; | ||
29 | } | ||
30 | sway_log(L_DEBUG, "new_input_config(%s)", identifier); | ||
31 | if (!(input->identifier = strdup(identifier))) { | ||
32 | free(input); | ||
33 | sway_log(L_DEBUG, "Unable to allocate input config"); | ||
34 | return NULL; | ||
35 | } | ||
36 | |||
37 | input->tap = INT_MIN; | ||
38 | input->drag_lock = INT_MIN; | ||
39 | input->dwt = INT_MIN; | ||
40 | input->send_events = INT_MIN; | ||
41 | input->click_method = INT_MIN; | ||
42 | input->middle_emulation = INT_MIN; | ||
43 | input->natural_scroll = INT_MIN; | ||
44 | input->accel_profile = INT_MIN; | ||
45 | input->pointer_accel = FLT_MIN; | ||
46 | input->scroll_method = INT_MIN; | ||
47 | input->left_handed = INT_MIN; | ||
48 | |||
49 | return input; | ||
50 | } | ||
51 | |||
52 | char *libinput_dev_unique_id(struct libinput_device *device) { | ||
53 | int vendor = libinput_device_get_id_vendor(device); | ||
54 | int product = libinput_device_get_id_product(device); | ||
55 | char *name = strdup(libinput_device_get_name(device)); | ||
56 | |||
57 | char *p = name; | ||
58 | for (; *p; ++p) { | ||
59 | if (*p == ' ') { | ||
60 | *p = '_'; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | sway_log(L_DEBUG, "rewritten name %s", name); | ||
65 | |||
66 | int len = strlen(name) + sizeof(char) * 6; | ||
67 | char *identifier = malloc(len); | ||
68 | if (!identifier) { | ||
69 | sway_log(L_ERROR, "Unable to allocate unique input device name"); | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
73 | const char *fmt = "%d:%d:%s"; | ||
74 | snprintf(identifier, len, fmt, vendor, product, name); | ||
75 | free(name); | ||
76 | return identifier; | ||
77 | } | ||
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c new file mode 100644 index 00000000..b9b571a6 --- /dev/null +++ b/sway/input/keyboard.c | |||
@@ -0,0 +1,111 @@ | |||
1 | #include "sway/input/seat.h" | ||
2 | #include "sway/input/keyboard.h" | ||
3 | #include "sway/input/input-manager.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | static void handle_keyboard_key(struct wl_listener *listener, void *data) { | ||
7 | struct sway_keyboard *keyboard = | ||
8 | wl_container_of(listener, keyboard, keyboard_key); | ||
9 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | ||
10 | struct wlr_input_device *wlr_device = | ||
11 | keyboard->seat_device->input_device->wlr_device; | ||
12 | struct wlr_event_keyboard_key *event = data; | ||
13 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | ||
14 | wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, | ||
15 | event->keycode, event->state); | ||
16 | } | ||
17 | |||
18 | static void handle_keyboard_modifiers(struct wl_listener *listener, | ||
19 | void *data) { | ||
20 | struct sway_keyboard *keyboard = | ||
21 | wl_container_of(listener, keyboard, keyboard_modifiers); | ||
22 | struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; | ||
23 | struct wlr_input_device *wlr_device = | ||
24 | keyboard->seat_device->input_device->wlr_device; | ||
25 | wlr_seat_set_keyboard(wlr_seat, wlr_device); | ||
26 | wlr_seat_keyboard_notify_modifiers(wlr_seat); | ||
27 | } | ||
28 | |||
29 | struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat, | ||
30 | struct sway_seat_device *device) { | ||
31 | struct sway_keyboard *keyboard = | ||
32 | calloc(1, sizeof(struct sway_keyboard)); | ||
33 | if (!sway_assert(keyboard, "could not allocate sway keyboard")) { | ||
34 | return NULL; | ||
35 | } | ||
36 | |||
37 | keyboard->seat_device = device; | ||
38 | device->keyboard = keyboard; | ||
39 | |||
40 | wl_list_init(&keyboard->keyboard_key.link); | ||
41 | wl_list_init(&keyboard->keyboard_modifiers.link); | ||
42 | |||
43 | return keyboard; | ||
44 | } | ||
45 | |||
46 | void sway_keyboard_configure(struct sway_keyboard *keyboard) { | ||
47 | struct xkb_rule_names rules; | ||
48 | memset(&rules, 0, sizeof(rules)); | ||
49 | struct input_config *input_config = | ||
50 | keyboard->seat_device->input_device->config; | ||
51 | struct wlr_input_device *wlr_device = | ||
52 | keyboard->seat_device->input_device->wlr_device; | ||
53 | |||
54 | if (input_config && input_config->xkb_layout) { | ||
55 | rules.layout = input_config->xkb_layout; | ||
56 | } else { | ||
57 | rules.layout = getenv("XKB_DEFAULT_LAYOUT"); | ||
58 | } | ||
59 | if (input_config && input_config->xkb_model) { | ||
60 | rules.model = input_config->xkb_model; | ||
61 | } else { | ||
62 | rules.model = getenv("XKB_DEFAULT_MODEL"); | ||
63 | } | ||
64 | |||
65 | if (input_config && input_config->xkb_options) { | ||
66 | rules.options = input_config->xkb_options; | ||
67 | } else { | ||
68 | rules.options = getenv("XKB_DEFAULT_OPTIONS"); | ||
69 | } | ||
70 | |||
71 | if (input_config && input_config->xkb_rules) { | ||
72 | rules.rules = input_config->xkb_rules; | ||
73 | } else { | ||
74 | rules.rules = getenv("XKB_DEFAULT_RULES"); | ||
75 | } | ||
76 | |||
77 | if (input_config && input_config->xkb_variant) { | ||
78 | rules.variant = input_config->xkb_variant; | ||
79 | } else { | ||
80 | rules.variant = getenv("XKB_DEFAULT_VARIANT"); | ||
81 | } | ||
82 | |||
83 | struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); | ||
84 | if (!sway_assert(context, "cannot create XKB context")) { | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | xkb_keymap_unref(keyboard->keymap); | ||
89 | keyboard->keymap = | ||
90 | xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); | ||
91 | wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); | ||
92 | wlr_keyboard_set_repeat_info(wlr_device->keyboard, 25, 600); | ||
93 | xkb_context_unref(context); | ||
94 | |||
95 | wl_list_remove(&keyboard->keyboard_key.link); | ||
96 | wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); | ||
97 | keyboard->keyboard_key.notify = handle_keyboard_key; | ||
98 | |||
99 | wl_list_remove(&keyboard->keyboard_modifiers.link); | ||
100 | wl_signal_add( &wlr_device->keyboard->events.modifiers, | ||
101 | &keyboard->keyboard_modifiers); | ||
102 | keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; | ||
103 | } | ||
104 | |||
105 | void sway_keyboard_destroy(struct sway_keyboard *keyboard) { | ||
106 | xkb_keymap_unref(keyboard->keymap); | ||
107 | wl_list_remove(&keyboard->keyboard_key.link); | ||
108 | wl_list_remove(&keyboard->keyboard_modifiers.link); | ||
109 | wl_list_remove(&keyboard->link); | ||
110 | free(keyboard); | ||
111 | } | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c new file mode 100644 index 00000000..1b25419b --- /dev/null +++ b/sway/input/seat.c | |||
@@ -0,0 +1,242 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <wlr/types/wlr_cursor.h> | ||
3 | #include <wlr/types/wlr_xcursor_manager.h> | ||
4 | #include "sway/input/seat.h" | ||
5 | #include "sway/input/cursor.h" | ||
6 | #include "sway/input/input-manager.h" | ||
7 | #include "sway/input/keyboard.h" | ||
8 | #include "sway/output.h" | ||
9 | #include "sway/view.h" | ||
10 | #include "log.h" | ||
11 | |||
12 | static void seat_device_destroy(struct sway_seat_device *seat_device) { | ||
13 | if (!seat_device) { | ||
14 | return; | ||
15 | } | ||
16 | |||
17 | sway_keyboard_destroy(seat_device->keyboard); | ||
18 | wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, | ||
19 | seat_device->input_device->wlr_device); | ||
20 | wl_list_remove(&seat_device->link); | ||
21 | free(seat_device); | ||
22 | } | ||
23 | |||
24 | struct sway_seat *sway_seat_create(struct sway_input_manager *input, | ||
25 | const char *seat_name) { | ||
26 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | ||
27 | if (!seat) { | ||
28 | return NULL; | ||
29 | } | ||
30 | |||
31 | seat->wlr_seat = wlr_seat_create(input->server->wl_display, seat_name); | ||
32 | if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { | ||
33 | return NULL; | ||
34 | } | ||
35 | |||
36 | seat->cursor = sway_cursor_create(seat); | ||
37 | if (!seat->cursor) { | ||
38 | wlr_seat_destroy(seat->wlr_seat); | ||
39 | free(seat); | ||
40 | return NULL; | ||
41 | } | ||
42 | |||
43 | seat->input = input; | ||
44 | wl_list_init(&seat->devices); | ||
45 | |||
46 | wlr_seat_set_capabilities(seat->wlr_seat, | ||
47 | WL_SEAT_CAPABILITY_KEYBOARD | | ||
48 | WL_SEAT_CAPABILITY_POINTER | | ||
49 | WL_SEAT_CAPABILITY_TOUCH); | ||
50 | |||
51 | sway_seat_configure_xcursor(seat); | ||
52 | |||
53 | wl_list_insert(&input->seats, &seat->link); | ||
54 | |||
55 | return seat; | ||
56 | } | ||
57 | |||
58 | static void seat_configure_pointer(struct sway_seat *seat, | ||
59 | struct sway_seat_device *sway_device) { | ||
60 | // TODO pointer configuration | ||
61 | wlr_cursor_attach_input_device(seat->cursor->cursor, | ||
62 | sway_device->input_device->wlr_device); | ||
63 | } | ||
64 | |||
65 | static void seat_configure_keyboard(struct sway_seat *seat, | ||
66 | struct sway_seat_device *seat_device) { | ||
67 | if (!seat_device->keyboard) { | ||
68 | sway_keyboard_create(seat, seat_device); | ||
69 | } | ||
70 | sway_keyboard_configure(seat_device->keyboard); | ||
71 | } | ||
72 | |||
73 | static struct sway_seat_device *sway_seat_get_device(struct sway_seat *seat, | ||
74 | struct sway_input_device *input_device) { | ||
75 | struct sway_seat_device *seat_device = NULL; | ||
76 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
77 | if (seat_device->input_device == input_device) { | ||
78 | return seat_device; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | void sway_seat_configure_device(struct sway_seat *seat, | ||
86 | struct sway_input_device *input_device) { | ||
87 | struct sway_seat_device *seat_device = | ||
88 | sway_seat_get_device(seat, input_device); | ||
89 | if (!seat_device) { | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | if (seat->config) { | ||
94 | seat_device->attachment_config = | ||
95 | seat_config_get_attachment(seat->config, input_device->identifier); | ||
96 | } | ||
97 | |||
98 | switch (input_device->wlr_device->type) { | ||
99 | case WLR_INPUT_DEVICE_POINTER: | ||
100 | seat_configure_pointer(seat, seat_device); | ||
101 | break; | ||
102 | case WLR_INPUT_DEVICE_KEYBOARD: | ||
103 | seat_configure_keyboard(seat, seat_device); | ||
104 | wlr_seat_set_keyboard(seat->wlr_seat, | ||
105 | seat_device->input_device->wlr_device); | ||
106 | break; | ||
107 | case WLR_INPUT_DEVICE_TOUCH: | ||
108 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
109 | case WLR_INPUT_DEVICE_TABLET_TOOL: | ||
110 | sway_log(L_DEBUG, "TODO: configure other devices"); | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | void sway_seat_add_device(struct sway_seat *seat, | ||
116 | struct sway_input_device *input_device) { | ||
117 | if (sway_seat_get_device(seat, input_device)) { | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | struct sway_seat_device *seat_device = | ||
122 | calloc(1, sizeof(struct sway_seat_device)); | ||
123 | if (!seat_device) { | ||
124 | sway_log(L_DEBUG, "could not allocate seat device"); | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | seat_device->sway_seat = seat; | ||
129 | seat_device->input_device = input_device; | ||
130 | wl_list_insert(&seat->devices, &seat_device->link); | ||
131 | |||
132 | sway_seat_configure_device(seat, input_device); | ||
133 | } | ||
134 | |||
135 | void sway_seat_remove_device(struct sway_seat *seat, | ||
136 | struct sway_input_device *input_device) { | ||
137 | sway_log(L_DEBUG, "input remove: %s", input_device->identifier); | ||
138 | struct sway_seat_device *seat_device = | ||
139 | sway_seat_get_device(seat, input_device); | ||
140 | |||
141 | if (!seat_device) { | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | seat_device_destroy(seat_device); | ||
146 | } | ||
147 | |||
148 | void sway_seat_configure_xcursor(struct sway_seat *seat) { | ||
149 | // TODO configure theme and size | ||
150 | const char *cursor_theme = "default"; | ||
151 | |||
152 | if (!seat->cursor->xcursor_manager) { | ||
153 | seat->cursor->xcursor_manager = | ||
154 | wlr_xcursor_manager_create("default", 24); | ||
155 | if (sway_assert(seat->cursor->xcursor_manager, | ||
156 | "Cannot create XCursor manager for theme %s", | ||
157 | cursor_theme)) { | ||
158 | return; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | for (int i = 0; i < root_container.children->length; ++i) { | ||
163 | swayc_t *output_container = root_container.children->items[i]; | ||
164 | struct wlr_output *output = | ||
165 | output_container->sway_output->wlr_output; | ||
166 | bool result = | ||
167 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, | ||
168 | output->scale); | ||
169 | |||
170 | sway_assert(!result, | ||
171 | "Cannot load xcursor theme for output '%s' with scale %d", | ||
172 | output->name, output->scale); | ||
173 | } | ||
174 | |||
175 | wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, | ||
176 | "left_ptr", seat->cursor->cursor); | ||
177 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, | ||
178 | seat->cursor->cursor->y); | ||
179 | } | ||
180 | |||
181 | static void handle_focus_destroy(struct wl_listener *listener, void *data) { | ||
182 | struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); | ||
183 | //swayc_t *container = data; | ||
184 | |||
185 | // TODO set new focus based on the state of the tree | ||
186 | sway_seat_set_focus(seat, NULL); | ||
187 | } | ||
188 | |||
189 | void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { | ||
190 | swayc_t *last_focus = seat->focus; | ||
191 | |||
192 | if (last_focus == container) { | ||
193 | return; | ||
194 | } | ||
195 | |||
196 | if (last_focus) { | ||
197 | wl_list_remove(&seat->focus_destroy.link); | ||
198 | } | ||
199 | |||
200 | if (container) { | ||
201 | struct sway_view *view = container->sway_view; | ||
202 | view->iface.set_activated(view, true); | ||
203 | wl_signal_add(&container->events.destroy, &seat->focus_destroy); | ||
204 | seat->focus_destroy.notify = handle_focus_destroy; | ||
205 | wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface); | ||
206 | } | ||
207 | |||
208 | seat->focus = container; | ||
209 | |||
210 | if (last_focus && | ||
211 | !sway_input_manager_has_focus(seat->input, last_focus)) { | ||
212 | struct sway_view *view = last_focus->sway_view; | ||
213 | view->iface.set_activated(view, false); | ||
214 | |||
215 | } | ||
216 | } | ||
217 | |||
218 | void sway_seat_set_config(struct sway_seat *seat, | ||
219 | struct seat_config *seat_config) { | ||
220 | // clear configs | ||
221 | seat->config = NULL; | ||
222 | |||
223 | struct sway_seat_device *seat_device = NULL; | ||
224 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
225 | seat_device->attachment_config = NULL; | ||
226 | } | ||
227 | |||
228 | if (!seat_config) { | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | // add configs | ||
233 | seat->config = seat_config; | ||
234 | |||
235 | wl_list_for_each(seat_device, &seat->devices, link) { | ||
236 | seat_device->attachment_config = | ||
237 | seat_config_get_attachment(seat_config, | ||
238 | seat_device->input_device->identifier); | ||
239 | sway_seat_configure_device(seat, seat_device->input_device); | ||
240 | } | ||
241 | |||
242 | } | ||
diff --git a/sway/main.c b/sway/main.c index 8952f997..bd69395a 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -158,6 +158,7 @@ static void log_distro() { | |||
158 | } | 158 | } |
159 | 159 | ||
160 | static void log_kernel() { | 160 | static void log_kernel() { |
161 | return; | ||
161 | FILE *f = popen("uname -a", "r"); | 162 | FILE *f = popen("uname -a", "r"); |
162 | if (!f) { | 163 | if (!f) { |
163 | sway_log(L_INFO, "Unable to determine kernel version"); | 164 | sway_log(L_INFO, "Unable to determine kernel version"); |
@@ -381,11 +382,12 @@ int main(int argc, char **argv) { | |||
381 | 382 | ||
382 | sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); | 383 | sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); |
383 | 384 | ||
385 | init_layout(); | ||
386 | |||
384 | if (!server_init(&server)) { | 387 | if (!server_init(&server)) { |
385 | return 1; | 388 | return 1; |
386 | } | 389 | } |
387 | 390 | ||
388 | init_layout(); | ||
389 | ipc_init(&server); | 391 | ipc_init(&server); |
390 | log_env(); | 392 | log_env(); |
391 | 393 | ||
diff --git a/sway/meson.build b/sway/meson.build index e16691a8..c1f75b13 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -2,10 +2,33 @@ sway_sources = files( | |||
2 | 'main.c', | 2 | 'main.c', |
3 | 'server.c', | 3 | 'server.c', |
4 | 'commands.c', | 4 | 'commands.c', |
5 | 'input/input-manager.c', | ||
6 | 'input/seat.c', | ||
7 | 'input/cursor.c', | ||
8 | 'input/keyboard.c', | ||
5 | 'commands/exit.c', | 9 | 'commands/exit.c', |
6 | 'commands/exec.c', | 10 | 'commands/exec.c', |
7 | 'commands/exec_always.c', | 11 | 'commands/exec_always.c', |
8 | 'commands/include.c', | 12 | 'commands/include.c', |
13 | 'commands/input.c', | ||
14 | 'commands/seat.c', | ||
15 | 'commands/seat/attach.c', | ||
16 | 'commands/input/accel_profile.c', | ||
17 | 'commands/input/click_method.c', | ||
18 | 'commands/input/drag_lock.c', | ||
19 | 'commands/input/dwt.c', | ||
20 | 'commands/input/events.c', | ||
21 | 'commands/input/left_handed.c', | ||
22 | 'commands/input/middle_emulation.c', | ||
23 | 'commands/input/natural_scroll.c', | ||
24 | 'commands/input/pointer_accel.c', | ||
25 | 'commands/input/scroll_method.c', | ||
26 | 'commands/input/tap.c', | ||
27 | 'commands/input/xkb_layout.c', | ||
28 | 'commands/input/xkb_model.c', | ||
29 | 'commands/input/xkb_options.c', | ||
30 | 'commands/input/xkb_rules.c', | ||
31 | 'commands/input/xkb_variant.c', | ||
9 | 'commands/output.c', | 32 | 'commands/output.c', |
10 | 'config.c', | 33 | 'config.c', |
11 | 'config/output.c', | 34 | 'config/output.c', |
@@ -28,6 +51,8 @@ sway_deps = [ | |||
28 | wlroots, | 51 | wlroots, |
29 | libcap, | 52 | libcap, |
30 | math, | 53 | math, |
54 | libinput, | ||
55 | xkbcommon, | ||
31 | ] | 56 | ] |
32 | 57 | ||
33 | executable( | 58 | executable( |
diff --git a/sway/server.c b/sway/server.c index 024d8429..32c8f03c 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -11,6 +11,7 @@ | |||
11 | // TODO WLR: make Xwayland optional | 11 | // TODO WLR: make Xwayland optional |
12 | #include <wlr/xwayland.h> | 12 | #include <wlr/xwayland.h> |
13 | #include "sway/server.h" | 13 | #include "sway/server.h" |
14 | #include "sway/input/input-manager.h" | ||
14 | #include "log.h" | 15 | #include "log.h" |
15 | 16 | ||
16 | bool server_init(struct sway_server *server) { | 17 | bool server_init(struct sway_server *server) { |
@@ -58,6 +59,9 @@ bool server_init(struct sway_server *server) { | |||
58 | wlr_backend_destroy(server->backend); | 59 | wlr_backend_destroy(server->backend); |
59 | return false; | 60 | return false; |
60 | } | 61 | } |
62 | |||
63 | input_manager = sway_input_manager_create(server); | ||
64 | |||
61 | return true; | 65 | return true; |
62 | } | 66 | } |
63 | 67 | ||
diff --git a/sway/tree/container.c b/sway/tree/container.c index 5df10bcb..6f2a3abf 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include <strings.h> | 5 | #include <strings.h> |
6 | #include <wlr/types/wlr_output_layout.h> | 6 | #include <wlr/types/wlr_output_layout.h> |
7 | #include <wlr/types/wlr_wl_shell.h> | ||
7 | #include "sway/config.h" | 8 | #include "sway/config.h" |
8 | #include "sway/container.h" | 9 | #include "sway/container.h" |
9 | #include "sway/layout.h" | 10 | #include "sway/layout.h" |
@@ -42,6 +43,9 @@ static swayc_t *new_swayc(enum swayc_types type) { | |||
42 | if (type != C_VIEW) { | 43 | if (type != C_VIEW) { |
43 | c->children = create_list(); | 44 | c->children = create_list(); |
44 | } | 45 | } |
46 | |||
47 | wl_signal_init(&c->events.destroy); | ||
48 | |||
45 | return c; | 49 | return c; |
46 | } | 50 | } |
47 | 51 | ||
@@ -140,6 +144,9 @@ static void free_swayc(swayc_t *cont) { | |||
140 | if (!sway_assert(cont, "free_swayc passed NULL")) { | 144 | if (!sway_assert(cont, "free_swayc passed NULL")) { |
141 | return; | 145 | return; |
142 | } | 146 | } |
147 | |||
148 | wl_signal_emit(&cont->events.destroy, cont); | ||
149 | |||
143 | if (cont->children) { | 150 | if (cont->children) { |
144 | // remove children until there are no more, free_swayc calls | 151 | // remove children until there are no more, free_swayc calls |
145 | // remove_child, which removes child from this container | 152 | // remove_child, which removes child from this container |
@@ -218,3 +225,63 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | |||
218 | } while (container && container->type != type); | 225 | } while (container && container->type != type); |
219 | return container; | 226 | return container; |
220 | } | 227 | } |
228 | |||
229 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, | ||
230 | struct wlr_surface **surface, double *sx, double *sy) { | ||
231 | list_t *queue = create_list(); | ||
232 | list_add(queue, parent); | ||
233 | |||
234 | swayc_t *swayc = NULL; | ||
235 | while (queue->length) { | ||
236 | swayc = queue->items[0]; | ||
237 | list_del(queue, 0); | ||
238 | if (swayc->type == C_VIEW) { | ||
239 | struct sway_view *sview = swayc->sway_view; | ||
240 | swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); | ||
241 | struct wlr_box *output_box = | ||
242 | wlr_output_layout_get_box( | ||
243 | root_container.sway_root->output_layout, | ||
244 | soutput->sway_output->wlr_output); | ||
245 | double ox = lx - output_box->x; | ||
246 | double oy = ly - output_box->y; | ||
247 | double view_sx = ox - swayc->x; | ||
248 | double view_sy = oy - swayc->y; | ||
249 | int width = swayc->sway_view->surface->current->width; | ||
250 | int height = swayc->sway_view->surface->current->height; | ||
251 | |||
252 | // TODO popups and subsurfaces | ||
253 | switch (sview->type) { | ||
254 | case SWAY_WL_SHELL_VIEW: | ||
255 | break; | ||
256 | case SWAY_XDG_SHELL_V6_VIEW: | ||
257 | // the top left corner of the sway container is the | ||
258 | // coordinate of the top left corner of the window geometry | ||
259 | view_sx += sview->wlr_xdg_surface_v6->geometry->x; | ||
260 | view_sy += sview->wlr_xdg_surface_v6->geometry->y; | ||
261 | break; | ||
262 | case SWAY_XWAYLAND_VIEW: | ||
263 | break; | ||
264 | default: | ||
265 | break; | ||
266 | } | ||
267 | |||
268 | if (view_sx > 0 && view_sx < width && | ||
269 | view_sy > 0 && view_sy < height && | ||
270 | pixman_region32_contains_point( | ||
271 | &sview->surface->current->input, | ||
272 | view_sx, view_sy, NULL)) { | ||
273 | *sx = view_sx; | ||
274 | *sy = view_sy; | ||
275 | *surface = swayc->sway_view->surface; | ||
276 | list_free(queue); | ||
277 | return swayc; | ||
278 | } | ||
279 | } else { | ||
280 | list_cat(queue, swayc->children); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | list_free(queue); | ||
285 | |||
286 | return NULL; | ||
287 | } | ||