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~~
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭