[原创] android增加鼠标支持

Wince.Android   2013-4-28 17:06 楼主

  • Android默认是没有鼠标支持的,但在Android系统会应用到许多其他的地方,如平板电脑、电视中,许多时候就需要鼠标的支持。

    支持原理:Android中有原生的Touch事件,鼠标的各种事件都可以转换为各种Touch事件,将鼠标事件走与Touch事件相关的路径就可以实现。需要注意的是,在屏幕旋转后,鼠标的坐标等信息需要程序处理才能正确。

    修改文件概览:
    C++文件:

                 frameworks\base\include\ui\EventHub.h
                  frameworks\base\libs\ui\EventHub.cpp
    java文件:
                   frameworks\base\core\java\android\view\RawInputEvent.java
                   frameworks\base\services\java\com\android\server\InputDevice.java
                   frameworks\base\services\java\com\android\server\KeyInputQueue.java
                   frameworks\base\services\java\com\android\server\WindowManagerService.java

    文件功能描述
                  EventHub.h                          增加鼠标设备的定义
                  EventHub.cpp                   函数open_device(const char *deviceName)中增加鼠标类型
                  RawInputEvent.java             增加鼠标设备
                  InputDevice.java                  增加鼠标连接状态标志
                                                    MotionState中增加方法 generateMouseMotion()将原始鼠标事件转化为
                                                        MotionEvent事件
                  KeyInputQueue.java     在事件RawInputEvent.EV_DEVICE_ADDED中判断鼠标设备,动态增加
                                                    在事件RawInputEvent.EV_DEVICE_REMOVED中,动态判断鼠标删除
                                                    在ev.type == RawInputEvent.EV_KEY中增加鼠标左中右键处理
                                                    在ev.type == RawInputEvent.EV_REL中增加鼠标坐标变动和滚轮的处理
                                                      recycleEvent()中增加鼠标相关的清理工作
                 WindowManagerService.java    实现在界面上的画鼠标及移动鼠标的工作。

    如果你的Android设备支持鼠标,你将会发现默认的光标为灰色半透明的三角形,系统的默认主题是黑色的,造成很难发现鼠标的位置。所以本文介绍怎样定制Android系统的鼠标光标。
         Android系统对鼠标的支持并不好,因为Android系统原本是为手机量身定做的,手机系统基本上是不需要鼠标的。但是随着Android系统移植到其他领域,对鼠标的支持也越来越有意义。现在Android已经支持鼠标了,但是有一个完善的过程。本文后面会介绍到Android对鼠标支持的一些不足。
         原来我以为Android系统的光标会和Windows差不多,是一个图片资源呢。这样的话,我只需要替换掉这个图片就可以搞定了。找了好久都没有找到图片资源的位置,最终反过来思考,Android系统鼠标光标非常简单,手动绘制也不是很难的事情。会不会是代码中绘制的呢?
         沿着这个思路,终于在WindowManagerService.java中,找到了相关的代码:
    frameworks/base/services/java/com/android/server/WindowManagerService.java
    相关的代码位于performLayoutAndPlaceSurfacesLockedInner方法中:
    mMouseSurface = new Surface(mFxSession, 0,-1,mMw,mMh, PixelFormat.TRANSPARENT, Surface.FX_SURFACE_NORMAL); mCanvas = mMouseSurface.lockCanvas(null); mCanvas.drawColor(0x0); mPath.moveTo(0.0f, 0.0f); mPath.lineTo(16.0f, 0.0f); mPath.lineTo(0.0f, 16.0f); mPath.close(); mCanvas.clipPath(mPath); mCanvas.drawColor(0x66666666); mMouseSurface.unlockCanvasAndPost(mCanvas); mMouseSurface.openTransaction(); mMouseSurface.setSize(mMw,mMh); mMouseSurface.closeTransaction();
         可以看出默认情况下Android系统用颜色值0×66666666绘制了一个三角形,这个颜色值为32bit——A8R8G8R8,A表示透明度,0表示全部透明,0xff为不透明,0×66表示半透明。
         你可以修改其中代码来修改鼠标光标的形状,需要学习一下Android绘图系统,熟悉Paint,Canvas等概念,不过挺简单的。下面是我的光标绘制的代码:
    mMouseSurface = new Surface(mFxSession, 0,-1,mMw,mMh, PixelFormat.TRANSPARENT, Surface.FX_SURFACE_NORMAL); mCanvas = mMouseSurface.lockCanvas(null); mCanvas.drawColor(0x0); mPath.moveTo(0.0f, 0.0f); mPath.lineTo(0.0f, 19.0f); mPath.lineTo(14.0f, 14.0f); mPath.close(); mCanvas.clipPath(mPath); mCanvas.drawColor(0xFFFFFFFF); Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setColor(0xFF000000); mCanvas.drawPath(mPath, paint); mMouseSurface.unlockCanvasAndPost(mCanvas); mMouseSurface.openTransaction();                                             
    绘制的光标为一个瘦一点儿的不透明的白色填充的三角形,然后用黑色给白色三角形描边。主要是模仿Windows的光标风格,对于各种颜色基调的主题这个光标都可以很清晰。
         可以看出Android系统鼠标光标的定制不是非常容易,需要修改代码,相信Android后续版本会对鼠标的支持有改进。以上代码仅供参考,如有错误敬请指正。




    SDL for Embedded Systems



      SDL stands for "Simple DirectMedia Layer". It is simple, small and can access multimedia hardware directly. Therefore, it is particularly useful in developing applications for Embedded Linux systems as such systems usually have highly constrained resources. However, from time to time you may need to make modifications to the SDL libraries in order that they fully function in the embedded environment. In general, an Embedded Linux system does not support X-Window as it requires tremendous amount of resources to run; this may render the mouse useless. In order to use the mouse in a non-X environment, we need to make some minor modifications to the SDL libraries as of to date ( version 1.2.11 ). Very often, an embedded Linux development board provides one or more USB ports for I/O interface; the USB ports can be used to interface to a mouse, a keyboard or some other USB devices. In this chapter, we discuss how to modify SDL-1.2.11 to support USB I/O devices for Embedded Linux.
    • USB Mouse and Touch Screen ( TS ) InputMouse and TS have similar input mechanisms. For latest Linux versions, the devices in general can be accessed via


        /dev/input/event0   or   /dev/input/event1
      For backward compatibility, the mouse may also be accessed via /dev/input/mice, /dev/input/mouse0, or/dev/input/mouse1, etc
      You could test if the mouse works by the executing the command,

        #cat /dev/input/event1
      Moving the mouse around will display some random characters, mostly unprintable on the screen.In an ARM-9 board, most likely you can only see
    • /dev/input/event0
    • /dev/input/event1In this case, event0 is for ts ( touch screen ) and event1 is for mouse or keyboard, depending on what you have plugged in the USB port. Again, you can use the command "cat /dev/input/eventn" to test if you could open the device.SDL mouse support

      SDL does not support USB mouse directly ( in a PC, SDL utilizes X-window routine to handle the mouse but in our ARM board, we use the frame buffer routine directly ). To support USB mouse and touch screen, we may modify some of the source files of the SDL-1.2.11 library as follows.You need to modify the following three files located at src/video/fbcon of the SDL source code tree:

      • SDL_fbevents.c
      • SDL_fbevents_c.h
      • SDL_fbvideo.c
    • First, add functions in SDL_fbvideo.c to handle mouse/ts I/Os ( note that we use SELECT to handle I/O ):

        static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) ... #ifdef __ARM__ if ( FB_OpenEventX(this) == 0 ) { SDL_SetError("Unable to open /dev/input/eventX"); FB_VideoQuit(this); return(-1); } #else //PC original code #endif
    • Second, add function prototypes to header file SDL_fbevents_c.h:
      static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) extern int FB_OpenEventX(_THIS); extern void FB_CloseEventX(_THIS); extern void FB_vgamousecallback(int button, int relative, int dx, int dy);

    • Third, add the following to SDL_fbevents.c:
      #include .... static int event0_fd = -1; static int event1_fd = -1; struct input_event ev0[64]; struct input_event ev1[64]; //for handling TS static void handle_event0(_THIS) { int button=0, x=0, y=0, realx=0, realy=0, i, rd; rd = read(event0_fd, ev0, sizeof(struct input_event) * 64); if( rd < sizeof(struct input_event) ) return; for (i = 0; i < rd / sizeof(struct input_event); i++) { if(ev0.type == 3 && ev0.code == 0) x = ev0.value; else if(ev0.type == 3 && ev0.code == 1) y = ev0.value; else if(ev0.type == 1 && ev0.code == 330) button = ev0.value << 2; else if(ev0.type == 0 && ev0.code == 0 && ev0.value == 0) { //need to define numbers in header for flexibility realx = (950-y)*240/(950-70); realy = (x-70)*320/(950-70); if( realx < 0 ) realx = 0; if( realx > 240 ) realx = 240; if( realy < 0 ) realy = 0; if( realy > 320 )realx = 320; FB_vgamousecallback(button, 0, realx, realy); } } return; } //for handling mouse static void handle_event1(_THIS) { int button=0, x=0, y=0, i, rd; rd = read(event1_fd, ev1, sizeof(struct input_event) * 64); if( rd < sizeof(struct input_event) ) return; for (i = 0; i < rd / sizeof(struct input_event); i++) { if(ev1.type == 2 && ev1.code == 0) x = ev1.value; else if(ev1.type == 2 && ev1.code == 1) y = ev1.value; else if(ev1.type == 1) { if(ev1.code == 272) { button &= ~0x4; button |= ev1.value << 2; } else if(ev1.code == 273) { button &= ~0x1; button |= ev1.value; } else if(ev1.code == 274) { button &= ~0x2; button |= ev1.value << 1; } } else if(ev1.type == 0 && ev1.code == 0 && ev1.value == 0) { FB_vgamousecallback(button, 1, x, y); x=0, y=0; } } return; } int FB_OpenEventX(_THIS) { event0_fd = open("/dev/input/event0", O_RDWR); event1_fd = open("/dev/input/event1", O_RDWR); if(event0_fd < 0 && event1_fd < 0) return 0; return 1; } void FB_CloseEventX(_THIS) { if ( event0_fd > 0 ) { close(event0_fd); } if ( event1_fd > 0 ) { close(event1_fd); } event0_fd = -1; event1_fd = -1; } ....
      After you've made the above modifications, recompile the SDL library as discussed in the previous chapters. The new library will support both USB mouse and touch screen.



回复评论 (1)

一般来说,android系统是支持的,只是鼠标的影子会看不到,没鼠标。O(∩_∩)O~
不过自己可以画出来的。
作者:goooogleman
        平台:S5pv210 之Sate210

        在三月底的时候Sate210 刚推出android系统的时候,我试过,四个USB hub 都是支持u盘和鼠标的,这两天给客户定制了android VGA 1024*768 分辨率的系统,忽然发现不支持鼠标和u盘了,只会打印如下信息,插拔鼠标的时候。

后来仔细发现是make menuconfig 没有选

#
# USB Input Devices
#
CONFIG_USB_HID=y

现在在make menuconfig的时候加上,然后把.config文件copy出来保存成sata210_config.config
以后只要执行sata210_config.config 脚本就可以配置支持USB 鼠标的系统了。

#!/bin/bash
make mrproper
cp sata210_config .config
make -j8

在Sate210 上这样,就可以出来了,鼠标也可以看见!
点赞  2013-4-28 17:16
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复