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