1 #include "tickit.h"
2 #include "taplib.h"
3 #include "taplib-mockterm.h"
4
5 #include <string.h>
6
7 struct LastEvent {
8 int type;
9 int mod;
10 int line, col, button;
11 char str[16];
12
13 int ret;
14 };
15
on_key_event_capture(TickitWindow * win,TickitEventFlags flags,void * _info,void * data)16 int on_key_event_capture(TickitWindow *win, TickitEventFlags flags, void *_info, void *data)
17 {
18 struct LastEvent *last_event = data;
19 TickitKeyEventInfo *info = _info;
20
21 last_event->type = info->type;
22 last_event->mod = info->mod;
23 strcpy(last_event->str, info->str);
24
25 return last_event->ret;
26 }
27
on_mouse_event_capture(TickitWindow * win,TickitEventFlags flags,void * _info,void * data)28 int on_mouse_event_capture(TickitWindow *win, TickitEventFlags flags, void *_info, void *data)
29 {
30 struct LastEvent *last_event = data;
31 TickitMouseEventInfo *info = _info;
32
33 last_event->type = info->type;
34 last_event->mod = info->mod;
35 last_event->line = info->line;
36 last_event->col = info->col;
37 last_event->button = info->button;
38
39 return last_event->ret;
40 }
41
42 int next_idx = 0;
43 char *ids[3];
44
on_event_push(TickitWindow * win,TickitEventFlags flags,void * _info,void * data)45 int on_event_push(TickitWindow *win, TickitEventFlags flags, void *_info, void *data)
46 {
47 ids[next_idx++] = data;
48 return 0;
49 }
50
on_event_incr_int(TickitWindow * win,TickitEventFlags flags,void * _info,void * data)51 int on_event_incr_int(TickitWindow *win, TickitEventFlags flags, void *_info, void *data)
52 {
53 ((int *)data)[0]++;
54 return 0;
55 }
56
on_termevent_incr_int(TickitTerm * tt,TickitEventFlags flags,void * _info,void * data)57 int on_termevent_incr_int(TickitTerm *tt, TickitEventFlags flags, void *_info, void *data)
58 {
59 ((int *)data)[0]++;
60 return 0;
61 }
62
63 TickitWindow *childwin = NULL;
64 int childmouse = 0;
65
win_on_mouse_child(TickitWindow * win,TickitEventFlags flags,void * _info,void * data)66 int win_on_mouse_child(TickitWindow *win, TickitEventFlags flags, void *_info, void *data) {
67 if(childwin)
68 return 0;
69
70 childwin = tickit_window_new(win, (TickitRect){0, 0, 2, 2}, 0);
71 tickit_window_bind_event(childwin, TICKIT_WINDOW_ON_MOUSE, 0, &on_event_incr_int, &childmouse);
72 return 0;
73 }
74
75 TickitWindow *siblingwin = NULL;
76 int siblingmouse = 0;
77
win_on_mouse_sibling(TickitWindow * win,TickitEventFlags flags,void * _info,void * data)78 int win_on_mouse_sibling(TickitWindow *win, TickitEventFlags flags, void *_info, void *data) {
79 if(siblingwin)
80 return 0;
81
82 siblingwin = tickit_window_new(win, (TickitRect){0, 0, 2, 2}, 0);
83 tickit_window_bind_event(siblingwin, TICKIT_WINDOW_ON_MOUSE, 0, &on_event_incr_int, &siblingmouse);
84 return 0;
85 }
86
main(int argc,char * argv[])87 int main(int argc, char *argv[])
88 {
89 TickitTerm *tt = make_term(25, 80);
90 TickitWindow *root = tickit_window_new_root(tt);
91
92 TickitWindow *win = tickit_window_new(root, (TickitRect){3, 10, 4, 20}, 0);
93
94 tickit_window_take_focus(win);
95 tickit_window_flush(root);
96
97 struct LastEvent win_last = { .ret = 1 };
98 int key_bind_id = tickit_window_bind_event(win, TICKIT_WINDOW_ON_KEY, 0,
99 &on_key_event_capture, &win_last);
100 int mouse_bind_id = tickit_window_bind_event(win, TICKIT_WINDOW_ON_MOUSE, 0,
101 &on_mouse_event_capture, &win_last);
102
103 // Key events
104 {
105 press_key(TICKIT_KEYEV_TEXT, "A", 0);
106
107 is_int(win_last.type, TICKIT_KEYEV_TEXT, "win_last.type for A");
108 is_str(win_last.str, "A", "win_last.str for A");
109
110 press_key(TICKIT_KEYEV_KEY, "C-a", TICKIT_MOD_CTRL);
111
112 is_int(win_last.type, TICKIT_KEYEV_KEY, "win_last.type for C-a");
113 is_str(win_last.str, "C-a", "win_last.str for C-a");
114 is_int(win_last.mod, TICKIT_MOD_CTRL, "win_last.mod for C-a");
115 }
116
117 // Mouse events
118 {
119 win_last.type = 0;
120 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 5, 15, 0);
121
122 is_int(win_last.type, TICKIT_MOUSEEV_PRESS, "win_last.type for press 1@15,5");
123 is_int(win_last.line, 2, "win_last.line for press 1@15,5");
124 is_int(win_last.col, 5, "win_last.col for press 1@15,5");
125
126 win_last.type = 0;
127 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 1, 2, 0);
128
129 is_int(win_last.type, 0, "win_last.type still 0 after press @1,2");
130 }
131
132 // Unhandled events are not consumed
133 {
134 int term_invoked = 0;
135 int bind_id = tickit_term_bind_event(tt, TICKIT_TERM_ON_KEY, 0, &on_termevent_incr_int, &term_invoked);
136
137 win_last.ret = 0;
138
139 press_key(TICKIT_KEYEV_KEY, "A", 0);
140
141 ok(term_invoked, "term event handler invoked after unhandled window event");
142
143 tickit_term_unbind_event_id(tt, bind_id);
144 }
145
146 TickitWindow *subwin = tickit_window_new(win, (TickitRect){2, 2, 1, 10}, 0);
147
148 // Subwindow
149 {
150 tickit_window_take_focus(subwin);
151 tickit_window_flush(root);
152
153 struct LastEvent subwin_last = { .ret = 1 };
154 int sub_key_bind_id = tickit_window_bind_event(subwin, TICKIT_WINDOW_ON_KEY, 0,
155 &on_key_event_capture, &subwin_last);
156 int sub_mouse_bind_id = tickit_window_bind_event(subwin, TICKIT_WINDOW_ON_MOUSE, 0,
157 &on_mouse_event_capture, &subwin_last);
158
159 win_last.type = 0;
160
161 press_key(TICKIT_KEYEV_TEXT, "B", 0);
162
163 is_int(subwin_last.type, TICKIT_KEYEV_TEXT, "subwin_last.type for B");
164 is_str(subwin_last.str, "B", "subwin_last.str for B");
165
166 is_int(win_last.type, 0, "win_last.type for B");
167
168 subwin_last.type = 0;
169
170 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 5, 15, 0);
171
172 is_int(subwin_last.type, TICKIT_MOUSEEV_PRESS, "subwin_last.type for press 1@15,5");
173 is_int(subwin_last.line, 0, "subwin_last.line for press 1@15,5");
174 is_int(subwin_last.col, 3, "subwin_last.col for press 1@15,5");
175
176 subwin_last.ret = 0;
177
178 subwin_last.type = 0;
179 win_last.type = 0;
180
181 press_key(TICKIT_KEYEV_TEXT, "C", 0);
182
183 is_int(subwin_last.type, TICKIT_KEYEV_TEXT, "subwin_last.type for C");
184 is_str(subwin_last.str, "C", "subwin_last.str for C");
185
186 is_int(win_last.type, TICKIT_KEYEV_TEXT, "win_last.type for C");
187 is_str(win_last.str, "C", "win_last.str for C");
188
189 tickit_window_unbind_event_id(subwin, sub_key_bind_id);
190 tickit_window_unbind_event_id(subwin, sub_mouse_bind_id);
191 }
192
193 tickit_window_unbind_event_id(win, key_bind_id);
194 tickit_window_unbind_event_id(win, mouse_bind_id);
195
196 // Event ordering
197 {
198 TickitWindow *otherwin = tickit_window_new(root, (TickitRect){10, 10, 4, 20}, 0);
199 tickit_window_flush(root);
200
201 int bind_ids[] = {
202 tickit_window_bind_event(win, TICKIT_WINDOW_ON_KEY, 0, &on_event_push, "win"),
203 tickit_window_bind_event(subwin, TICKIT_WINDOW_ON_KEY, 0, &on_event_push, "subwin"),
204 tickit_window_bind_event(otherwin, TICKIT_WINDOW_ON_KEY, 0, &on_event_push, "otherwin"),
205 };
206
207 press_key(TICKIT_KEYEV_TEXT, "D", 0);
208
209 is_int(next_idx, 3, "press_key pushes 3 strings for D");
210 is_str(ids[0], "subwin", "ids[0] for D");
211 is_str(ids[1], "win", "ids[1] for D");
212 is_str(ids[2], "otherwin", "ids[2] for D");
213
214 tickit_window_hide(subwin);
215
216 next_idx = 0;
217
218 press_key(TICKIT_KEYEV_TEXT, "E", 0);
219
220 is_int(next_idx, 2, "press_key pushes 2 strings for E");
221 is_str(ids[0], "win", "ids[0] for E");
222 is_str(ids[1], "otherwin", "ids[1] for E");
223
224 tickit_window_unref(otherwin);
225 tickit_window_flush(root);
226
227 tickit_window_unbind_event_id(win, bind_ids[0]);
228 tickit_window_unbind_event_id(subwin, bind_ids[1]);
229 }
230
231 tickit_window_unref(subwin);
232
233 // Windows created in input events handlers don't receive events
234 // child windows
235 {
236 int id = tickit_window_bind_event(win, TICKIT_WINDOW_ON_MOUSE, 0, &win_on_mouse_child, NULL);
237
238 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 3, 10, 0);
239
240 ok(!!childwin, "child window created");
241 is_int(childmouse, 0, "child window has not yet received a mouse event");
242
243 tickit_window_flush(root);
244
245 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 3, 10, 0);
246
247 is_int(childmouse, 1, "child window has now received an event after flush");
248
249 tickit_window_unbind_event_id(win, id);
250 tickit_window_unref(childwin);
251 tickit_window_flush(root);
252 }
253
254 // sibling windows
255 {
256 int id = tickit_window_bind_event(win, TICKIT_WINDOW_ON_MOUSE, 0, &win_on_mouse_sibling, NULL);
257
258 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 3, 10, 0);
259
260 ok(!!siblingwin, "sibling window created");
261 is_int(siblingmouse, 0, "sibling window has not yet received a mouse event");
262
263 tickit_window_flush(root);
264
265 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 3, 10, 0);
266
267 is_int(siblingmouse, 1, "sibling window has now received an event after flush");
268
269 tickit_window_unbind_event_id(win, id);
270 tickit_window_unref(siblingwin);
271 tickit_window_flush(root);
272 }
273
274 // STEAL_INPUT
275 {
276 TickitWindow *thief = tickit_window_new(root, (TickitRect){2, 5, 3, 3},
277 TICKIT_WINDOW_STEAL_INPUT);
278
279 struct LastEvent thief_last = { .ret = 1 };
280 tickit_window_bind_event(thief, TICKIT_WINDOW_ON_KEY, 0, &on_key_event_capture, &thief_last);
281 tickit_window_bind_event(thief, TICKIT_WINDOW_ON_MOUSE, 0, &on_mouse_event_capture, &thief_last);
282
283 ok(tickit_window_is_steal_input(thief), "tickit_window_is_steal_input() returns true");
284
285 press_key(TICKIT_KEYEV_TEXT, "D", 0);
286
287 is_int(thief_last.type, TICKIT_KEYEV_TEXT, "thief_last.type for D");
288 is_str(thief_last.str, "D", "thief_last.str for D");
289
290 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 1, 1, 0);
291
292 is_int(thief_last.type, TICKIT_MOUSEEV_PRESS, "thief_last.type for press 1@1,1");
293 is_int(thief_last.line, -1, "thief_last.line for press 1@1,1");
294 is_int(thief_last.col, -4, "thief_last.col for press 1@1,1");
295
296 thief_last.type = 0;
297 win_last.type = 0;
298
299 tickit_window_setctl_int(thief, TICKIT_WINCTL_STEAL_INPUT, false);
300 ok(!tickit_window_is_steal_input(thief), "tickit_window_is_steal_input() returns false");
301
302 press_mouse(TICKIT_MOUSEEV_PRESS, 1, 1, 1, 0);
303
304 is_int(thief_last.type, 0, "thief does not see event after disabling STEAL_INPUT");
305
306 tickit_window_unref(thief);
307 }
308
309 tickit_window_unref(win);
310 tickit_window_unref(root);
311 tickit_term_unref(tt);
312
313 return exit_status();
314 }
315