现在的位置: 首页 > 综合 > 正文

X11 入门练习

2014年09月05日 ⁄ 综合 ⁄ 共 2099字 ⁄ 字号 评论关闭

转自http://blog.csdn.net/dbzhang800/article/details/6428207,感谢dbzhang800

应该用不了多久,Wayland(参考百度百科) 就会取代 X Window System 在linux系统下的地位了。  尽管如此,稍微了解一点点X11编程的东西应该没有坏处。

客户端-服务器

大家都说X是 客户端-服务器 的架构。那么这一定是真的了,可是,这到底是什么意思呢?

  • A client-server architecture is a general mechanism for handling a shared resource that several programs may want to access simultaneously. In the case of X, the shared resources are the drawing
    area and the input channel.

一个例子

既然是X11编程,首先我们需要相应的头文件

#include<X11/Xlib.h> 

int main()
{

前面提了X11是客户端-服务器架构,那么我们的程序(客户端)需要和服务器建立连接:

    Display *dsp = XOpenDisplay(NULL);

    if(!dsp) {
        return 1;
    }

建立连接后,就可以请求创建窗口了:

    int screenNumber = DefaultScreen(dsp);
    unsigned long white = WhitePixel(dsp,screenNumber);
    unsigned long black = BlackPixel(dsp,screenNumber);

    Window win = XCreateSimpleWindow(dsp,
            DefaultRootWindow(dsp),
            50, 50,   // origin
            200, 200, // size
            0, black, // border
            white );  // backgd

仅仅创建还不行,还需要map(想象成从内存拷贝到显存?)

    XMapWindow( dsp, win );

通讯是双向的,我们告诉server我们对哪些事件感兴趣:

    long eventMask = StructureNotifyMask;
    XSelectInput( dsp, win, eventMask );

然后等待server的 map 完成的通知

    XEvent evt;
    do{
        XNextEvent( dsp, &evt );   // calls XFlush()
    }while( evt.type != MapNotify ); );

收到通知以后,我们就可以在上面画线了:

  • 由于server记不住我们的每次绘图操作的设置,我们将设置保存在“Graphics Context”中
  • 每次绘图操作都要传递这些信息。
    GC gc = XCreateGC(dsp, win, 0, NULL );
    XSetForeground( dsp, gc, black );

    XDrawLine(dsp, win, gc, 10, 10,190,190);

我们告诉server,我们对鼠标按键感兴趣:

    eventMask = ButtonPressMask|ButtonReleaseMask;
    XSelectInput(dsp,win,eventMask); // override prev

等待鼠标释放的事件:

    do {
        XNextEvent(dsp, &evt);   // calls XFlush()
    } while (evt.type != ButtonRelease);

收到鼠标按键后:销毁窗口,断开连接,退出程序。

    XDestroyWindow(dsp, win);
    XCloseDisplay(dsp);

    return 0;
}

XFlush()

前面有一点没说,当我们执行了 XCreateSimpleWindow、XMapWindow 等操作时,数据还缓存在客户端。我们要确保数据送到server,需要调用 XFlush()。这一点我们可以类似写文件操作或网络写socket操作。

可是例子中为什么没有调用XFlush()能,这是由于XNextEvent()内部会调用XFlush(),所以我们省略了。

如果我们程序后面不是等待鼠标按键来退出,而是睡眠10秒钟再退出,那么就需要显式调用XFlush()了

#include<X11/Xlib.h>
#include<unistd.h>
...
    XDrawLine(dsp, win, gc, 10, 10,190,190);

    // Send the "DrawLine" request to the server
    XFlush(dsp);
    // Wait for 10 seconds
    sleep(10);

    XDestroyWindow(dsp, win);
    XCloseDisplay(dsp);

    return 0;
}

编译

把刚才分步解释的程序copy出来保存为hello.cpp或者hello.c

编译就很简单了:

g++ hello.cpp -o hello -lX11

或正式一点

g++ hello.cpp -o hello `pkg-config --cflags --libs x11`

注意,这里是反引号`,而不是单引号'。请记住反引号是要求shell执行其包含的命令并将输出结果附加其后。 

抱歉!评论已关闭.