美文网首页
minigui添加键盘支持

minigui添加键盘支持

作者: 幕枫楚雨 | 来源:发表于2019-10-09 14:29 被阅读0次

    本文主要介绍minigui中添加键盘支持功能

    一、介绍

    由于项目需求,要在minigui中添加键盘处理。

    不清楚minigui默认是否支持键盘,作者拿到的代码是改动过的,没有实现键盘功能。键盘的整个流程涉及到libminigui部分和minigui主应用部分,作者的理解中,libminigui类似于HAL的功能,minigui主应用则主要是调用libminigui库提供的功能,所以改动部分主要在libminigui中。

    二、libminigui库

    1.libminigui库中的主要流程分析

    InitGUI()  函数入口

    mg_InitLWEvent()  ->  mg_InitIAL()   注册键盘和光标处理函数

    SystemThreads()  ->  pthread_create (&__mg_parsor, NULL, EventLoop, &wait);

    EventLoop()  线程中循环查询键盘消息和光标消息

    EventLoop:

    kernel_GetLWEvent()

        ->  kernel_RefreshCursor()  ->  IAL_GetMouseButton() ->  __mg_cur_input->get_mouse_button  获取光标消息

        ->  IAL_UpdateKeyboard()  ->  IAL_GetKeyboardState()  获取键盘消息

    ParseEvent()  ->  QueueDeskMessage()  发送键盘和光标消息

    以上只是简单分析库的流程,关于查询键盘消息和光标消息的流程不做深入讨论,这里主要是介绍注册函数的实现。

    2.mg_InitIAL函数定义如下:

    int mg_InitIAL (void)

    {

    ...

    for (i = 0; i < NR_INPUTS; i++) {

            //printf("====================input test===================\n");

            if (strncmp (engine, inputs[i].id, LEN_ENGINE_NAME) == 0) {

                //printf("inputs[i].id: %s\n",inputs[i].id);

                __mg_cur_input = inputs + i;

                break;

            }

        }

    ...

    }

    在mg_InitIAL中,主要是检测输入引擎是否存在,并将存在inputs赋值给__mg_cur_input。

    3.inputs定义如下:

    static INPUT inputs [] =

    {

    ...

    #ifdef _MGIAL_TSLIB

        {"tslib", InitTSLibInput, TermTSLibInput},

    #endif

    ...

    };

    其中InitTSLibInput是输入引擎的初始化,TermTSLibInput是销毁函数。

    4.InitTSLibInput

    #define KBD_DEVICE "/dev/input/event1"

    static int keykoard_fd = -1;

    static XVFBKEYDATA kbd_data;

    static unsigned char kbd_state [NR_KEYS];

    static struct input_event kb_event;

    BOOL InitTSLibInput(INPUT* input, const char* mdev, const char* mtype)

    {

        const char* tsdevice;

        if ((tsdevice = getenv ("TSLIB_TSDEVICE")) == NULL) {

            tsdevice = mdev;

        }

        //printf("[kevin]: tsdevice:%s\n",tsdevice);

        if (tsdevice == NULL) {

            _MG_PRINTF ("IAL>TSLib: Please specify the ts device\n");

            return FALSE;

        }

        //printf("start InitTSLibInput!\n");

        ts = ts_open (tsdevice, 0);

        if (!ts) {

            _MG_PRINTF ("IAL>TSLib: can not open ts device\n");

            return FALSE;

        }

        if (ts_config (ts)) {

            _MG_PRINTF ("IAL>TSLib: can not config ts device\n");

            return FALSE;

        }

        keykoard_fd = open (KBD_DEVICE, O_RDONLY);

        if (keykoard_fd < 0 ) {

            _MG_PRINTF ("IAL>%s: Can not open button key!\n", __FILE__);

            return FALSE;

        }

        input->update_mouse = mouse_update;

        input->get_mouse_xy = mouse_getxy;

        input->set_mouse_xy = NULL;

        input->get_mouse_button = mouse_getbutton;

        input->set_mouse_range = NULL;

        input->update_keyboard = keyboard_update;

        input->get_keyboard_state = keyboard_get_state;

        input->set_leds = NULL;

        input->wait_event = wait_event;

        return TRUE;

    }

    ts是触摸屏相关的文件指针(即光标函数mouse相关部分),keykoard_fd是键盘的文件指针。与键盘有关的部分是后添加的内容,其余为之前就有的部分。

    其中主要添加了keyboard_update和keyboard_get_state的实现,以及在wait_event中加入键盘事件检测。

    5.keyboard_update和keyboard_get_state

    static int keyboard_update(void)

    {

        unsigned char scan_code;

        unsigned char nr_changed_keys = 0;       

        scan_code = kbd_data.key_code;

        kbd_state [scan_code] = kbd_data.key_state ? 1 : 0;

        nr_changed_keys = scan_code + 1;

        //printf("scan_code:%d, kbd_state:%d, nr_changed_keys:%d\n", scan_code, kbd_state[scan_code], nr_changed_keys);

        return nr_changed_keys;

    }

    static const char * keyboard_get_state (void)

    {

        return (char*)kbd_state;

    }

    主要功能是上报键值和键盘的按键状态。

    6.wait_event

    static int wait_event (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except, struct timeval *timeout)

    {

    ...

        if((which & IAL_KEYEVENT) && keykoard_fd >= 0)

        {

            FD_SET (keykoard_fd, in); 

        }

    #ifndef _MGRM_THREADS

        e = select (maxfd + 1, in, out, except, timeout);

    #else

        e = select (FD_SETSIZE, in, out, except, timeout);

    #endif

        if (e > 0) {

            if (fd > 0 && FD_ISSET (fd, in)) {

                return IAL_MOUSEEVENT;

            }

            else if(keykoard_fd >= 0  && FD_ISSET (keykoard_fd, in) )

            {

                FD_CLR (keykoard_fd, in); 

                if(read (keykoard_fd, &kb_event, sizeof (struct input_event))>0)

                {

                    if(kb_event.type==EV_KEY) 

                        if(kb_event.value==0 || kb_event.value==1) 

                        { 

                            kbd_data.key_code = kb_event.code;

                            kbd_data.key_state = kb_event.value;

                            ret |= IAL_KEYEVENT; 

                            //printf("wait_event, key_code:%d, key_state:%d\n", kbd_data.key_code, kbd_data.key_state);

                        } 

                }

            }

        }

    ...

    }

    对键盘的相应操作主要是,read键值和状态,并把键值和状态赋值给全局变量,并由上面提到的keyboard_update和keyboard_get_state上报给处理函数。

    7.最后是TermTSLibInput

    void TermTSLibInput(void)

    {

        if (ts) {

            ts_close(ts);   

            ts = NULL;

        }

        if (keykoard_fd < 0) {

            close(keykoard_fd);   

            keykoard_fd = -1;

        }

    }

    作用是销毁文件指针。

    三、minigui主应用中

    static int DesktopPanelProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)

    {

    ...

    switch (message)

    {

    case MSG_KEYDOWN:

    printf ("MGS_KEYDOWN: key %d\n", LOWORD(wParam));

    break;

    case MSG_CHAR:

    printf ("MGS_CHAR: char %d\n", wParam);

    break;

    ...

    }

    return DefaultMainWinProc(hWnd, message, wParam, lParam);

    }

    在窗口的MainWindowProc中对MSG_KEYDOWN和MSG_CHAR消息进行相应的处理即可。

    四、总结

    值得注意的是,当插入键盘开机之后,键盘的结点是event0和event1,触摸屏的结点是event2,此时无论是键盘还是触摸屏都无效了(触摸屏open的结点是event0)。当先开机后插入键盘时,键盘的结点是event1和event2,触摸屏的结点是event0,此时键盘和触摸屏都能正常工作。

    关于event结点的自动挂载功能实现,暂时还没有思路,如果后面能够解决,作者会将实现方法记录下来供大家参考。

    相关文章

      网友评论

          本文标题:minigui添加键盘支持

          本文链接:https://www.haomeiwen.com/subject/aaahyctx.html