1 module unde.keybar.events;
2 
3 import unde.global_state;
4 import unde.lib;
5 import unde.tick;
6 import unde.keybar.lib;
7 
8 import derelict.sdl2.sdl;
9 
10 import std.stdio;
11 import std..string;
12 import std.math;
13 import std.conv;
14 import std.range.primitives;
15 
16 version(Windows)
17 {
18 import berkeleydb.all: ssize_t;
19 }
20 
21 int process_modifiers_down(GlobalState gs, int scancode)
22 {
23     int result = 0;
24     switch(scancode)
25     {
26         case SDL_SCANCODE_LCTRL:
27                 gs.modifiers |= Modifiers.Left_Ctrl;
28                 break;
29         case SDL_SCANCODE_RCTRL:
30                 gs.modifiers |= Modifiers.Right_Ctrl;
31                 break;
32         case SDL_SCANCODE_LSHIFT:
33                 gs.modifiers |= Modifiers.Left_Shift;
34                 if (SDL_GetTicks() - gs.keybar.last_shift < DOUBLE_DELAY)
35                 {
36                     result = 1;
37                     gs.keybar.last_shift = 0;
38                 }
39                 else
40                     gs.keybar.last_shift = SDL_GetTicks();
41                 break;
42         case SDL_SCANCODE_RSHIFT:
43                 gs.modifiers |= Modifiers.Right_Shift;
44                 if (SDL_GetTicks() - gs.keybar.last_shift < DOUBLE_DELAY)
45                 {
46                     result = 1;
47                     gs.keybar.last_shift = 0;
48                 }
49                 else
50                     gs.keybar.last_shift = SDL_GetTicks();
51                 break;
52         case SDL_SCANCODE_LALT:
53                 gs.modifiers |= Modifiers.Left_Alt;
54                 break;
55         case SDL_SCANCODE_RALT:
56                 gs.modifiers |= Modifiers.Right_Alt;
57                 break;
58         case SDL_SCANCODE_CAPSLOCK:
59                 gs.modifiers |= Modifiers.CapsLock;
60                 break;
61         case SDL_SCANCODE_LGUI:
62                 gs.modifiers |= Modifiers.Left_Win;
63                 break;
64         case SDL_SCANCODE_RGUI:
65                 gs.modifiers |= Modifiers.Right_Win;
66                 break;
67         case SDL_SCANCODE_SPACE:
68                 gs.modifiers |= Modifiers.Space;
69                 break;
70         case SDL_SCANCODE_APPLICATION:
71                 gs.modifiers |= Modifiers.Menu;
72                 break;
73         case SDL_SCANCODE_SCROLLLOCK:
74                 gs.modifiers |= Modifiers.ScrollLock;
75                 break;
76         default:
77                 break;
78     }
79 
80     if ((gs.modifiers & gs.keybar.changer) == gs.keybar.changer)
81     {
82         if (SDL_GetTicks() - gs.keybar.last_change < DOUBLE_DELAY)
83         {
84             result = 2;
85             gs.keybar.last_change = 0;
86         }
87         else
88         {
89             gs.keybar.mode++;
90             if (gs.keybar.mode >= gs.keybar.layout_modes.length)
91                 gs.keybar.mode = 0;
92             gs.keybar.last_change = SDL_GetTicks();
93         }
94     }
95 
96     update_letters(gs);
97     return result;
98 }
99 
100 void process_modifiers_up(GlobalState gs, int scancode)
101 {
102     switch(scancode)
103     {
104         case SDL_SCANCODE_LCTRL:
105             gs.modifiers &= ~Modifiers.Left_Ctrl;
106             break;
107         case SDL_SCANCODE_RCTRL:
108             gs.modifiers &= ~Modifiers.Right_Ctrl;
109             break;
110         case SDL_SCANCODE_LSHIFT:
111             gs.modifiers &= ~Modifiers.Left_Shift;
112             break;
113         case SDL_SCANCODE_RSHIFT:
114             gs.modifiers &= ~Modifiers.Right_Shift;
115             break;
116         case SDL_SCANCODE_LALT:
117             gs.modifiers &= ~Modifiers.Left_Alt;
118             break;
119         case SDL_SCANCODE_RALT:
120             gs.modifiers &= ~Modifiers.Right_Alt;
121             break;
122         case SDL_SCANCODE_CAPSLOCK:
123             gs.modifiers &= ~Modifiers.CapsLock;
124             break;
125         case SDL_SCANCODE_LGUI:
126             gs.modifiers &= ~Modifiers.Left_Win;
127             break;
128         case SDL_SCANCODE_RGUI:
129             gs.modifiers &= ~Modifiers.Right_Win;
130             break;
131         case SDL_SCANCODE_SPACE:
132             gs.modifiers &= ~Modifiers.Space;
133             break;
134         case SDL_SCANCODE_APPLICATION:
135             gs.modifiers &= ~Modifiers.Menu;
136             break;
137         case SDL_SCANCODE_SCROLLLOCK:
138             gs.modifiers &= ~Modifiers.ScrollLock;
139             break;
140         default:
141             break;
142     }
143 }
144 
145 void process_event(GlobalState gs, ref SDL_Event event, KeyHandler *kh)
146 {
147     switch( event.type )
148     {
149         case SDL_KEYDOWN:
150             int res = process_modifiers_down(gs, event.key.keysym.scancode);
151 
152             with(gs.keybar)
153             {
154                 if (input_mode && !kh)
155                 {
156                     ButtonPos* buttonpos = event.key.keysym.scancode in buttonpos_by_scan;
157                     if (buttonpos || res)
158                     {
159                         string chr;
160                         if (res)
161                            chr = "" ~ char.init ~ res.to!string();
162                         else if (buttonpos)
163                            chr = (*letters)[buttonpos.i][buttonpos.pos];
164                         if (chr == "Spc")
165                             chr = " ";
166                         if (chr.walkLength == 1 && "↑←↓→".indexOf(chr) < 0 || res)
167                         {
168                             gs.keybar.last_change = 0;
169                             gs.keybar.last_shift = 0;
170                             SDL_Event sevent;
171                             sevent.type = SDL_TEXTINPUT;
172                             sevent.text.text = to_char_array_z!32(chr);
173                             unde.tick.process_event(gs, sevent);
174                         }
175                     }
176                 }
177             }
178             break;
179         case SDL_KEYUP:
180             process_modifiers_up(gs, event.key.keysym.scancode);
181             break;
182 
183         case SDL_MOUSEMOTION:
184             gs.mouse_screen_x = event.motion.x;
185             gs.mouse_screen_y = event.motion.y;
186             gs.moved_while_click++;
187             break;
188             
189         case SDL_MOUSEBUTTONDOWN:
190             ssize_t i = -1;
191             switch (event.button.button)
192             {
193                 case SDL_BUTTON_LEFT:
194                     gs.mouse_buttons |= unDE_MouseButtons.Left;
195                     i = 0;
196                     break;
197                 case SDL_BUTTON_RIGHT:
198                     gs.mouse_buttons |= unDE_MouseButtons.Right;
199                     i = 1;
200                     break;
201                 case SDL_BUTTON_MIDDLE:
202                     gs.mouse_buttons |= unDE_MouseButtons.Middle;
203                     i = 2;
204                     break;
205                 default:
206                     break;
207             }
208 
209             if (i >= 0)
210             {
211                 gs.moved_while_click = 0;
212                 with(gs.keybar)
213                 {
214                     if (pos >= 0)
215                     {
216                         //ushort omodifiers = gs.modifiers;
217                         process_modifiers_down(gs, (*scans_cur)[i][pos]);
218                         /*if (omodifiers == gs.modifiers)
219                             gs.last_mouse_down = 0;
220                         else
221                             gs.last_mouse_down = SDL_GetTicks();*/
222                         KeyHandler* keyhandler = scans[i][pos] in gs.keybar.handlers_down;
223                         if (keyhandler)
224                         {
225                             keyhandler.handler(gs);
226                         }
227                         else if (input_mode)
228                         {
229                             string chr = (*letters)[i][pos];
230                             if (chr == "Spc")
231                                 chr = " ";
232                             if (chr.walkLength == 1 && "↑←↓→".indexOf(chr) < 0)
233                             {
234                                 SDL_Event sevent;
235                                 sevent.type = SDL_TEXTINPUT;
236                                 sevent.text.text = to_char_array_z!32(chr);
237                                 unde.tick.process_event(gs, sevent);
238                             }
239                         }
240                     }
241                 }
242             }
243 
244             break;
245             
246         case SDL_MOUSEBUTTONUP:
247 
248             ssize_t i = -1;
249             long *last_click;
250             switch (event.button.button)
251             {
252                 case SDL_BUTTON_LEFT:
253                     gs.mouse_buttons &= ~unDE_MouseButtons.Left;
254                     i = 0;
255                     last_click = &gs.last_left_click;
256                     break;
257                 case SDL_BUTTON_RIGHT:
258                     gs.mouse_buttons &= ~unDE_MouseButtons.Right;
259                     i = 1;
260                     last_click = &gs.last_right_click;
261                     break;
262                 case SDL_BUTTON_MIDDLE:
263                     gs.mouse_buttons &= ~unDE_MouseButtons.Middle;
264                     i = 2;
265                     last_click = &gs.last_middle_click;
266                     break;
267                 default:
268                     break;
269             }
270 
271             if ( i >= 0 )
272             {
273                 if (!gs.moved_while_click)
274                 {
275                     with(gs.keybar)
276                     {
277                         if (pos >= 0)
278                         {
279                             //if (SDL_GetTicks() - gs.last_mouse_down > DOUBLE_DELAY/2)
280                                 process_modifiers_up(gs, (*scans_cur)[i][pos]);
281 
282                             KeyHandler* keyhandler;
283                             if (SDL_GetTicks() - *last_click < DOUBLE_DELAY)
284                                 keyhandler = scans[i][pos] in gs.keybar.handlers_double;
285                             if (keyhandler)
286                                 keyhandler.handler(gs);
287                             keyhandler = scans[i][pos] in gs.keybar.handlers;
288                             if (keyhandler)
289                                 keyhandler.handler(gs);
290                             *last_click = SDL_GetTicks();
291                         }
292                     }
293                 }
294             }
295 
296             break;
297 
298         case SDL_MOUSEWHEEL:
299             break;
300             
301         case SDL_QUIT:
302             /* Do something event.quit */
303             gs.finish=true;
304             break;
305             
306         default:
307             //writeln("Ignored event: "~to!string(event.type));
308             break;
309     }
310 }