写了个测试小程序,用X11的Xlib库创建个可写的framebuffer窗口,逐像素刷新。供参考。
编译
gcc testfb.c -lX11
d键测试,esc和小叉退出。
#include
#include
#include
#include
enum KEY {K_Escape=9, K_1,K_2,K_3,K_4,K_5,K_6,K_7,K_8,K_9,K_0,
K_minus,K_equal,K_BackSpace,K_Tab,K_q,K_w,K_e,K_r,K_t,K_y,
K_u,K_i,K_o,K_p,K_bracketleft,K_bracketright,K_Return,K_Control_L,K_a,K_s,
K_d,K_f,K_g,K_h,K_j,K_k,K_l,K_semicolon,K_apostrophe,K_grave,
K_Shift_L,K_backslash,K_z,K_x,K_c,K_v,K_b,K_n,K_m,K_comma,
K_period,K_slash,K_Shift_R,Kp_Multiply,K_Alt_L,K_space,K_Caps_Lock,K_F1,K_F2,K_F3,
K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,K_Num_Lock,K_Scroll_Lock,Kp_Home,
Kp_Up,Kp_Prior,Kp_Subtract,Kp_Left,Kp_Begin,Kp_Right,Kp_Add,Kp_End,Kp_Down ,Kp_Next,
Kp_Insert,Kp_Delete,K_ISO_Level3_Shift,K_less=94,K_F11,K_F12,
Kp_Enter=104,K_Control_R,Kp_Divide,K_Print,K_Alt_R,K_Linefeed,
K_Home,K_Up,K_Prior,K_Left,K_Right,K_End,K_Down,K_Next,K_Insert,K_Delete,
Kp_Equal=125,K_plusminus,K_Pause,Kp_Decimal=129,
K_Super_L=133,K_Super_R,K_Menu,K_Cancel,K_Redo};
enum BUTTON { B_Right = 1, B_Middle, B_Left,B_Wheel_up, B_Wheel_down};
Window win;
short fb_width;
short fb_height;
Display *display;
GC *gcptr;
XImage *img;
int* dataptr;
int put_pixel(int x, int y, int pix)
{
if(x>=0 && x < fb_width && y >= 0 && y < fb_height){
XPutPixel(img, x, y, (unsigned long) pix);
XPutImage(display,win,*gcptr,img,x,y,x,y,1,1); // refresh single pixel
// XPutImage(display,win,*gcptr,img,0,0,0,0,fb_width,fb_height); //refresh all
return 0;
} else
return -1; //not valid
}
void flush()
{
XPutImage(display,win,*gcptr,img,0,0,0,0,fb_width,fb_height); //refresh all
}
int process_event_loop()
{
XEvent event;
Atom wm_delete_window;
wm_delete_window = XInternAtom(display,"WM_DELETE_WINDOW",False);
XSetWMProtocols(display,win,&wm_delete_window,1);
while(1) {
XNextEvent(display,&event);
if (event.type == KeyPress ){
switch(event.xkey.keycode) {
case K_d: //d键 测试
for(int i = 0; i<fb_width; i++) {
int pix = (i*256)/fb_width <<8;
for(int j = 0; j <fb_height; j++)
put_pixel(i,j,pix);
}
break;
case K_Escape:
return 0;
default:
break;
}
} else if (event.type == Expose){
img->data = (char*)dataptr;
XPutImage(display,win,*gcptr,img,0,0,0,0,fb_width,fb_height);
} else if ( event.type == ClientMessage
&& ((Atom) event.xclient.data.l[0]) == wm_delete_window)
{ // 处理右上角叉退出
return 0;
}
// else XPutImage(display,win,*gcptr,img,0,0,0,0,fb_width,fb_height);
}
}
void open_window(short width,short height)
{
fb_width = width;
fb_height = height;
display = XOpenDisplay(NULL);
int screen_num = DefaultScreen(display);
Window root = RootWindow(display,screen_num);
Visual *visual = DefaultVisual(display, screen_num);
dataptr = (int*) malloc(fb_width*fb_height*4*sizeof(char));
img = XCreateImage(display, visual, DefaultDepth(display,screen_num),
ZPixmap,0,(char*)dataptr,fb_width,fb_height,32,0);
win = XCreateSimpleWindow(display, root, 50, 50, fb_width, fb_height, 1, 0, 0);
gcptr = &(DefaultGC(display,screen_num));
XSelectInput(display,win,ExposureMask | KeyPressMask |StructureNotifyMask |ButtonPressMask|ButtonReleaseMask|SubstructureNotifyMask);
XMapWindow(display,win);
}
void close_window()
{
free(dataptr);
XCloseDisplay(display);
}
int main() {
open_window(640,480);
process_event_loop();
printf("exited\n");
close_window();
}