minigui添加键盘支持

2019-10-09  本文已影响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结点的自动挂载功能实现,暂时还没有思路,如果后面能够解决,作者会将实现方法记录下来供大家参考。

上一篇下一篇

猜你喜欢

热点阅读