幻想小说网 酷文学 深夜书屋 叮当小说网 找小说网 无限小说网 红尘小说网

DirectFB同时显示到X11和VNC上

DirectFB同时显示到X11和VNC上

转载时请注明出处和作者联系方式
作者联系方式:李先静 <xianjimli at hotmail dot com>

DirectFB可以使用多种后端作为输入输出设备,典型的有VNC、X11、SDL和fbdev等等,这种设计可以说非常巧妙了。但美中不足的是它在任意时刻只能使用一种后端,更换成其它后端需要重新起动DirectFB应用程序。大多数情况下,这也没有问题,但我想broncho手机在正常使用的情况下,还能通过VNC访问,这样就可以在PC上操作broncho手机的所有功能,甚至到把手机屏幕显示到投影仪上。

对于让DirectFB同时支持多个后端的情况,从设计的角度来看,当然是首选Composite模式,用一种新的后端把其它几个后端组合起来,即不用修改DirectFB框架,又不用修改现有的后端,改一下配置文件就行了。麻烦的是DirectFB-1.1.1中带的VNC根本就不能用,单进程的情况,那些问题我都修改掉了,支持多进程的情况遇到些困难了。最后懒得管它了,先给X11加上VNC功能试一下再说。


先编译LibVNCServer-0.9.1。从sf下载软件包,按正常方式编译即可。

接下来修改X11后端。

1.修改Makefile.am,连接VNC的库。


libdirectfb_x11_la_LDFLAGS = /
    $(X11_LIBS)    $(VNC_LIBS) /
    -avoid-version    /
    -module

2.初始化VNC

     int argc = 0;
     char** argv = NULL;

     D_DEBUG( "DirectFB/VNC: layer config properties/n");

     if(rfb_screen) /*!!! FIXME*/
         return DFB_OK;

     /* Set video mode */
     rfb_screen = rfbGetScreen(&argc, argv, config->width, config->height, 8,3,4);
    
     if(DFB_COLOR_BITS_PER_PIXEL(config->format) == DSPF_RGB16)
     {
        rfb_screen->serverFormat.redShift = 11;
        rfb_screen->serverFormat.greenShift = 5;
        rfb_screen->serverFormat.blueShift = 0;
        rfb_screen->serverFormat.redMax = 31;
        rfb_screen->serverFormat.greenMax = 63;
        rfb_screen->serverFormat.blueMax = 31;
     }
   
     rfb_screen->frameBuffer = malloc(rfb_screen->width * rfb_screen->height * rfb_screen->depth / 8) ;
    
     rfb_screen->kbdAddEvent = process_key_event;
     rfb_screen->ptrAddEvent = process_pointer_event;
     rfb_screen->newClientHook = newclient;
    
     rfbInitServer(rfb_screen);
    
     direct_thread_create( DTT_OUTPUT, vnc_server_thread, rfb_screen, "VNC Output" );
   
     if ( !(config->surface_caps & (DSCAPS_DOUBLE | DSCAPS_TRIPLE)) )
          direct_thread_create( DTT_OUTPUT, vnc_refresh_thread, rfb_screen, "VNC Refresh" );
 
     return DFB_OK;




3.更新VNC显示

static DFBResult
vnc_update_screen(void* src, int x, int y, int w, int h )
{
     int          i, j, k;
     void        *dst;
     int          pitch;
     DFBResult    ret;
     unsigned short* p = NULL;
     unsigned int* q = NULL;
     D_ASSERT( surface != NULL );
     D_ASSERT( rfb_screen != NULL );
     D_ASSERT( rfb_screen->frameBuffer != NULL );

     dst = rfb_screen->frameBuffer;
   
     if(g_vnc_client_nr > 0)
     {
        direct_memcpy( dst, src, w * h * rfb_screen->depth/8 );
        rfbMarkRectAsModified ( rfb_screen, x, y, x+w, y+h );
        printf("%s %d %d %d %d/n", __func__, x, y, w, h);
     }

     return DFB_OK;
}



4.处理VNC输入


static void
process_pointer_event(int buttonMask, int x, int y, rfbClientPtr cl)
{

    DFBInputEvent evt = {0};
    int button = 0;

    if( vncPointerDevice == NULL ){
        /* Attach to first input device */
        dfb_input_enumerate_devices( attach_pointer_device,NULL,
            DICAPS_BUTTONS|DICAPS_AXES);
        D_ASSERT(vncPointerDevice);
    }

    ClientData* cd=cl->clientData;
    if(buttonMask != cd->oldButtonMask ) {
        int mask = buttonMask^cd->oldButtonMask;
        if( mask & (1 << 0)) {
            button=DIBI_LEFT;
        } else if( mask & (1 << 1)) {
            button=DIBI_MIDDLE;
        } else if( mask & (1 << 2)) {
            button=DIBI_RIGHT;
        } else {
            return;
        }
        evt.flags = DIEF_NONE;
               
        if(cd->pressed)
        {
            evt.type = DIET_BUTTONRELEASE;
            cd->pressed=0;
            cd->oldButtonMask = 0;
        }else {
            evt.type = DIET_BUTTONPRESS;
            cd->pressed=1;
            cd->oldButtonMask=buttonMask;
        }
        evt.button=button;
        printf("%s %d %d %d %d/n", __func__, button, cd->pressed, x, y);
        dfb_input_dispatch( vncPointerDevice, &evt );
        cd->oldx=x;
        cd->oldy=y;
        return;
    }

    evt.type    = DIET_AXISMOTION;
    evt.flags   = DIEF_AXISABS;

    if( cd->oldx != x ) {
          evt.axis    = DIAI_X;
          evt.axisabs = x;
          dfb_input_dispatch( vncPointerDevice, &evt );
    }

    if( cd->oldy != y ) {
          evt.axis    = DIAI_Y;
          evt.axisabs = y;
          dfb_input_dispatch( vncPointerDevice, &evt );
    }
    cd->oldx=x;
    cd->oldy=y;

    dfb_input_dispatch( vncPointerDevice, &evt );
    rfbDefaultPtrAddEvent(buttonMask,x,y,cl);

}

static void
process_key_event(rfbBool down, rfbKeySym key, rfbClientPtr cl)
{
    DFBInputEvent evt;
    if( vncKeyboardDevice == NULL ){
        /* Attach to first input device */
        dfb_input_enumerate_devices( attach_keyboard_device,NULL, DICAPS_KEYS);
        D_ASSERT(vncKeyboardDevice);
    }
     if (down)
          evt.type = DIET_KEYPRESS;
     else
          evt.type = DIET_KEYRELEASE;
                                                                                 
     if (translate_key( key, &evt )) {
          dfb_input_dispatch( vncKeyboardDevice, &evt );
     }

}


5.处理VNC客户端连接

static void clientgone(rfbClientPtr cl)
{
  g_vnc_client_nr--;
  free(cl->clientData);

  return;
}

static enum rfbNewClientAction newclient(rfbClientPtr cl)
{
  g_vnc_client_nr++;
  cl->clientData = (void*)calloc(sizeof(ClientData),1);
  cl->clientGoneHook = clientgone;
  return RFB_CLIENT_ACCEPT;
}



编译完成后运行broncho,然后用VNC viewer连接到本机,效果如下:



色彩有点不对,有时间再看看。


~~end~~

posted on 2008-06-09 14:48  张云临  阅读(230)  评论(0编辑  收藏  举报

导航