MiniGUI 体系结构之四 图形抽象层和输入抽象层及 Native Engine 的实现(一)


本文是 MiniGUI 体系结构系列文章的第四篇。图形抽象层(GAL)和输入抽象层(IAL)大大提高了 MiniGUI 的可移植性,并将底层图形设备和上层接口分离开来。这里将重点介绍 MiniGUI 的 GAL 和 IAL 接口,并以最新的 MiniGUI-Lite 版本为例,介绍基于 Linux FrameBuffer 的 Native 图形引擎的实现,以及特定嵌入式系统上输入引擎的实现。

1 引言

在 MiniGUI 0.3.xx 的开发中,我们引入了图形和输入抽象层(Graphics and Input Abstract Layer,GAL 和 IAL)的概念。抽象层的概念类似 Linux 内核虚拟文件系统的概念。它定义了一组不依赖于任何特殊硬件的抽象接口,所有顶层的图形操作和输入处理都建立在抽象接口之上。而用于实现这一抽象接口的底层代码称为“图形引擎”或“输入引擎”,类似操作系统中的驱动程序。这实际是一种面向对象的程序结构。利用 GAL 和 IAL,MiniGUI 可以在许多已有的图形函数库上运行,比如 SVGALib 和 LibGGI。并且可以非常方便地将 MiniGUI 移植到其他 POSIX 系统上,只需要根据我们的抽象层接口实现新的图形引擎即可。比如,在基于 Linux 的系统上,我们可以在 Linux FrameBuffer 驱动程序的基础上建立通用的 MiniGUI 图形引擎。实际上,包含在 MiniGUI 1.0.00 版本中的私有图形引擎(Native Engine)就是建立在 FrameBuffer 之上的图形引擎。一般而言,基于 Linux 的嵌入式系统均会提供 FrameBuffer 支持,这样私有图形引擎可以运行在一般的 PC 上,也可以运行在特定的嵌入式系统上。

相比图形来讲,将 MiniGUI 的底层输入与上层相隔显得更为重要。在基于 Linux 的嵌入式系统中,图形引擎可以通过 FrameBuffer 而获得,而输入设备的处理却没有统一的接口。在 PC 上,我们通常使用键盘和鼠标,而在嵌入式系统上,可能只有触摸屏和为数不多的几个键。在这种情况下,提供一个抽象的输入层,就显得格外重要。

本文将介绍 MiniGUI 的 GAL 和 IAL 接口,并介绍私有图形引擎和特定嵌入式系统下的输入引擎实现。

2 MiniGUI 的 GAL 和 IAL 定义

GAL 和 IAL 的结构是类似的,我们以 GAL 为例说明 MiniGUI GAL 和 IAL 抽象层的结构。

2.1 GAL 和图形引擎

参见图 1。系统维护一个已注册图形引擎数组,保存每个图形引擎数据结构的指针。系统利用一个指针保存当前使用的图形引擎。一般而言,系统中至少有两个图形引擎,一个是“哑”图形引擎,不进行任何实际的图形输出;一个是实际要使用的图形引擎,比如 LibGGI 或者 SVGALib,或者 Native Engine。每个图形引擎的数据结构定义了该图形引擎的一些信息,比如标识符、属性等,更重要的是,它实现了 GAL 所定义的各个接口,包括初始化和终止、图形上下文管理、画点处理函数、画线处理函数、矩形框填充函数、调色板函数等等。



图1 GAL 和图形引擎

如果在某个实际项目中所使用的图形硬件比较特殊,现有的图形引擎均不支持。这时,我们就可以安照 GAL 所定义的接口实现自己的图形引擎,并指定 MiniGUI 使用这种私有的图形引擎即可。这种软件技术实际就是面向对象多态性的具体体现。

利用 GAL 和 IAL,大大提高了 MiniGUI 的可移植性,并且使得程序的开发和调试变得更加容易。我们可以在 X Window 上开发和调试自己的 MiniGUI 程序,通过重新编译就可以让 MiniGUI 应用程序运行在特殊的嵌入式硬件平台上。

在代码实现上,MiniGUI 通过 GFX 数据结构来表示图形引擎,见清单 1。

                         清单 1   MiniGUI 中的图形引擎结构(src/include/gal.h)
        55 typedef struct tagGFX
        56 {
        57     char*   id;
        58
        59     // Initialization and termination
        60     BOOL    (*initgfx) (struct tagGFX* gfx);
        61     void    (*termgfx) (struct tagGFX* gfx);
        62
        63     // Phisical graphics context
        64     GAL_GC  phygc;
        65     int     bytes_per_phypixel;
        66     int     bits_per_phypixel;
        67     int     width_phygc;
        68     int     height_phygc;
        69     int     colors_phygc;
        70     BOOL    grayscale_screen;
        71
        72     // GC properties
        73     int     (*bytesperpixel) (GAL_GC gc);
        74     int     (*bitsperpixel) (GAL_GC gc);
        75     int     (*width) (GAL_GC gc);
        76     int     (*height) (GAL_GC gc);
        77     int     (*colors) (GAL_GC gc);
        78
        79     // Allocation and release of graphics context
        80     int     (*allocategc) (GAL_GC gc, int width, int height, int depth,
        81                 GAL_GC* newgc);
        82     void    (*freegc) (GAL_GC gc);
        83     void    (*setgc) (GAL_GC gc);
        84
        85     // Clipping of graphics context
        86     void    (*enableclipping) (GAL_GC gc);
        87     void    (*disableclipping) (GAL_GC gc);
        88     int     (*setclipping) (GAL_GC gc, int x1, int y1, int x2, int y2);
        89     int     (*getclipping) (GAL_GC gc, int* x1, int* y1, int* x2, int* y2);
        90
        91     // Background and foreground colors
        92     int     (*getbgcolor) (GAL_GC gc, gal_pixel* color);
        93     int     (*setbgcolor) (GAL_GC gc, gal_pixel color);
        94     int     (*getfgcolor) (GAL_GC gc, gal_pixel* color);
        95     int     (*setfgcolor) (GAL_GC gc, gal_pixel color);
        96
        97     // Convertion between gal_color and gal_pixel
        98     gal_pixel (*mapcolor) (GAL_GC gc, gal_color *color);
        99     int     (*unmappixel) (GAL_GC gc, gal_pixel pixel, gal_color* color);
        100     int     (*packcolors) (GAL_GC gc, void* buf, gal_color* colors, int len);
        101     int     (*unpackpixels) (GAL_GC gc, void* buf, gal_color* colors, int len);
        102
        103     // Palette operations
        104     int     (*getpalette) (GAL_GC gc, int s, int len, gal_color* cmap);
        105     int     (*setpalette) (GAL_GC gc, int s, int len, gal_color* cmap);
        106     int     (*setcolorfulpalette) (GAL_GC gc);
        107
        108     // Box operations
        109     size_t  (*boxsize) (GAL_GC gc, int w, int h);
        110     int     (*fillbox) (GAL_GC gc, int x, int y, int w, int h,
        111                 gal_pixel pixel);
        112     int     (*putbox) (GAL_GC gc, int x, int y, int w, int h, void* buf);
        113     int     (*getbox) (GAL_GC gc, int x, int y, int w, int h, void* buf);
        114     int     (*putboxmask) (GAL_GC gc, int x, int y, int w, int h, void* buf, gal_pixel cxx);
        115     int     (*putboxpart) (GAL_GC gc, int x, int y, int w, int h, int bw,
        116                 int bh, void* buf, int xo, int yo);
        117     int     (*putboxwithop) (GAL_GC gc, int x, int y, int w, int h,
        118                 void* buf, int raster_op);
        119     int     (*scalebox) (GAL_GC gc, int sw, int sh, void* srcbuf,
        120                 int dw, int dh, void* dstbuf);
        121
        122     int     (*copybox) (GAL_GC gc, int x, int y, int w, int h, int nx, int ny);
        123     int     (*crossblit) (GAL_GC src, int sx, int sy, int sw, int sh,
        124                 GAL_GC dst, int dx, int dy);
        125
        126     // Horizontal line operaions
        127     int     (*drawhline) (GAL_GC gc, int x, int y, int w, gal_pixel pixel);
        128     int     (*puthline)  (GAL_GC gc, int x, int y, int w, void* buf);
        129     int     (*gethline)  (GAL_GC gc, int x, int y, int w, void* buf);
        130
        131     // Vertical line operations
        132     int     (*drawvline) (GAL_GC gc, int x, int y, int h, gal_pixel pixel);
        133     int     (*putvline)  (GAL_GC gc, int x, int y, int h, void* buf);
        134     int     (*getvline)  (GAL_GC gc, int x, int y, int h, void* buf);
        135
        136     // Pixel operations
        137     int     (*drawpixel) (GAL_GC gc, int x, int y, gal_pixel pixel);
        138     int     (*putpixel) (GAL_GC gc, int x, int y, gal_pixel color);
        139     int     (*getpixel) (GAL_GC gc, int x, int y, gal_pixel* color);
        140
        141     // Other drawing
        142     int     (*circle) (GAL_GC gc, int x, int y, int r, gal_pixel pixel);
        143     int     (*line) (GAL_GC gc, int x1, int y1, int x2, int y2,
        144                 gal_pixel pixel);
        145     int     (*rectangle) (GAL_GC gc, int l, int t, int r, int b,
        146                 gal_pixel pixel);
        147
        148     // Simple Character output
        149     int     (*putchar) (GAL_GC gc, int x, int y, char c);
        150     int     (*putstr) (GAL_GC gc, int x, int y, const char* str);
        151     int     (*getcharsize) (GAL_GC gc, int* width, int* height);
        152     int     (*setputcharmode) (GAL_GC gc, int bkmode);
        153     int     (*setfontcolors) (GAL_GC gc,
        154                 gal_pixel fg, gal_pixel bg);
        155
        156     // Asynchronous mode support
        157     void (*flush) (GAL_GC gc);
        158     void (*flushregion) (GAL_GC gc, int x, int y, int w, int h);
        159
        160     // Panic
        161     void (*panic) (int exitcode);
        162
        163 } GFX;
        164
        165 extern GFX* cur_gfx;
        

系统启动之后,将根据配置寻找特定的图形引擎作为当前的图形引擎,并且对全局变量 cur_gfx 赋值。之后,当 MiniGUI 需要在屏幕上进行绘制之后,调用当前图形引擎的相应功能函数。比如,在画水平线时如下调用:

(*cur_gfx->drawhline) (gc, x, y, w, pixel);
        

为方便程序书写,我们还定义了如下 C 语言宏:

 167 #define PHYSICALGC              (cur_gfx->phygc)
        168 #define BYTESPERPHYPIXEL        (cur_gfx->bytes_per_phypixel)
        169 #define BITSPERPHYPIXEL         (cur_gfx->bits_per_phypixel)
        170 #define WIDTHOFPHYGC            (cur_gfx->width_phygc)
        171 #define HEIGHTOFPHYGC           (cur_gfx->height_phygc)
        172 #define COLORSOFPHYGC           (cur_gfx->colors_phygc)
        173 #define GRAYSCALESCREEN         (cur_gfx->grayscale_screen)
        174
        175 #define GAL_BytesPerPixel       (*cur_gfx->bytesperpixel)
        176 #define GAL_BitsPerPixel        (*cur_gfx->bitsperpixel)
        177 #define GAL_Width               (*cur_gfx->width)
        178 #define GAL_Height              (*cur_gfx->height)
        179 #define GAL_Colors              (*cur_gfx->colors)
        180
        181 #define GAL_InitGfx             (*cur_gfx->initgfx)
        182 #define GAL_TermGfx             (*cur_gfx->termgfx)
        183
        184 #define GAL_AllocateGC          (*cur_gfx->allocategc)
        185 #define GAL_FreeGC              (*cur_gfx->freegc)
        186
        ...
        198
        199 #define GAL_MapColor            (*cur_gfx->mapcolor)
        200 #define GAL_UnmapPixel          (*cur_gfx->unmappixel)
        201 #define GAL_PackColors          (*cur_gfx->packcolors)
        202 #define GAL_UnpackPixels        (*cur_gfx->unpackpixels)
        203
        ...
        208 #define GAL_BoxSize             (*cur_gfx->boxsize)
        209 #define GAL_FillBox             (*cur_gfx->fillbox)
        210 #define GAL_PutBox              (*cur_gfx->putbox)
        211 #define GAL_GetBox              (*cur_gfx->getbox)
        212 #define GAL_PutBoxMask          (*cur_gfx->putboxmask)
        213 #define GAL_PutBoxPart          (*cur_gfx->putboxpart)
        214 #define GAL_PubBoxWithOp        (*cur_gfx->putboxwithop)
        215 #define GAL_ScaleBox            (*cur_gfx->scalebox)
        ...
        224 #define GAL_DrawVLine           (*cur_gfx->drawvline)
        225 #define GAL_PutVLine            (*cur_gfx->putvline)
        226 #define GAL_GetVLine            (*cur_gfx->getvline)
        

这样,上述画线函数可以如下书写:

GAL_DrawVLine (gc, x, y, w, pixel);
        

显然,只要在系统初始化时能够根据设定对 cur_gfx 进行适当的赋值,MiniGUI 就能够在相应的图形引擎之上进行绘制。

对底层图形引擎的调用,主要集中在 MiniGUI 的 GDI 函数中。比如,要绘制一条直线,MiniGUI 的 LineTo 函数定义如清单 2 所示:

                           清单 2   LineTo 函数(src/gdi/draw-lite.c)
        255 void GUIAPI LineTo (HDC hdc, int x, int y)
        256 {
        257     PCLIPRECT pClipRect;
        258     PDC pdc;
        259     RECT rcOutput;
        260     int startx, starty;
        261
        262     pdc = dc_HDC2PDC(hdc);
        263
        264     if (dc_IsGeneralHDC(hdc)) {
        265         if (!dc_GenerateECRgn (pdc, FALSE)) {
        266             return;
        267         }
        268     }
        269
        270     // Transfer logical to device to screen here.
        271     startx = pdc->CurPenPos.x;
        272     starty = pdc->CurPenPos.y;
        273
        274     // Move the current pen pos.
        275     pdc->CurPenPos.x = x;
        276     pdc->CurPenPos.y = y;
        277
        278     coor_LP2SP(pdc, &x, &y);
        279     coor_LP2SP(pdc, &startx, &starty);
        280     rcOutput.left = startx - 1;
        281     rcOutput.top  = starty - 1;
        282     rcOutput.right = x + 1;
        283     rcOutput.bottom = y + 1;
        284     NormalizeRect(&rcOutput);
        285
        286     IntersectRect (&rcOutput, &rcOutput, &pdc->ecrgn.rcBound);
        287     if( !dc_IsMemHDC(hdc) ) ShowCursorForGDI(FALSE, &rcOutput);
        288
        289     // set graphics context.
        290     GAL_SetGC (pdc->gc);
        291     GAL_SetFgColor (pdc->gc, pdc->pencolor);
        292
        293     pClipRect = pdc->ecrgn.head;
        294     while(pClipRect)
        295     {
        296         if (DoesIntersect (&rcOutput, &pClipRect->rc)) {
        297             GAL_SetClipping (pdc->gc, pClipRect->rc.left, pClipRect->rc.top,
        298                     pClipRect->rc.right - 1, pClipRect->rc.bottom - 1);
        299
        300             if(starty == y) {
        301                 if (startx > x)
        302                     GAL_DrawHLine (pdc->gc, x, y, startx - x, pdc->pencolor);
        303                 else
        304                     GAL_DrawHLine (pdc->gc, startx, y, x - startx, pdc->pencolor);
        305             }
        306             else
        307                 GAL_Line (pdc->gc, startx, starty, x, y, pdc->pencolor);
        308         }
        309
        310         pClipRect = pClipRect->next;
        311     }
        312
        313     if (!dc_IsMemHDC (hdc)) ShowCursorForGDI (TRUE, &rcOutput);
        314 }
        

在 MiniGUI 的所有绘图函数中,要依次做如下几件事:

  1. 进行逻辑坐标到设备坐标的转换;
  2. 检查是否应该重新生成有效剪切域;
  3. 计算输出矩形,并判断是否隐藏鼠标;
  4. 由于底层引擎尚不支持剪切域,因此,对剪切域中的每个剪切矩形,调用底层绘图函数输出一次。

在上面的四个步骤当中,第 3 步和第 4 步实际可以放到底层引擎当中,从而能够大大提高 MiniGUI 的绘图效率。不过,这种性能上的提高,对块输出,比如填充矩形、输出位图来讲,并不是非常明显。在将来的底层图形引擎当中,我们将针对上述两点,进行较大的优化以提高图形输出效率。

2.2 IAL 和输入引擎

如前所属,MiniGUI IAL 结构和 GAL 结构类似。在代码实现上,MiniGUI 通过 INPUT数据结构来表示输入引擎,见清单 3。

                         清单 3   MiniGUI 中的输入引擎结构(src/include/ial.h)
        34 typedef struct tagINPUT
        35 {
        36     char*   id;
        37
        38     // Initialization and termination
        39     BOOL (*init_input) (struct tagINPUT *input, const char* mdev, const char* mtype);
        40     void (*term_input) (void);
        41
        42     // Mouse operations
        43     int  (*update_mouse) (void);
        44     int  (*get_mouse_x) (void);
        45     int  (*get_mouse_y) (void);
        46     void (*set_mouse_xy) (int x, int y);
        47     int  (*get_mouse_button) (void);
        48     void (*set_mouse_range) (int minx, int miny,int maxx,int maxy);
        49
        50     // Keyboard operations
        51     int  (*update_keyboard) (void);
        52     char* (*get_keyboard_state) (void);
        53         void (*suspend_keyboard) (void);
        54         void (*resume_keyboard) (void);
        55     void (*set_leds) (unsigned int leds);
        56
        57     // Event
        58 #ifdef _LITE_VERSION
        59     int (*wait_event) (int which, int maxfd, fd_set *in, fd_set *out, fd_set *except,
        60             struct timeval *timeout);
        61 #else
        62     int (*wait_event) (int which, fd_set *in, fd_set *out, fd_set *except,
        63             struct timeval *timeout);
        64 #endif
        65 }INPUT;
        66
        67 extern INPUT* cur_input;
        

系统启动之后,将根据配置寻找特定的输入引擎作为当前的输入引擎,并且对全局变量 cur_input 赋值。

(*cur_gfx->drawhline) (gc, x, y, w, pixel);
        

为方便程序书写,我们还定义了如下 C 语言宏:

  69 #define IAL_InitInput           (*cur_input->init_input)
        70 #define IAL_TermInput           (*cur_input->term_input)
        71 #define IAL_UpdateMouse         (*cur_input->update_mouse)
        72 #define IAL_GetMouseX           (*cur_input->get_mouse_x)
        73 #define IAL_GetMouseY           (*cur_input->get_mouse_y)
        74 #define IAL_SetMouseXY          (*cur_input->set_mouse_xy)
        75 #define IAL_GetMouseButton      (*cur_input->get_mouse_button)
        76 #define IAL_SetMouseRange      (*cur_input->set_mouse_range)
        77
        78 #define IAL_UpdateKeyboard      (*cur_input->update_keyboard)
        79 #define IAL_GetKeyboardState    (*cur_input->get_keyboard_state)
        80 #define IAL_SuspendKeyboard             (*cur_input->suspend_keyboard)
        81 #define IAL_ResumeKeyboard              (*cur_input->resume_keyboard)
        82 #define IAL_SetLeds(leds)       if (cur_input->set_leds) (*cur_input->set_leds) (leds)
        83
        84 #define IAL_WaitEvent           (*cur_input->wait_event)
        

在 src/kernel/event.c 中,我们如下调用底层的输入引擎,从而将输入引擎的数据转换为 MiniGUI 上层能够理解的消息(以 MiniGUI-Lite 为例),见清单 4:

                   清单 4   MiniGUI 对底层输入事件的处理
        172 #ifdef _LITE_VERSION
        173 BOOL GetLWEvent (int event, PLWEVENT lwe)
        174 {
        175     static LWEVENT old_lwe = {0, 0};
        176     unsigned int interval;
        177     int button;
        178     PMOUSEEVENT me = &(lwe->data.me);
        179     PKEYEVENT ke = &(lwe->data.ke);
        180     unsigned char* keystate;
        181     int i;
        182     int make;       /* 0 = release, 1 = presse */
        183
        184     if (event == 0) {
        185         if (timer_counter >= timeout_count) {
        186
        187             timeout_count = timer_counter + repeat_threshold;
        188
        189             // repeat last event
        190             if (old_lwe.type == LWETYPE_KEY
        191                     && old_lwe.data.ke.event == KE_KEYDOWN) {
        192                 memcpy (lwe, &old_lwe, sizeof (LWEVENT));
        193                 lwe->data.ke.status |= KE_REPEATED;
        194                 return 1;
        195             }
        196
        197             if (!(old_lwe.type == LWETYPE_MOUSE
        198                     && (old_lwe.data.me.event == ME_LEFTDOWN ||
        199                         old_lwe.data.me.event == ME_RIGHTDOWN ||
        200                         old_lwe.data.me.event == ME_MIDDLEDOWN))) {
        201                 // reset delay time
        202                 timeout_count = timer_counter + timeout_threshold;
        203             }
        204
        205             // reset delay time
        206             lwe->type = LWETYPE_TIMEOUT;
        207             lwe->count = timer_counter;
        208             return 1;
        209         }
        210         return 0;
        211     }
        212
        213     timeout_count = timer_counter + timeout_threshold;
        214     // There was a event occurred.
        215     if (event & IAL_MOUSEEVENT) {
        216         lwe->type = LWETYPE_MOUSE;
        217         if (RefreshCursor(&me->x, &me->y, &button)) {
        218             me->event = ME_MOVED;
        219             time1 = 0;
        220             time2 = 0;
        221
        222             if (oldbutton == button)
        223                 return 1;
        224         }
        225
        226         if ( !(oldbutton & IAL_MOUSE_LEFTBUTTON) &&
        227               (button & IAL_MOUSE_LEFTBUTTON) )
        228         {
        229             if (time1) {
        230                 interval = timer_counter - time1;
        231                 if (interval <= dblclicktime)
        232                     me->event = ME_LEFTDBLCLICK;
        233                 else
        234                     me->event = ME_LEFTDOWN;
        235                 time1 = 0;
        236             }
        237             else {
        238                 time1 = timer_counter;
        239                 me->event = ME_LEFTDOWN;
        240             }
        241             goto mouseret;
        242         }
        243
        244         if ( (oldbutton & IAL_MOUSE_LEFTBUTTON) &&
        245              !(button & IAL_MOUSE_LEFTBUTTON) )
        246         {
        247             me->event = ME_LEFTUP;
        248             goto mouseret;
        249         }
        250
        251         if ( !(oldbutton & IAL_MOUSE_RIGHTBUTTON) &&
        252               (button & IAL_MOUSE_RIGHTBUTTON) )
        253         {
        254             if (time2) {
        255                 interval = timer_counter - time2;
        256                 if (interval <= dblclicktime)
        257                     me->event = ME_RIGHTDBLCLICK;
        258                 else
        259                     me->event = ME_RIGHTDOWN;
        260                 time2 = 0;
        261             }
        262             else {
        263                 time2 = timer_counter;
        264                 me->event = ME_RIGHTDOWN;
        265             }
        266             goto mouseret;
        267         }
        268
        269         if ( (oldbutton & IAL_MOUSE_RIGHTBUTTON) &&
        270             !(button & IAL_MOUSE_RIGHTBUTTON) )
        271         {
        272             me->event = ME_RIGHTUP;
        273             goto mouseret;
        274         }
        275     }
        276
        277     if(event & IAL_KEYEVENT) {
        278         lwe->type = LWETYPE_KEY;
        279         keystate = IAL_GetKeyboardState ();
        280         for(i = 0; i < NR_KEYS; i++) {
        281             if(!oldkeystate[i] && keystate[i]) {
        282                  ke->event = KE_KEYDOWN;
        283                  ke->scancode = i;
        284                  olddownkey = i;
        285                  break;
        286             }
        287             if(oldkeystate[i] && !keystate[i]) {
        288                  ke->event = KE_KEYUP;
        289                  ke->scancode = i;
        290                  break;
        291             }
        292         }
        293         if (i == NR_KEYS) {
        294             ke->event = KE_KEYDOWN;
        295             ke->scancode = olddownkey;
        296         }
        297
        298         make = (ke->event == KE_KEYDOWN)?1:0;
        299
        300         if (i != NR_KEYS) {
        301             unsigned leds;
        302
        303             switch (ke->scancode) {
        304                 case SCANCODE_CAPSLOCK:
        305                     if (make && caps_off) {
        306                         capslock = 1 - capslock;
        307                         leds = slock | (numlock << 1) | (capslock << 2);
        308                         IAL_SetLeds (leds);
        309                         status = (DWORD)leds << 16;
        310                     }
        311                     caps_off = 1 - make;
        312                 break;
        313
        314                 case SCANCODE_NUMLOCK:
        315                     if (make && num_off) {
        316                         numlock = 1 - numlock;
        317                         leds = slock | (numlock << 1) | (capslock << 2);
        318                         IAL_SetLeds (leds);
        319                         status = (DWORD)leds << 16;
        320                     }
        321                     num_off = 1 - make;
        322                 break;
        323
        324                 case SCANCODE_SCROLLLOCK:
        325                     if (make & slock_off) {
        326                         slock = 1 - slock;
        327                         leds = slock | (numlock << 1) | (capslock << 2);
        328                         IAL_SetLeds (leds);
        329                         status = (DWORD)leds << 16;
        330                     }
        331                     slock_off = 1 - make;
        332                     break;
        333
        334                 case SCANCODE_LEFTCONTROL:
        335                     control1 = make;
        336                     break;
        337
        338                 case SCANCODE_RIGHTCONTROL:
        339                     control2 = make;
        340                     break;
        341
        342                 case SCANCODE_LEFTSHIFT:
        343                     shift1 = make;
        344                     break;
        345
        346                 case SCANCODE_RIGHTSHIFT:
        347                     shift2 = make;
        348                     break;
        349
        350                 case SCANCODE_LEFTALT:
        351                     alt1 = make;
        352                     break;
        353
        354                 case SCANCODE_RIGHTALT:
        355                     alt2 = make;
        356                     break;
        357
        358             }
        359
        360             status &= 0xFFFFF0C0;
        361
        362             status |= (DWORD)((capslock << 8) |
        363                              (numlock << 7)   |
        364                              (slock << 6)     |
        365                              (control1 << 5)  |
        366                              (control2 << 4)  |
        367                              (alt1 << 3)      |
        368                              (alt2 << 2)      |
        369                              (shift1 << 1)    |
        370                              (shift2));
        371
        372             // Mouse button status
        373             if (oldbutton & IAL_MOUSE_LEFTBUTTON)
        374                 status |= 0x00000100;
        375             else if (oldbutton & IAL_MOUSE_RIGHTBUTTON)
        376                 status |= 0x00000200;
        377         }
        378         ke->status = status;
        379         SHAREDRES_SHIFTSTATUS = status;
        380         memcpy (oldkeystate, keystate, NR_KEYS);
        381         memcpy (&old_lwe, lwe, sizeof (LWEVENT));
        382         return 1;
        383     }
        384
        385     old_lwe.type = 0;
        386     return 0;
        387
        388 mouseret:
        389     status &= 0xFFFFF0FF;
        390     oldbutton = button;
        391     if (oldbutton & IAL_MOUSE_LEFTBUTTON)
        392         status |= 0x00000100;
        393     if (oldbutton & IAL_MOUSE_RIGHTBUTTON)
        394         status |= 0x00000200;
        395     me->status = status;
        396     SHAREDRES_SHIFTSTATUS = status;
        397     memcpy (&old_lwe, lwe, sizeof (LWEVENT));
        398     return 1;
        399 }
        #endif
        

从这段代码中可以看出,对定点设备来讲,比如鼠标或者触摸屏,MiniGUI 能够自动识别移动信息,也能够自动识别用户的单击和双击事件。这样,底层引擎只需提供位置信息和当前的按键状态信息就可以了。对类似键盘的东西,MiniGUI 也能够自动进行重复处理。当一个按键按下一段时间之后,MiniGUI 将连续发送该按键的消息给上层处理。对特定的嵌入式系统来讲,可以将某些按键映射为 PC 的某些键盘键,上层只需处理这些键盘键消息的按下和释放即可。这样,嵌入式系统上的某些键的功能就可以在 PC 上进行模拟了。

posted @ 2009-06-12 12:45  clara  阅读(767)  评论(0编辑  收藏  举报