您的位置:首页 > 其它

第一个基于XServer的程序

2009-12-21 21:37 169 查看
看了fcitx源码很长时间,里面的结构也大概明白了,但是按键消息怎么给输入法的总是不明白,前几天看到一个Linux下输入法的说明文章,才一下子解开了这个迷,原来有一个XIM(X Input Method),在Linux下弄输入法,就是对这个库编程。网址在这里:
http://www.ibm.com/developerworks/cn/linux/i18n/xim/xim-2/index.html
有了这个文章的帮助,很容易就把fcitx的整体结构看清楚了。主要用的是xlib的库,每一个输入法的相关函数封装到了一个结构中,这个结构包括了有关输入法的所有操作函数,然后在切换输入法的时候,把这个结构换一下就可以。所有的输入法结构的初始化在SetIM函数中,可以清楚的看到,用RegisterNewIM函数来注册,在这个函数里,就可以看到,把每个输入法相关的函数都放到了IM结构中,IM的定义如下

typedef struct {
char            strName[MAX_IM_NAME + 1];
void            (*ResetIM) (void);
INPUT_RETURN_VALUE (*DoInput) (int);
INPUT_RETURN_VALUE (*GetCandWords) (SEARCH_MODE);
char           *(*GetCandWord) (int);
char           *(*GetLegendCandWord) (int);
Bool (*PhraseTips) (void);
void            (*Init) (void);
void            (*Destroy) (void);
} IM;


在程序中,定义了一个IM *im变量,用来保存现在的输入法。在SetIM中会给这个im分配内存, im = (IM *) malloc (sizeof (IM) * iIMCount);

这样,处理完成后,就等待客户端程序的事件了。原来这这么一个过程

现在fcitx的结构要比以前的结构清楚多了。

程序结构清楚了,下一步就是学习了。首先从最简单的做起,一个XServer的客户端,显示一个小窗口,因为要给用户一个界面来看到现在的输入法状态。

代码如下

#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xlocale.h>
#include <X11/Xutil.h>
#include <iconv.h>

typedef struct
{
GC    gc;
XColor        color;
}WINDOW_COLOR;

int     WIDTH = 150;
int     HEIGHT = 60;
Display *dpy;             // 这就是和XServer通信的一个标识
int iScreen;

GC      dimGC;
GC      lightGC;
WINDOW_COLOR    mainWindowColor = { NULL, {0, 240 << 8, 255 << 8, 240 << 8} }; Window      mainWindow;
int     iMainWindowX = 20;
int     iMainWindowY = 40;
void InitWindowColor( void );
Bool InitX(void);
Bool InitX( void )
{
if ( ( dpy = XOpenDisplay( (char *)NULL)) == NULL )
{
fprintf ( stderr, "Error: this programe can't open display/n" );
return False;
}

iScreen = DefaultScreen ( dpy );
return True;
}

void InitWindowColor( void )
{
XGCValues     values;
int           iPixel;
int           i  = 0;
mainWindowColor.gc = XCreateGC( dpy, mainWindow, 0, &values );
if ( XAllocColor ( dpy, DefaultColormap( dpy, DefaultScreen ( dpy ) ), &(mainWindowColor.color)))
iPixel = mainWindowColor.color.pixel;
else
iPixel = WhitePixel ( dpy, DefaultScreen ( dpy ) );

XSetForeground ( dpy, mainWindowColor.gc, iPixel );

}

void CloseX(void)
{
XCloseDisplay( dpy );
}

Bool CreateWindow(void)
{
XSetWindowAttributes attrib;
unsigned long attribmask;
int           iBackPixel;

attrib.override_redirect = True;
attribmask = CWOverrideRedirect;

//  sprintf ( str
mainWindow = XCreateSimpleWindow ( dpy, DefaultRootWindow( dpy ), iMainWindowX, iMainWindowY, WIDTH, HEIGHT, 0, WhitePixel ( dpy, DefaultScreen(dpy)), iBackPixel );
if ( mainWindow == ( Window ) NULL ) {
return False;
}
XChangeWindowAttributes ( dpy, mainWindow, attribmask, &attrib );
XSelectInput ( dpy, mainWindow, ExposureMask | KeyPressMask | ButtonPress | ButtonReleaseMask | StructureNotifyMask | EnterWindowMask | PointerMotionMask | LeaveWindowMask | VisibilityChangeMask );
InitWindowColor();
return True;
}

void DisplayWindow(void)
{
XMapRaised ( dpy, mainWindow );
}
void DrawMainWindow( void )
{
XDrawRectangle ( dpy, mainWindow, mainWindowColor.gc, 1, 1, WIDTH-2, HEIGHT - 2 );
}

void MyXEventHandler ( XEvent *event )
{
unsigned char iPos;
switch ( event->type )
{
case ClientMessage:
//if ( ( event->xclient.message_type == about_protocol_atom ) && ( ( Atom )event->xclient.data.l[0] == about_kill_atom ))
{
DrawMainWindow();
}
break;
case Expose:
fprintf ( stderr, "XEvent--Expose/n");
if ( event->xexpose.count > 0 )
{
break;
}
if ( event->xexpose.window == mainWindow )
{
DrawMainWindow();
}
break;
case DestroyNotify:

break;
case ButtonPress:
switch ( event->xbutton.button )
{
case Button1:
{
// 这里是移动窗口的代码
int x = event->xbutton.x;
int y = event->xbutton.y;
XEvent evtGrabbed;
Bool bMoved = False;
while ( 1 )
{
XMaskEvent ( dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask, &evtGrabbed );
if ( ButtonRelease == evtGrabbed.xany.type )
{
if ( Button1 == evtGrabbed.xbutton.button )
break;
}
else if ( MotionNotify == evtGrabbed.xany.type )
{
static Time LastTime;
if ( evtGrabbed.xmotion.time - LastTime < 20 )
{
continue;
}
XMoveWindow ( dpy, mainWindow, evtGrabbed.xmotion.x_root - x, evtGrabbed.xmotion.y_root - y );
XRaiseWindow ( dpy, mainWindow );
bMoved = True;
LastTime = evtGrabbed.xmotion.time;
}
}
printf ( "Left Mouse Button Press/n" );
}
break;
case Button2:
printf ( "Middle Mouse Button Press/n" );
break;
case Button3:
printf ( "Right Mouse Button Press/n" );
break;
}
break;
case KeyPressMask:
printf ( "Key Down/n" );
}
}

int main ( int argc, char *argv[] )
{
XEvent        event;
if ( !InitX() )
{
return 1;
}

printf ( "OK, Create OK/n" );
if ( CreateWindow() )
{
printf ( "OK, Create Window OK/n" );
}
DisplayWindow();
DrawMainWindow();

// 和Windows下的消息循环相同
for ( ;; )
{
XNextEvent ( dpy, &event );
if ( XFilterEvent ( &event, None ) == True )
{
continue;
}
// 自己定义的消息处理函数
MyXEventHandler( &event );
}

CloseX();

return 0;
}


编译此代码:gcc -lX11 -o firstxlib firstxlib.o

最后附一个Xlib Manual的网址:http://tronche.com/gui/x/xlib/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐