1 #include <hikari/normal_mode.h>
2
3 #include <wlr/types/wlr_cursor.h>
4 #include <wlr/types/wlr_seat.h>
5
6 #include <hikari/action.h>
7 #include <hikari/binding.h>
8 #include <hikari/binding_group.h>
9 #include <hikari/configuration.h>
10 #include <hikari/indicator.h>
11 #include <hikari/indicator_frame.h>
12 #include <hikari/keyboard.h>
13 #include <hikari/renderer.h>
14 #include <hikari/server.h>
15 #include <hikari/view.h>
16
17 #ifndef NDEBUG
18 #include <hikari/layout.h>
19 #include <hikari/sheet.h>
20 #include <hikari/workspace.h>
21 #endif
22
23 struct cursor_down_state {
24 double lx;
25 double ly;
26 double sx;
27 double sy;
28 };
29
30 static struct cursor_down_state cursor_down_state;
31
32 static bool
handle_input(struct hikari_binding_group * map,uint32_t code)33 handle_input(struct hikari_binding_group *map, uint32_t code)
34 {
35 int nbindings = map->nbindings;
36 struct hikari_binding *bindings = map->bindings;
37
38 for (int i = 0; i < nbindings; i++) {
39 struct hikari_binding *binding = &bindings[i];
40
41 if (binding->keycode == code) {
42 struct hikari_event_action *event_action;
43
44 if (binding->action->end.action != NULL) {
45 hikari_server.normal_mode.pending_action = &binding->action->end;
46 }
47
48 event_action = &binding->action->begin;
49 if (event_action->action != NULL) {
50 event_action->action(event_action->arg);
51 }
52 return true;
53 }
54 }
55
56 return false;
57 }
58
59 static bool
handle_pending_action(void)60 handle_pending_action(void)
61 {
62 struct hikari_event_action *pending_action =
63 hikari_server.normal_mode.pending_action;
64
65 if (pending_action != NULL) {
66 pending_action->action(pending_action->arg);
67 hikari_server.normal_mode.pending_action = NULL;
68 return true;
69 }
70
71 return false;
72 }
73
74 #ifndef NDEBUG
75 static void
dump_debug(struct hikari_server * server)76 dump_debug(struct hikari_server *server)
77 {
78 struct hikari_view *view;
79 printf("---------------------------------------------------------------------"
80 "\n");
81 printf("VIEWS\n");
82 printf("---------------------------------------------------------------------"
83 "\n");
84 wl_list_for_each (view, &hikari_server.visible_views, visible_server_views) {
85 printf("%p ", view);
86 }
87 printf("\n");
88 printf("---------------------------------------------------------------------"
89 "\n");
90 printf("GROUPS\n");
91 printf("---------------------------------------------------------------------"
92 "\n");
93 struct hikari_group *group;
94 wl_list_for_each (group, &hikari_server.groups, server_groups) {
95 printf("%s ", group->name);
96
97 wl_list_for_each (view, &group->visible_views, visible_group_views) {
98 printf("%p ", view);
99 }
100
101 printf("/ ");
102
103 wl_list_for_each (view, &group->views, group_views) {
104 printf("%p ", view);
105 }
106
107 printf("\n");
108 }
109 printf("---------------------------------------------------------------------"
110 "\n");
111 struct hikari_output *output;
112 wl_list_for_each (output, &hikari_server.outputs, server_outputs) {
113 struct hikari_workspace *workspace = output->workspace;
114 const char *output_name = workspace->output->wlr_output->name;
115 printf("SHEETS %s (%p)\n", output_name, workspace->focus_view);
116 printf(
117 "---------------------------------------------------------------------"
118 "\n");
119 struct hikari_sheet *sheets = workspace->sheets;
120 struct hikari_sheet *sheet;
121 for (int i = 0; i < 10; i++) {
122 sheet = &sheets[i];
123 if (!wl_list_empty(&sheet->views)) {
124 printf("%d ", sheet->nr);
125 wl_list_for_each (view, &sheet->views, sheet_views) {
126 printf("%p ", view);
127 }
128 printf("\n");
129 }
130 }
131 printf(
132 "---------------------------------------------------------------------"
133 "\n");
134 if (workspace->sheet->layout != NULL) {
135 printf(
136 "-------------------------------------------------------------------"
137 "--\n");
138 printf("LAYOUT %s\n", output_name);
139 struct hikari_tile *tile;
140 wl_list_for_each (tile, &workspace->sheet->layout->tiles, layout_tiles) {
141 printf("%p ", tile->view);
142 }
143 printf("\n");
144 }
145 }
146 printf("/////////////////////////////////////////////////////////////////////"
147 "\n");
148 }
149 #endif
150
151 static void
modifiers_handler(struct hikari_keyboard * keyboard)152 modifiers_handler(struct hikari_keyboard *keyboard)
153 {
154 wlr_seat_set_keyboard(hikari_server.seat, keyboard->device);
155 struct hikari_view *focus_view = hikari_server.workspace->focus_view;
156
157 if (hikari_server.keyboard_state.mod_released) {
158
159 if (hikari_server_is_cycling() && focus_view != NULL) {
160 hikari_view_raise(focus_view);
161 hikari_view_center_cursor(focus_view);
162 hikari_server_cursor_focus();
163 }
164
165 hikari_server_unset_cycling();
166 }
167
168 if (hikari_server.keyboard_state.mod_changed) {
169 if (focus_view != NULL) {
170 hikari_group_damage(focus_view->group);
171 hikari_indicator_damage(&hikari_server.indicator, focus_view);
172 }
173 #ifndef NDEBUG
174 dump_debug(&hikari_server);
175 #endif
176 }
177
178 wlr_seat_keyboard_notify_modifiers(
179 hikari_server.seat, &keyboard->device->keyboard->modifiers);
180 }
181
182 static void
cancel(void)183 cancel(void)
184 {}
185
186 static void
cursor_down_move(uint32_t time)187 cursor_down_move(uint32_t time)
188 {
189 struct wlr_seat *seat = hikari_server.seat;
190
191 double x = hikari_server.cursor.wlr_cursor->x;
192 double y = hikari_server.cursor.wlr_cursor->y;
193
194 double moved_x = x - cursor_down_state.lx;
195 double moved_y = y - cursor_down_state.ly;
196
197 double sx = cursor_down_state.sx + moved_x;
198 double sy = cursor_down_state.sy + moved_y;
199
200 wlr_seat_pointer_notify_motion(seat, time, sx, sy);
201 }
202
203 static void
cursor_move(uint32_t time)204 cursor_move(uint32_t time)
205 {
206 assert(hikari_server_in_normal_mode());
207
208 double sx, sy;
209 struct wlr_seat *seat = hikari_server.seat;
210 struct wlr_surface *surface;
211 struct hikari_workspace *workspace;
212
213 struct hikari_node *node =
214 hikari_server_node_at(hikari_server.cursor.wlr_cursor->x,
215 hikari_server.cursor.wlr_cursor->y,
216 &surface,
217 &workspace,
218 &sx,
219 &sy);
220
221 if (node != NULL) {
222 struct hikari_node *focus_node =
223 (struct hikari_node *)hikari_server.workspace->focus_view;
224
225 if (node != focus_node) {
226 hikari_node_focus(node);
227 }
228
229 wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
230 wlr_seat_pointer_notify_motion(seat, time, sx, sy);
231 } else {
232 if (hikari_server.workspace != workspace) {
233 struct hikari_view *view = hikari_workspace_first_view(workspace);
234 hikari_workspace_focus_view(workspace, view);
235 }
236 if (seat->pointer_state.focused_surface != NULL) {
237 hikari_cursor_reset_image(&hikari_server.cursor);
238 }
239 wlr_seat_pointer_clear_focus(seat);
240 }
241 }
242
243 static inline void
start_cursor_down_handling(struct wlr_event_pointer_button * event)244 start_cursor_down_handling(struct wlr_event_pointer_button *event)
245 {
246 double lx = hikari_server.cursor.wlr_cursor->x;
247 double ly = hikari_server.cursor.wlr_cursor->y;
248
249 double sx;
250 double sy;
251 struct hikari_workspace *workspace;
252 struct wlr_surface *surface;
253
254 struct hikari_node *node =
255 hikari_server_node_at(lx, ly, &surface, &workspace, &sx, &sy);
256
257 if (node != NULL) {
258 hikari_server.normal_mode.mode.cursor_move = cursor_down_move;
259 cursor_down_state.lx = lx;
260 cursor_down_state.ly = ly;
261 cursor_down_state.sx = sx;
262 cursor_down_state.sy = sy;
263 }
264
265 wlr_seat_pointer_notify_button(
266 hikari_server.seat, event->time_msec, event->button, event->state);
267 }
268
269 static inline void
stop_cursor_down_handling(struct wlr_event_pointer_button * event)270 stop_cursor_down_handling(struct wlr_event_pointer_button *event)
271 {
272 hikari_server.normal_mode.mode.cursor_move = cursor_move;
273
274 wlr_seat_pointer_notify_button(
275 hikari_server.seat, event->time_msec, event->button, event->state);
276
277 hikari_server_cursor_focus();
278 }
279
280 static inline bool
is_cursor_down(void)281 is_cursor_down(void)
282 {
283 return hikari_server.normal_mode.mode.cursor_move == cursor_down_move;
284 }
285
286 static void
button_handler(struct hikari_cursor * cursor,struct wlr_event_pointer_button * event)287 button_handler(
288 struct hikari_cursor *cursor, struct wlr_event_pointer_button *event)
289 {
290 if (handle_pending_action()) {
291 if (event->state == WLR_BUTTON_RELEASED && is_cursor_down()) {
292 stop_cursor_down_handling(event);
293 }
294 return;
295 }
296
297 if (event->state == WLR_BUTTON_PRESSED) {
298 uint32_t modifiers = hikari_server.keyboard_state.modifiers;
299 struct hikari_binding_group *map = &cursor->bindings[modifiers];
300
301 if (!handle_input(map, event->button)) {
302 start_cursor_down_handling(event);
303 }
304 } else {
305 if (is_cursor_down()) {
306 stop_cursor_down_handling(event);
307 } else {
308 wlr_seat_pointer_notify_button(
309 hikari_server.seat, event->time_msec, event->button, event->state);
310 }
311 }
312 }
313
314 static void
key_handler(struct hikari_keyboard * keyboard,struct wlr_event_keyboard_key * event)315 key_handler(
316 struct hikari_keyboard *keyboard, struct wlr_event_keyboard_key *event)
317 {
318 if (handle_pending_action()) {
319 return;
320 }
321
322 if (event->state == WLR_KEY_PRESSED) {
323 uint32_t modifiers = hikari_server.keyboard_state.modifiers;
324 struct hikari_binding_group *bindings = &keyboard->bindings[modifiers];
325
326 if (handle_input(bindings, event->keycode)) {
327 return;
328 }
329 }
330
331 wlr_seat_set_keyboard(hikari_server.seat, keyboard->device);
332 wlr_seat_keyboard_notify_key(
333 hikari_server.seat, event->time_msec, event->keycode, event->state);
334 }
335
336 void
hikari_normal_mode_init(struct hikari_normal_mode * normal_mode)337 hikari_normal_mode_init(struct hikari_normal_mode *normal_mode)
338 {
339 normal_mode->mode.key_handler = key_handler;
340 normal_mode->mode.button_handler = button_handler;
341 normal_mode->mode.modifiers_handler = modifiers_handler;
342 normal_mode->mode.render = hikari_renderer_normal_mode;
343 normal_mode->mode.cancel = cancel;
344 normal_mode->mode.cursor_move = cursor_move;
345 normal_mode->pending_action = NULL;
346 }
347
348 void
hikari_normal_mode_enter(void)349 hikari_normal_mode_enter(void)
350 {
351 struct hikari_server *server = &hikari_server;
352
353 assert(server->workspace != NULL);
354
355 hikari_server.normal_mode.mode.cursor_move = cursor_move;
356
357 server->mode->cancel();
358 server->mode = (struct hikari_mode *)&server->normal_mode;
359 }
360