diff options
-rw-r--r-- | include/sway/container.h | 4 | ||||
-rw-r--r-- | include/sway/input/cursor.h | 30 | ||||
-rw-r--r-- | include/sway/input/input-manager.h | 22 | ||||
-rw-r--r-- | include/sway/input/seat.h | 23 | ||||
-rw-r--r-- | include/sway/server.h | 2 | ||||
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | sway/desktop/output.c | 29 | ||||
-rw-r--r-- | sway/input/cursor.c | 168 | ||||
-rw-r--r-- | sway/input/input-manager.c | 133 | ||||
-rw-r--r-- | sway/input/input.c | 77 | ||||
-rw-r--r-- | sway/input/seat.c | 112 | ||||
-rw-r--r-- | sway/main.c | 3 | ||||
-rw-r--r-- | sway/meson.build | 4 | ||||
-rw-r--r-- | sway/server.c | 4 | ||||
-rw-r--r-- | sway/tree/container.c | 60 |
15 files changed, 589 insertions, 83 deletions
diff --git a/include/sway/container.h b/include/sway/container.h index 08a98ed9..0e1cc8a3 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; |
@@ -136,4 +137,7 @@ swayc_t *destroy_view(swayc_t *view); | |||
136 | 137 | ||
137 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); | 138 | swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type); |
138 | 139 | ||
140 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, | ||
141 | struct wlr_surface **surface, double *sx, double *sy); | ||
142 | |||
139 | #endif | 143 | #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..5dc75ba7 --- /dev/null +++ b/include/sway/input/input-manager.h | |||
@@ -0,0 +1,22 @@ | |||
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 | struct sway_input_manager { | ||
9 | struct wl_listener input_add; | ||
10 | struct wl_listener input_remove; | ||
11 | struct sway_server *server; | ||
12 | list_t *seats; | ||
13 | }; | ||
14 | |||
15 | struct input_config *new_input_config(const char* identifier); | ||
16 | |||
17 | char* libinput_dev_unique_id(struct libinput_device *dev); | ||
18 | |||
19 | struct sway_input_manager *sway_input_manager_create( | ||
20 | struct sway_server *server); | ||
21 | |||
22 | #endif | ||
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h new file mode 100644 index 00000000..f7f8a1bb --- /dev/null +++ b/include/sway/input/seat.h | |||
@@ -0,0 +1,23 @@ | |||
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 { | ||
8 | struct wlr_seat *seat; | ||
9 | struct sway_cursor *cursor; | ||
10 | }; | ||
11 | |||
12 | struct sway_seat *sway_seat_create(struct wl_display *display, | ||
13 | const char *seat_name); | ||
14 | |||
15 | void sway_seat_add_device(struct sway_seat *seat, | ||
16 | struct wlr_input_device *device); | ||
17 | |||
18 | void sway_seat_remove_device(struct sway_seat *seat, | ||
19 | struct wlr_input_device *device); | ||
20 | |||
21 | void sway_seat_configure_xcursor(struct sway_seat *seat); | ||
22 | |||
23 | #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/desktop/output.c b/sway/desktop/output.c index 7eb48bdf..0e7f7060 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]; |
@@ -120,6 +136,11 @@ void output_add_notify(struct wl_listener *listener, void *data) { | |||
120 | output->resolution.notify = output_resolution_notify; | 136 | output->resolution.notify = output_resolution_notify; |
121 | wl_signal_add(&wlr_output->events.resolution, &output->resolution); | 137 | wl_signal_add(&wlr_output->events.resolution, &output->resolution); |
122 | 138 | ||
139 | for (int i = 0; i < server->input->seats->length; ++i) { | ||
140 | struct sway_seat *seat = server->input->seats->items[i]; | ||
141 | sway_seat_configure_xcursor(seat); | ||
142 | } | ||
143 | |||
123 | arrange_windows(output->swayc, -1, -1); | 144 | arrange_windows(output->swayc, -1, -1); |
124 | } | 145 | } |
125 | 146 | ||
diff --git a/sway/input/cursor.c b/sway/input/cursor.c new file mode 100644 index 00000000..5f2d650e --- /dev/null +++ b/sway/input/cursor.c | |||
@@ -0,0 +1,168 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <wlr/types/wlr_cursor.h> | ||
3 | #include <wlr/types/wlr_xcursor_manager.h> | ||
4 | #include "sway/input/cursor.h" | ||
5 | #include "sway/view.h" | ||
6 | #include "list.h" | ||
7 | #include "log.h" | ||
8 | |||
9 | static void cursor_update_position(struct sway_cursor *cursor) { | ||
10 | double x = cursor->cursor->x; | ||
11 | double y = cursor->cursor->y; | ||
12 | |||
13 | wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, | ||
14 | "left_ptr", cursor->cursor); | ||
15 | |||
16 | cursor->x = x; | ||
17 | cursor->y = y; | ||
18 | } | ||
19 | |||
20 | static void cursor_send_pointer_motion(struct sway_cursor *cursor, | ||
21 | uint32_t time) { | ||
22 | struct wlr_seat *seat = cursor->seat->seat; | ||
23 | struct wlr_surface *surface = NULL; | ||
24 | double sx, sy; | ||
25 | swayc_t *swayc = | ||
26 | swayc_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy); | ||
27 | if (swayc) { | ||
28 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | ||
29 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | ||
30 | } else { | ||
31 | wlr_seat_pointer_clear_focus(seat); | ||
32 | } | ||
33 | } | ||
34 | |||
35 | static void handle_cursor_motion(struct wl_listener *listener, void *data) { | ||
36 | struct sway_cursor *cursor = | ||
37 | wl_container_of(listener, cursor, motion); | ||
38 | struct wlr_event_pointer_motion *event = data; | ||
39 | wlr_cursor_move(cursor->cursor, event->device, | ||
40 | event->delta_x, event->delta_y); | ||
41 | cursor_update_position(cursor); | ||
42 | cursor_send_pointer_motion(cursor, event->time_msec); | ||
43 | } | ||
44 | |||
45 | static void handle_cursor_motion_absolute(struct wl_listener *listener, | ||
46 | void *data) { | ||
47 | struct sway_cursor *cursor = | ||
48 | wl_container_of(listener, cursor, motion_absolute); | ||
49 | struct wlr_event_pointer_motion_absolute *event = data; | ||
50 | wlr_cursor_warp_absolute(cursor->cursor, event->device, | ||
51 | event->x_mm / event->width_mm, event->y_mm / event->height_mm); | ||
52 | cursor_update_position(cursor); | ||
53 | cursor_send_pointer_motion(cursor, event->time_msec); | ||
54 | } | ||
55 | |||
56 | static void handle_cursor_button(struct wl_listener *listener, void *data) { | ||
57 | struct sway_cursor *cursor = | ||
58 | wl_container_of(listener, cursor, button); | ||
59 | struct wlr_event_pointer_button *event = data; | ||
60 | wlr_seat_pointer_notify_button(cursor->seat->seat, event->time_msec, | ||
61 | event->button, event->state); | ||
62 | } | ||
63 | |||
64 | static void handle_cursor_axis(struct wl_listener *listener, void *data) { | ||
65 | struct sway_cursor *cursor = | ||
66 | wl_container_of(listener, cursor, axis); | ||
67 | struct wlr_event_pointer_axis *event = data; | ||
68 | wlr_seat_pointer_notify_axis(cursor->seat->seat, event->time_msec, | ||
69 | event->orientation, event->delta); | ||
70 | } | ||
71 | |||
72 | static void handle_touch_down(struct wl_listener *listener, void *data) { | ||
73 | struct sway_cursor *cursor = | ||
74 | wl_container_of(listener, cursor, touch_down); | ||
75 | struct wlr_event_touch_down *event = data; | ||
76 | sway_log(L_DEBUG, "TODO: handle touch down event: %p", event); | ||
77 | } | ||
78 | |||
79 | static void handle_touch_up(struct wl_listener *listener, void *data) { | ||
80 | struct sway_cursor *cursor = | ||
81 | wl_container_of(listener, cursor, touch_up); | ||
82 | struct wlr_event_touch_up *event = data; | ||
83 | sway_log(L_DEBUG, "TODO: handle touch up event: %p", event); | ||
84 | } | ||
85 | |||
86 | static void handle_touch_motion(struct wl_listener *listener, void *data) { | ||
87 | struct sway_cursor *cursor = | ||
88 | wl_container_of(listener, cursor, touch_motion); | ||
89 | struct wlr_event_touch_motion *event = data; | ||
90 | sway_log(L_DEBUG, "TODO: handle touch motion event: %p", event); | ||
91 | } | ||
92 | |||
93 | static void handle_tool_axis(struct wl_listener *listener, void *data) { | ||
94 | struct sway_cursor *cursor = | ||
95 | wl_container_of(listener, cursor, tool_axis); | ||
96 | struct wlr_event_tablet_tool_axis *event = data; | ||
97 | sway_log(L_DEBUG, "TODO: handle tool axis event: %p", event); | ||
98 | } | ||
99 | |||
100 | static void handle_tool_tip(struct wl_listener *listener, void *data) { | ||
101 | struct sway_cursor *cursor = | ||
102 | wl_container_of(listener, cursor, tool_tip); | ||
103 | struct wlr_event_tablet_tool_tip *event = data; | ||
104 | sway_log(L_DEBUG, "TODO: handle tool tip event: %p", event); | ||
105 | } | ||
106 | |||
107 | static void handle_request_set_cursor(struct wl_listener *listener, | ||
108 | void *data) { | ||
109 | struct sway_cursor *cursor = | ||
110 | wl_container_of(listener, cursor, request_set_cursor); | ||
111 | struct wlr_seat_pointer_request_set_cursor_event *event = data; | ||
112 | sway_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); | ||
113 | } | ||
114 | |||
115 | struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { | ||
116 | struct sway_cursor *cursor = calloc(1, sizeof(struct sway_cursor)); | ||
117 | if (!sway_assert(cursor, "could not allocate sway cursor")) { | ||
118 | return NULL; | ||
119 | } | ||
120 | |||
121 | struct wlr_cursor *wlr_cursor = wlr_cursor_create(); | ||
122 | if (!sway_assert(wlr_cursor, "could not allocate wlr cursor")) { | ||
123 | free(cursor); | ||
124 | return NULL; | ||
125 | } | ||
126 | |||
127 | cursor->seat = seat; | ||
128 | wlr_cursor_attach_output_layout(wlr_cursor, root_container.output_layout); | ||
129 | |||
130 | // input events | ||
131 | wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); | ||
132 | cursor->motion.notify = handle_cursor_motion; | ||
133 | |||
134 | wl_signal_add(&wlr_cursor->events.motion_absolute, | ||
135 | &cursor->motion_absolute); | ||
136 | cursor->motion_absolute.notify = handle_cursor_motion_absolute; | ||
137 | |||
138 | wl_signal_add(&wlr_cursor->events.button, &cursor->button); | ||
139 | cursor->button.notify = handle_cursor_button; | ||
140 | |||
141 | wl_signal_add(&wlr_cursor->events.axis, &cursor->axis); | ||
142 | cursor->axis.notify = handle_cursor_axis; | ||
143 | |||
144 | wl_signal_add(&wlr_cursor->events.touch_down, &cursor->touch_down); | ||
145 | cursor->touch_down.notify = handle_touch_down; | ||
146 | |||
147 | wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); | ||
148 | cursor->touch_up.notify = handle_touch_up; | ||
149 | |||
150 | wl_signal_add(&wlr_cursor->events.touch_motion, | ||
151 | &cursor->touch_motion); | ||
152 | cursor->touch_motion.notify = handle_touch_motion; | ||
153 | |||
154 | wl_signal_add(&wlr_cursor->events.tablet_tool_axis, | ||
155 | &cursor->tool_axis); | ||
156 | cursor->tool_axis.notify = handle_tool_axis; | ||
157 | |||
158 | wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &cursor->tool_tip); | ||
159 | cursor->tool_tip.notify = handle_tool_tip; | ||
160 | |||
161 | wl_signal_add(&seat->seat->events.request_set_cursor, | ||
162 | &cursor->request_set_cursor); | ||
163 | cursor->request_set_cursor.notify = handle_request_set_cursor; | ||
164 | |||
165 | cursor->cursor = wlr_cursor; | ||
166 | |||
167 | return cursor; | ||
168 | } | ||
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c new file mode 100644 index 00000000..4f52e59a --- /dev/null +++ b/sway/input/input-manager.c | |||
@@ -0,0 +1,133 @@ | |||
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 | struct input_config *current_input_config = NULL; | ||
18 | |||
19 | static struct sway_seat *input_manager_get_seat( | ||
20 | struct sway_input_manager *input, const char *seat_name) { | ||
21 | struct sway_seat *seat = NULL; | ||
22 | |||
23 | for (int i = 0; i < input->seats->length; ++i) { | ||
24 | seat = input->seats->items[i]; | ||
25 | if (strcmp(seat->seat->name, seat_name) == 0) { | ||
26 | return seat; | ||
27 | } | ||
28 | } | ||
29 | |||
30 | seat = sway_seat_create(input->server->wl_display, seat_name); | ||
31 | list_add(input->seats, seat); | ||
32 | |||
33 | return seat; | ||
34 | } | ||
35 | |||
36 | static void input_add_notify(struct wl_listener *listener, void *data) { | ||
37 | struct sway_input_manager *input = | ||
38 | wl_container_of(listener, input, input_add); | ||
39 | struct wlr_input_device *device = data; | ||
40 | |||
41 | // TODO device configuration | ||
42 | struct sway_seat *seat = input_manager_get_seat(input, default_seat); | ||
43 | sway_seat_add_device(seat, device); | ||
44 | } | ||
45 | |||
46 | static void input_remove_notify(struct wl_listener *listener, void *data) { | ||
47 | struct sway_input_manager *input = | ||
48 | wl_container_of(listener, input, input_remove); | ||
49 | struct wlr_input_device *device = data; | ||
50 | |||
51 | // TODO device configuration | ||
52 | struct sway_seat *seat = input_manager_get_seat(input, default_seat); | ||
53 | sway_seat_remove_device(seat, device); | ||
54 | } | ||
55 | |||
56 | struct sway_input_manager *sway_input_manager_create( | ||
57 | struct sway_server *server) { | ||
58 | struct sway_input_manager *input = | ||
59 | calloc(1, sizeof(struct sway_input_manager)); | ||
60 | if (!input) { | ||
61 | return NULL; | ||
62 | } | ||
63 | // XXX probably don't need the full server | ||
64 | input->server = server; | ||
65 | |||
66 | input->seats = create_list(); | ||
67 | |||
68 | // create the default seat | ||
69 | input_manager_get_seat(input, default_seat); | ||
70 | |||
71 | input->input_add.notify = input_add_notify; | ||
72 | wl_signal_add(&server->backend->events.input_add, &input->input_add); | ||
73 | |||
74 | input->input_remove.notify = input_remove_notify; | ||
75 | wl_signal_add(&server->backend->events.input_remove, &input->input_remove); | ||
76 | |||
77 | return input; | ||
78 | } | ||
79 | |||
80 | struct input_config *new_input_config(const char* identifier) { | ||
81 | struct input_config *input = calloc(1, sizeof(struct input_config)); | ||
82 | if (!input) { | ||
83 | sway_log(L_DEBUG, "Unable to allocate input config"); | ||
84 | return NULL; | ||
85 | } | ||
86 | sway_log(L_DEBUG, "new_input_config(%s)", identifier); | ||
87 | if (!(input->identifier = strdup(identifier))) { | ||
88 | free(input); | ||
89 | sway_log(L_DEBUG, "Unable to allocate input config"); | ||
90 | return NULL; | ||
91 | } | ||
92 | |||
93 | input->tap = INT_MIN; | ||
94 | input->drag_lock = INT_MIN; | ||
95 | input->dwt = INT_MIN; | ||
96 | input->send_events = INT_MIN; | ||
97 | input->click_method = INT_MIN; | ||
98 | input->middle_emulation = INT_MIN; | ||
99 | input->natural_scroll = INT_MIN; | ||
100 | input->accel_profile = INT_MIN; | ||
101 | input->pointer_accel = FLT_MIN; | ||
102 | input->scroll_method = INT_MIN; | ||
103 | input->left_handed = INT_MIN; | ||
104 | |||
105 | return input; | ||
106 | } | ||
107 | |||
108 | char *libinput_dev_unique_id(struct libinput_device *device) { | ||
109 | int vendor = libinput_device_get_id_vendor(device); | ||
110 | int product = libinput_device_get_id_product(device); | ||
111 | char *name = strdup(libinput_device_get_name(device)); | ||
112 | |||
113 | char *p = name; | ||
114 | for (; *p; ++p) { | ||
115 | if (*p == ' ') { | ||
116 | *p = '_'; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | sway_log(L_DEBUG, "rewritten name %s", name); | ||
121 | |||
122 | int len = strlen(name) + sizeof(char) * 6; | ||
123 | char *identifier = malloc(len); | ||
124 | if (!identifier) { | ||
125 | sway_log(L_ERROR, "Unable to allocate unique input device name"); | ||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | const char *fmt = "%d:%d:%s"; | ||
130 | snprintf(identifier, len, fmt, vendor, product, name); | ||
131 | free(name); | ||
132 | return identifier; | ||
133 | } | ||
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/seat.c b/sway/input/seat.c new file mode 100644 index 00000000..5aed1f68 --- /dev/null +++ b/sway/input/seat.c | |||
@@ -0,0 +1,112 @@ | |||
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/output.h" | ||
8 | #include "log.h" | ||
9 | |||
10 | struct sway_seat *sway_seat_create(struct wl_display *display, | ||
11 | const char *seat_name) { | ||
12 | struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); | ||
13 | if (!seat) { | ||
14 | return NULL; | ||
15 | } | ||
16 | |||
17 | seat->seat = wlr_seat_create(display, seat_name); | ||
18 | if (!sway_assert(seat->seat, "could not allocate seat")) { | ||
19 | return NULL; | ||
20 | } | ||
21 | |||
22 | seat->cursor = sway_cursor_create(seat); | ||
23 | if (!seat->cursor) { | ||
24 | wlr_seat_destroy(seat->seat); | ||
25 | free(seat); | ||
26 | return NULL; | ||
27 | } | ||
28 | |||
29 | wlr_seat_set_capabilities(seat->seat, | ||
30 | WL_SEAT_CAPABILITY_KEYBOARD | | ||
31 | WL_SEAT_CAPABILITY_POINTER | | ||
32 | WL_SEAT_CAPABILITY_TOUCH); | ||
33 | |||
34 | sway_seat_configure_xcursor(seat); | ||
35 | |||
36 | return seat; | ||
37 | } | ||
38 | |||
39 | static void seat_add_pointer(struct sway_seat *seat, | ||
40 | struct wlr_input_device *device) { | ||
41 | // TODO pointer configuration | ||
42 | wlr_cursor_attach_input_device(seat->cursor->cursor, device); | ||
43 | } | ||
44 | |||
45 | void sway_seat_add_device(struct sway_seat *seat, | ||
46 | struct wlr_input_device *device) { | ||
47 | sway_log(L_DEBUG, "input add: %s", device->name); | ||
48 | switch (device->type) { | ||
49 | case WLR_INPUT_DEVICE_POINTER: | ||
50 | seat_add_pointer(seat, device); | ||
51 | break; | ||
52 | case WLR_INPUT_DEVICE_KEYBOARD: | ||
53 | case WLR_INPUT_DEVICE_TOUCH: | ||
54 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
55 | case WLR_INPUT_DEVICE_TABLET_TOOL: | ||
56 | sway_log(L_DEBUG, "TODO: add other devices"); | ||
57 | break; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static void seat_remove_pointer(struct sway_seat *seat, | ||
62 | struct wlr_input_device *device) { | ||
63 | // TODO | ||
64 | } | ||
65 | |||
66 | void sway_seat_remove_device(struct sway_seat *seat, | ||
67 | struct wlr_input_device *device) { | ||
68 | sway_log(L_DEBUG, "input remove: %s", device->name); | ||
69 | switch (device->type) { | ||
70 | case WLR_INPUT_DEVICE_POINTER: | ||
71 | seat_remove_pointer(seat, device); | ||
72 | break; | ||
73 | case WLR_INPUT_DEVICE_KEYBOARD: | ||
74 | case WLR_INPUT_DEVICE_TOUCH: | ||
75 | case WLR_INPUT_DEVICE_TABLET_PAD: | ||
76 | case WLR_INPUT_DEVICE_TABLET_TOOL: | ||
77 | sway_log(L_DEBUG, "TODO: remove other devices"); | ||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | void sway_seat_configure_xcursor(struct sway_seat *seat) { | ||
83 | // TODO configure theme and size | ||
84 | const char *cursor_theme = "default"; | ||
85 | |||
86 | if (!seat->cursor->xcursor_manager) { | ||
87 | seat->cursor->xcursor_manager = | ||
88 | wlr_xcursor_manager_create("default", 24); | ||
89 | if (sway_assert(seat->cursor->xcursor_manager, | ||
90 | "Cannot create XCursor manager for theme %s", cursor_theme)) { | ||
91 | return; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | for (int i = 0; i < root_container.children->length; ++i) { | ||
96 | swayc_t *output_container = root_container.children->items[i]; | ||
97 | struct wlr_output *output = | ||
98 | output_container->sway_output->wlr_output; | ||
99 | bool result = | ||
100 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, | ||
101 | output->scale); | ||
102 | |||
103 | sway_assert(!result, | ||
104 | "Cannot load xcursor theme for output '%s' with scale %d", | ||
105 | output->name, output->scale); | ||
106 | } | ||
107 | |||
108 | wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager, | ||
109 | "left_ptr", seat->cursor->cursor); | ||
110 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, | ||
111 | seat->cursor->cursor->y); | ||
112 | } | ||
diff --git a/sway/main.c b/sway/main.c index bc843591..363f4d96 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -381,11 +381,12 @@ int main(int argc, char **argv) { | |||
381 | 381 | ||
382 | sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); | 382 | sway_log(L_INFO, "Starting sway version " SWAY_VERSION "\n"); |
383 | 383 | ||
384 | init_layout(); | ||
385 | |||
384 | if (!server_init(&server)) { | 386 | if (!server_init(&server)) { |
385 | return 1; | 387 | return 1; |
386 | } | 388 | } |
387 | 389 | ||
388 | init_layout(); | ||
389 | ipc_init(&server); | 390 | ipc_init(&server); |
390 | log_env(); | 391 | log_env(); |
391 | 392 | ||
diff --git a/sway/meson.build b/sway/meson.build index ab863e87..18955693 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -2,6 +2,9 @@ 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', | ||
5 | 'commands/exit.c', | 8 | 'commands/exit.c', |
6 | 'commands/exec.c', | 9 | 'commands/exec.c', |
7 | 'commands/exec_always.c', | 10 | 'commands/exec_always.c', |
@@ -26,6 +29,7 @@ sway_deps = [ | |||
26 | wlroots, | 29 | wlroots, |
27 | libcap, | 30 | libcap, |
28 | math, | 31 | math, |
32 | libinput, | ||
29 | ] | 33 | ] |
30 | 34 | ||
31 | executable( | 35 | executable( |
diff --git a/sway/server.c b/sway/server.c index 024d8429..7b9a5e8e 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 | server->input = 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 e205fbcf..321ef8b1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include <wlr/types/wlr_output_layout.h> | 5 | #include <wlr/types/wlr_output_layout.h> |
6 | #include <wlr/types/wlr_wl_shell.h> | ||
6 | #include "sway/container.h" | 7 | #include "sway/container.h" |
7 | #include "sway/layout.h" | 8 | #include "sway/layout.h" |
8 | #include "sway/output.h" | 9 | #include "sway/output.h" |
@@ -168,3 +169,62 @@ swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { | |||
168 | } while (container && container->type != type); | 169 | } while (container && container->type != type); |
169 | return container; | 170 | return container; |
170 | } | 171 | } |
172 | |||
173 | swayc_t *swayc_at(swayc_t *parent, double lx, double ly, | ||
174 | struct wlr_surface **surface, double *sx, double *sy) { | ||
175 | list_t *queue = create_list(); | ||
176 | list_add(queue, parent); | ||
177 | |||
178 | swayc_t *swayc = NULL; | ||
179 | while (queue->length) { | ||
180 | swayc = queue->items[0]; | ||
181 | list_del(queue, 0); | ||
182 | if (swayc->type == C_VIEW) { | ||
183 | struct sway_view *sview = swayc->sway_view; | ||
184 | swayc_t *soutput = swayc_parent_by_type(swayc, C_OUTPUT); | ||
185 | struct wlr_box *output_box = | ||
186 | wlr_output_layout_get_box(root_container.output_layout, | ||
187 | soutput->sway_output->wlr_output); | ||
188 | double ox = lx - output_box->x; | ||
189 | double oy = ly - output_box->y; | ||
190 | double view_sx = ox - swayc->x; | ||
191 | double view_sy = oy - swayc->y; | ||
192 | int width = swayc->sway_view->surface->current->width; | ||
193 | int height = swayc->sway_view->surface->current->height; | ||
194 | |||
195 | // TODO popups and subsurfaces | ||
196 | switch (sview->type) { | ||
197 | case SWAY_WL_SHELL_VIEW: | ||
198 | break; | ||
199 | case SWAY_XDG_SHELL_V6_VIEW: | ||
200 | // the top left corner of the sway container is the | ||
201 | // coordinate of the top left corner of the window geometry | ||
202 | view_sx += sview->wlr_xdg_surface_v6->geometry->x; | ||
203 | view_sy += sview->wlr_xdg_surface_v6->geometry->y; | ||
204 | break; | ||
205 | case SWAY_XWAYLAND_VIEW: | ||
206 | break; | ||
207 | default: | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | if (view_sx > 0 && view_sx < width && | ||
212 | view_sy > 0 && view_sy < height && | ||
213 | pixman_region32_contains_point( | ||
214 | &sview->surface->current->input, | ||
215 | view_sx, view_sy, NULL)) { | ||
216 | *sx = view_sx; | ||
217 | *sy = view_sy; | ||
218 | *surface = swayc->sway_view->surface; | ||
219 | list_free(queue); | ||
220 | return swayc; | ||
221 | } | ||
222 | } else { | ||
223 | list_cat(queue, swayc->children); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | list_free(queue); | ||
228 | |||
229 | return NULL; | ||
230 | } | ||