1 
2 /**
3  * @file lv_keyboard.c
4  *
5  */
6 
7 /*********************
8  *      INCLUDES
9  *********************/
10 #include "lv_keyboard_private.h"
11 #include "../../core/lv_obj_class_private.h"
12 #if LV_USE_KEYBOARD
13 
14 #include "../textarea/lv_textarea.h"
15 #include "../../misc/lv_assert.h"
16 #include "../../stdlib/lv_string.h"
17 
18 /*********************
19  *      DEFINES
20  *********************/
21 #define MY_CLASS (&lv_keyboard_class)
22 #define LV_KB_BTN(width) LV_BUTTONMATRIX_CTRL_POPOVER | width
23 
24 /**********************
25  *      TYPEDEFS
26  **********************/
27 
28 /**********************
29  *  STATIC PROTOTYPES
30  **********************/
31 static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
32 
33 static void lv_keyboard_update_map(lv_obj_t * obj);
34 
35 static void lv_keyboard_update_ctrl_map(lv_obj_t * obj);
36 
37 /**********************
38  *  STATIC VARIABLES
39  **********************/
40 #if LV_USE_OBJ_PROPERTY
41 static const lv_property_ops_t properties[] = {
42     {
43         .id = LV_PROPERTY_KEYBOARD_TEXTAREA,
44         .setter = lv_keyboard_set_textarea,
45         .getter = lv_keyboard_get_textarea,
46     },
47     {
48         .id = LV_PROPERTY_KEYBOARD_MODE,
49         .setter = lv_keyboard_set_mode,
50         .getter = lv_keyboard_get_mode,
51     },
52     {
53         .id = LV_PROPERTY_KEYBOARD_POPOVERS,
54         .setter = lv_keyboard_set_popovers,
55         .getter = lv_keyboard_get_popovers,
56     },
57     {
58         .id = LV_PROPERTY_KEYBOARD_SELECTED_BUTTON,
59         .setter = lv_buttonmatrix_set_selected_button,
60         .getter = lv_keyboard_get_selected_button,
61     },
62 };
63 #endif
64 
65 const lv_obj_class_t lv_keyboard_class = {
66     .constructor_cb = lv_keyboard_constructor,
67     .width_def = LV_PCT(100),
68     .height_def = LV_PCT(50),
69     .instance_size = sizeof(lv_keyboard_t),
70     .editable = 1,
71     .base_class = &lv_buttonmatrix_class,
72     .name = "keyboard",
73 #if LV_USE_OBJ_PROPERTY
74     .prop_index_start = LV_PROPERTY_KEYBOARD_START,
75     .prop_index_end = LV_PROPERTY_KEYBOARD_END,
76     .properties = properties,
77     .properties_count = sizeof(properties) / sizeof(properties[0]),
78 
79 #if LV_USE_OBJ_PROPERTY_NAME
80     .property_names = lv_keyboard_property_names,
81     .names_count = sizeof(lv_keyboard_property_names) / sizeof(lv_property_name_t),
82 #endif
83 
84 #endif
85 };
86 
87 static const char * const default_kb_map_lc[] = {"1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", LV_SYMBOL_BACKSPACE, "\n",
88                                                  "ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_NEW_LINE, "\n",
89                                                  "_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", "\n",
90                                                  LV_SYMBOL_KEYBOARD,
91 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
92                                                  "أب",
93 #endif
94                                                  LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
95                                                 };
96 
97 static const lv_buttonmatrix_ctrl_t default_kb_ctrl_lc_map[] = {
98     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BUTTONMATRIX_CTRL_CHECKED | 7,
99     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BUTTONMATRIX_CTRL_CHECKED | 7,
100     LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1),
101     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
102 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
103     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
104 #endif
105     LV_BUTTONMATRIX_CTRL_CHECKED | 2, 6, LV_BUTTONMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2
106 };
107 
108 static const char * const default_kb_map_uc[] = {"1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", LV_SYMBOL_BACKSPACE, "\n",
109                                                  "abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", LV_SYMBOL_NEW_LINE, "\n",
110                                                  "_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", "\n",
111                                                  LV_SYMBOL_CLOSE,
112 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
113                                                  "أب",
114 #endif
115                                                  LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
116                                                 };
117 
118 static const lv_buttonmatrix_ctrl_t default_kb_ctrl_uc_map[] = {
119     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 5, LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_KB_BTN(4), LV_BUTTONMATRIX_CTRL_CHECKED | 7,
120     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 6, LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_KB_BTN(3), LV_BUTTONMATRIX_CTRL_CHECKED | 7,
121     LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | LV_KB_BTN(1),
122     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
123 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
124     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
125 #endif
126     LV_BUTTONMATRIX_CTRL_CHECKED | 2, 6, LV_BUTTONMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2
127 };
128 
129 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
130 static const char * const default_kb_map_ar[] = {
131     "1#", "ض", "ص", "ث", "ق", "ف", "غ", "ع", "ه", "خ", "ح", "ج", "\n",
132     "ش", "س", "ي", "ب", "ل", "ا", "ت", "ن", "م", "ك", "ط", LV_SYMBOL_BACKSPACE, "\n",
133     "ذ", "ء", "ؤ", "ر", "ى", "ة", "و", "ز", "ظ", "د", "ز", "ظ", "د", "\n",
134     LV_SYMBOL_CLOSE, "abc", LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_NEW_LINE, LV_SYMBOL_OK, ""
135 };
136 
137 static const lv_buttonmatrix_ctrl_t default_kb_ctrl_ar_map[] = {
138     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
139     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7,
140     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
141     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, 2, 6, 2, 3, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2
142 };
143 #endif
144 
145 static const char * const default_kb_map_spec[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n",
146                                                    "abc", "+", "&", "/", "*", "=", "%", "!", "?", "#", "<", ">", "\n",
147                                                    "\\",  "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", "\n",
148                                                    LV_SYMBOL_KEYBOARD,
149 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
150                                                    "أب",
151 #endif
152                                                    LV_SYMBOL_LEFT, " ", LV_SYMBOL_RIGHT, LV_SYMBOL_OK, ""
153                                                   };
154 
155 static const lv_buttonmatrix_ctrl_t default_kb_ctrl_spec_map[] = {
156     LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_BUTTONMATRIX_CTRL_CHECKED | 2,
157     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2, LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1),
158     LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1), LV_KB_BTN(1),
159     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
160 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
161     LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
162 #endif
163     LV_BUTTONMATRIX_CTRL_CHECKED | 2, 6, LV_BUTTONMATRIX_CTRL_CHECKED | 2, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2
164 };
165 
166 static const char * const default_kb_map_num[] = {"1", "2", "3", LV_SYMBOL_KEYBOARD, "\n",
167                                                   "4", "5", "6", LV_SYMBOL_OK, "\n",
168                                                   "7", "8", "9", LV_SYMBOL_BACKSPACE, "\n",
169                                                   "+/-", "0", ".", LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT, ""
170                                                  };
171 
172 static const lv_buttonmatrix_ctrl_t default_kb_ctrl_num_map[] = {
173     1, 1, 1, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
174     1, 1, 1, LV_KEYBOARD_CTRL_BUTTON_FLAGS | 2,
175     1, 1, 1, 2,
176     1, 1, 1, 1, 1
177 };
178 
179 static const char * const * kb_map[10] = {
180     default_kb_map_lc,
181     default_kb_map_uc,
182     default_kb_map_spec,
183     default_kb_map_num,
184     default_kb_map_lc,
185     default_kb_map_lc,
186     default_kb_map_lc,
187     default_kb_map_lc,
188 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
189     default_kb_map_ar,
190 #endif
191     NULL
192 };
193 static const lv_buttonmatrix_ctrl_t * kb_ctrl[10] = {
194     default_kb_ctrl_lc_map,
195     default_kb_ctrl_uc_map,
196     default_kb_ctrl_spec_map,
197     default_kb_ctrl_num_map,
198     default_kb_ctrl_lc_map,
199     default_kb_ctrl_lc_map,
200     default_kb_ctrl_lc_map,
201     default_kb_ctrl_lc_map,
202 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
203     default_kb_ctrl_ar_map,
204 #endif
205     NULL
206 };
207 
208 /**********************
209  *      MACROS
210  **********************/
211 
212 /**********************
213  *   GLOBAL FUNCTIONS
214  **********************/
215 
lv_keyboard_create(lv_obj_t * parent)216 lv_obj_t * lv_keyboard_create(lv_obj_t * parent)
217 {
218     LV_LOG_INFO("begin");
219     lv_obj_t * obj = lv_obj_class_create_obj(&lv_keyboard_class, parent);
220     lv_obj_class_init_obj(obj);
221     return obj;
222 }
223 
224 /*=====================
225  * Setter functions
226  *====================*/
227 
lv_keyboard_set_textarea(lv_obj_t * obj,lv_obj_t * ta)228 void lv_keyboard_set_textarea(lv_obj_t * obj, lv_obj_t * ta)
229 {
230     if(ta) {
231         LV_ASSERT_OBJ(ta, &lv_textarea_class);
232     }
233 
234     LV_ASSERT_OBJ(obj, MY_CLASS);
235     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
236 
237     /*Hide the cursor of the old Text area if cursor management is enabled*/
238     if(keyboard->ta) {
239         lv_obj_remove_state(obj, LV_STATE_FOCUSED);
240     }
241 
242     keyboard->ta = ta;
243 
244     /*Show the cursor of the new Text area if cursor management is enabled*/
245     if(keyboard->ta) {
246         lv_obj_add_state(obj, LV_STATE_FOCUSED);
247     }
248 }
249 
lv_keyboard_set_mode(lv_obj_t * obj,lv_keyboard_mode_t mode)250 void lv_keyboard_set_mode(lv_obj_t * obj, lv_keyboard_mode_t mode)
251 {
252     LV_ASSERT_OBJ(obj, MY_CLASS);
253     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
254     if(keyboard->mode == mode) return;
255 
256     keyboard->mode = mode;
257     lv_keyboard_update_map(obj);
258 }
259 
lv_keyboard_set_popovers(lv_obj_t * obj,bool en)260 void lv_keyboard_set_popovers(lv_obj_t * obj, bool en)
261 {
262     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
263 
264     if(keyboard->popovers == en) {
265         return;
266     }
267 
268     keyboard->popovers = en;
269     lv_keyboard_update_ctrl_map(obj);
270 }
271 
lv_keyboard_set_map(lv_obj_t * obj,lv_keyboard_mode_t mode,const char * const map[],const lv_buttonmatrix_ctrl_t ctrl_map[])272 void lv_keyboard_set_map(lv_obj_t * obj, lv_keyboard_mode_t mode, const char * const map[],
273                          const lv_buttonmatrix_ctrl_t ctrl_map[])
274 {
275     LV_ASSERT_OBJ(obj, MY_CLASS);
276     kb_map[mode] = map;
277     kb_ctrl[mode] = ctrl_map;
278     lv_keyboard_update_map(obj);
279 }
280 
281 /*=====================
282  * Getter functions
283  *====================*/
284 
lv_keyboard_get_textarea(const lv_obj_t * obj)285 lv_obj_t * lv_keyboard_get_textarea(const lv_obj_t * obj)
286 {
287     LV_ASSERT_OBJ(obj, MY_CLASS);
288     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
289     return keyboard->ta;
290 }
291 
lv_keyboard_get_mode(const lv_obj_t * obj)292 lv_keyboard_mode_t lv_keyboard_get_mode(const lv_obj_t * obj)
293 {
294     LV_ASSERT_OBJ(obj, MY_CLASS);
295     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
296     return keyboard->mode;
297 }
298 
lv_keyboard_get_popovers(const lv_obj_t * obj)299 bool lv_keyboard_get_popovers(const lv_obj_t * obj)
300 {
301     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
302     return keyboard->popovers;
303 }
304 
305 /*=====================
306  * Other functions
307  *====================*/
308 
lv_keyboard_def_event_cb(lv_event_t * e)309 void lv_keyboard_def_event_cb(lv_event_t * e)
310 {
311     lv_obj_t * obj = lv_event_get_current_target(e);
312 
313     LV_ASSERT_OBJ(obj, MY_CLASS);
314     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
315     uint32_t btn_id = lv_buttonmatrix_get_selected_button(obj);
316     if(btn_id == LV_BUTTONMATRIX_BUTTON_NONE) return;
317 
318     const char * txt = lv_buttonmatrix_get_button_text(obj, btn_id);
319     if(txt == NULL) return;
320 
321     if(lv_strcmp(txt, "abc") == 0) {
322         keyboard->mode = LV_KEYBOARD_MODE_TEXT_LOWER;
323         lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_LOWER]);
324         lv_keyboard_update_ctrl_map(obj);
325         return;
326     }
327 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
328     else if(lv_strcmp(txt, "أب") == 0) {
329         keyboard->mode = LV_KEYBOARD_MODE_TEXT_ARABIC;
330         lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_ARABIC]);
331         lv_keyboard_update_ctrl_map(obj);
332         return;
333     }
334 #endif
335     else if(lv_strcmp(txt, "ABC") == 0) {
336         keyboard->mode = LV_KEYBOARD_MODE_TEXT_UPPER;
337         lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_TEXT_UPPER]);
338         lv_keyboard_update_ctrl_map(obj);
339         return;
340     }
341     else if(lv_strcmp(txt, "1#") == 0) {
342         keyboard->mode = LV_KEYBOARD_MODE_SPECIAL;
343         lv_buttonmatrix_set_map(obj, kb_map[LV_KEYBOARD_MODE_SPECIAL]);
344         lv_keyboard_update_ctrl_map(obj);
345         return;
346     }
347     else if(lv_strcmp(txt, LV_SYMBOL_CLOSE) == 0 || lv_strcmp(txt, LV_SYMBOL_KEYBOARD) == 0) {
348         lv_result_t res = lv_obj_send_event(obj, LV_EVENT_CANCEL, NULL);
349         if(res != LV_RESULT_OK) return;
350 
351         if(keyboard->ta) {
352             res = lv_obj_send_event(keyboard->ta, LV_EVENT_CANCEL, NULL);
353             if(res != LV_RESULT_OK) return;
354         }
355         return;
356     }
357     else if(lv_strcmp(txt, LV_SYMBOL_OK) == 0) {
358         lv_result_t res = lv_obj_send_event(obj, LV_EVENT_READY, NULL);
359         if(res != LV_RESULT_OK) return;
360 
361         if(keyboard->ta) {
362             res = lv_obj_send_event(keyboard->ta, LV_EVENT_READY, NULL);
363             if(res != LV_RESULT_OK) return;
364         }
365         return;
366     }
367 
368     /*Add the characters to the text area if set*/
369     if(keyboard->ta == NULL) return;
370 
371     if(lv_strcmp(txt, "Enter") == 0 || lv_strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) {
372         lv_textarea_add_char(keyboard->ta, '\n');
373         if(lv_textarea_get_one_line(keyboard->ta)) {
374             lv_result_t res = lv_obj_send_event(keyboard->ta, LV_EVENT_READY, NULL);
375             if(res != LV_RESULT_OK) return;
376         }
377     }
378     else if(lv_strcmp(txt, LV_SYMBOL_LEFT) == 0) {
379         lv_textarea_cursor_left(keyboard->ta);
380     }
381     else if(lv_strcmp(txt, LV_SYMBOL_RIGHT) == 0) {
382         lv_textarea_cursor_right(keyboard->ta);
383     }
384     else if(lv_strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) {
385         lv_textarea_delete_char(keyboard->ta);
386     }
387     else if(lv_strcmp(txt, "+/-") == 0) {
388         uint32_t cur        = lv_textarea_get_cursor_pos(keyboard->ta);
389         const char * ta_txt = lv_textarea_get_text(keyboard->ta);
390         if(ta_txt[0] == '-') {
391             lv_textarea_set_cursor_pos(keyboard->ta, 1);
392             lv_textarea_delete_char(keyboard->ta);
393             lv_textarea_add_char(keyboard->ta, '+');
394             lv_textarea_set_cursor_pos(keyboard->ta, cur);
395         }
396         else if(ta_txt[0] == '+') {
397             lv_textarea_set_cursor_pos(keyboard->ta, 1);
398             lv_textarea_delete_char(keyboard->ta);
399             lv_textarea_add_char(keyboard->ta, '-');
400             lv_textarea_set_cursor_pos(keyboard->ta, cur);
401         }
402         else {
403             lv_textarea_set_cursor_pos(keyboard->ta, 0);
404             lv_textarea_add_char(keyboard->ta, '-');
405             lv_textarea_set_cursor_pos(keyboard->ta, cur + 1);
406         }
407     }
408     else {
409         lv_textarea_add_text(keyboard->ta, txt);
410     }
411 }
412 
lv_keyboard_get_map_array(const lv_obj_t * kb)413 const char * const * lv_keyboard_get_map_array(const lv_obj_t * kb)
414 {
415     return lv_buttonmatrix_get_map(kb);
416 }
417 
lv_keyboard_get_selected_button(const lv_obj_t * obj)418 uint32_t lv_keyboard_get_selected_button(const lv_obj_t * obj)
419 {
420     return lv_buttonmatrix_get_selected_button(obj);
421 }
422 
lv_keyboard_get_button_text(const lv_obj_t * obj,uint32_t btn_id)423 const char * lv_keyboard_get_button_text(const lv_obj_t * obj, uint32_t btn_id)
424 {
425     return lv_buttonmatrix_get_button_text(obj, btn_id);
426 }
427 
428 /**********************
429  *   STATIC FUNCTIONS
430  **********************/
431 
lv_keyboard_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)432 static void lv_keyboard_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
433 {
434     LV_UNUSED(class_p);
435     lv_obj_remove_flag(obj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
436 
437     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
438     keyboard->ta         = NULL;
439     keyboard->mode       = LV_KEYBOARD_MODE_TEXT_LOWER;
440     keyboard->popovers   = 0;
441 
442     lv_obj_align(obj, LV_ALIGN_BOTTOM_MID, 0, 0);
443     lv_obj_add_event_cb(obj, lv_keyboard_def_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
444     lv_obj_set_style_base_dir(obj, LV_BASE_DIR_LTR, 0);
445 
446     lv_keyboard_update_map(obj);
447 }
448 
449 /**
450  * Update the key and control map for the current mode
451  * @param obj pointer to a keyboard object
452  */
lv_keyboard_update_map(lv_obj_t * obj)453 static void lv_keyboard_update_map(lv_obj_t * obj)
454 {
455     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
456     lv_buttonmatrix_set_map(obj, kb_map[keyboard->mode]);
457     lv_keyboard_update_ctrl_map(obj);
458 }
459 
460 /**
461  * Update the control map for the current mode
462  * @param obj pointer to a keyboard object
463  */
lv_keyboard_update_ctrl_map(lv_obj_t * obj)464 static void lv_keyboard_update_ctrl_map(lv_obj_t * obj)
465 {
466     lv_keyboard_t * keyboard = (lv_keyboard_t *)obj;
467 
468     if(keyboard->popovers) {
469         /*Apply the current control map (already includes LV_BUTTONMATRIX_CTRL_POPOVER flags)*/
470         lv_buttonmatrix_set_ctrl_map(obj, kb_ctrl[keyboard->mode]);
471     }
472     else {
473         /*Make a copy of the current control map*/
474         lv_buttonmatrix_t * btnm = (lv_buttonmatrix_t *)obj;
475         lv_buttonmatrix_ctrl_t * ctrl_map = lv_malloc(btnm->btn_cnt * sizeof(lv_buttonmatrix_ctrl_t));
476         lv_memcpy(ctrl_map, kb_ctrl[keyboard->mode], sizeof(lv_buttonmatrix_ctrl_t) * btnm->btn_cnt);
477 
478         /*Remove all LV_BUTTONMATRIX_CTRL_POPOVER flags*/
479         uint32_t i;
480         for(i = 0; i < btnm->btn_cnt; i++) {
481             ctrl_map[i] &= (~LV_BUTTONMATRIX_CTRL_POPOVER);
482         }
483 
484         /*Apply new control map and clean up*/
485         lv_buttonmatrix_set_ctrl_map(obj, ctrl_map);
486         lv_free(ctrl_map);
487     }
488 }
489 
490 #endif  /*LV_USE_KEYBOARD*/
491