天天看点

第一个Wayland程序

这是楼主的第一个Wayland程序:

效果图:

第一个Wayland程序

程序源代码:

//wayland-hello.h

/*
	Copyright (c) 第三界主 2014
	代码使用MIT协议发布
*/
#ifndef WAYLAND_HELLO_H
#define WAYLAND_HELLO_H


#include 
   
    
#include 
    
     
#include 
     
      
#include 
      
       
#include 
       
         #include 
        
          #include 
         
           #include 
          
            /* 某些struct wl_开头的对象实际上是wl_proxy对象的id,与windows下的Handle类似。 */ typedef struct wl_display* HDISPLAY; typedef struct wl_registry* HREGISTRY; typedef struct wl_compositor* HCOMPOSITOR; typedef struct wl_shell* HSHELL; typedef struct wl_shm* HSHM; typedef struct wl_shm_pool* HSHMPOOL; typedef struct wl_seat* HSEAT; typedef struct wl_pointer* HPOINTER; typedef struct wl_surface* HSURFACE; typedef struct wl_shell_surface * HSHELLSURFACE; typedef struct wl_callback* HCALLBACK; typedef struct wl_buffer* HBUFFER; typedef struct wl_keyboard* HKEYBOARD; typedef void* LPVOID; typedef struct _WAYLANDREGISTRY { /* 所有API都需要wl_display */ HDISPLAY s_display; /* 合成器 */ HCOMPOSITOR s_compositor; /* shell提供接口,与窗口操作有关 */ HSHELL s_shell; /* 缓存管理器,与绘制相关 */ HSHM s_shm; uint32_t shm_formats; /* 输入设备管理器,管理键盘鼠标 */ HSEAT s_seat; /* 鼠标控制器 */ HPOINTER s_pointer; /* 键盘控制器 */ HKEYBOARD s_keyboard; /* 鼠标当前窗口 */ HSURFACE s_pointer_surface; /* 键盘当前窗口 */ HSURFACE s_kb_surface; } WAYLANDREGISTRY, *LPWAYLANDREGISTRY; /* wayland的全局对象都放在registry中 */ LPWAYLANDREGISTRY wlGetRegistry(); typedef struct _PAINTBUFFER { HBUFFER buffer; void *data; int busy; }PAINTBUFFER, *LPPAINTBUFFER; typedef struct _PAINTSTRUCTURE { LPPAINTBUFFER buffer; } PAINTSTRUCTURE, *LPPAINTSTRUCTURE; typedef void(*REPAINTPROC)(HSURFACE hSurface, LPPAINTSTRUCTURE lpPaint, uint32_t time); typedef struct _SURFACEPRIVATE { struct wl_surface *surface; struct wl_shell_surface *shell_surface; int width, height; REPAINTPROC surfaceproc; PAINTBUFFER buffer[2]; } SURFACEPRIVATE, *LPSURFACEPRIVATE; typedef struct _SIZE { int width, height; } SIZE; typedef int POINTERPROC; typedef int KEYBOARDPROC; static inline HDISPLAY wlGetDisplay() { return wlGetRegistry()->s_display; } static inline HCOMPOSITOR wlGetCompositor() { return wlGetRegistry()->s_compositor; } static inline HSHELL wlGetShell() { return wlGetRegistry()->s_shell; } static inline HPOINTER wlGetPointer() { return wlGetRegistry()->s_pointer; } static inline HKEYBOARD wlGetKeyboard() { return wlGetRegistry()->s_keyboard; } LPSURFACEPRIVATE _wlGetSurfacePrivate(HSURFACE surface); void _wlCreatePaintStructure(int width, int height, LPPAINTBUFFER lpBuffer); void _wlSetFrameListener(HSURFACE surface); void _wlDrawFrame(HSURFACE surface, uint32_t time); void wlBeginPaint(HSURFACE surface, LPPAINTSTRUCTURE lpPaint); void wlEndPaint(HSURFACE surface, LPPAINTSTRUCTURE lpPaint); int wlInit(); void wlTerminate(); HSURFACE wlCreateSurface(const char* title, int width, int height); void wlSetPaintProc(HSURFACE surface, REPAINTPROC surfaceproc); void wlCallPaintProc(HSURFACE hSurface, LPPAINTSTRUCTURE lpPaint, uint32_t time); void wlSetPointerProc(HSURFACE surface, POINTERPROC surfaceproc); void wlSetKeyboardProc(HSURFACE surface, KEYBOARDPROC surfaceproc); SIZE wlGetSurfaceSize(HSURFACE surface); int wlDispatch(); #endif
          
         
        
       
      
     
    
   
           

//wayland-hello.c

/*
	Copyright (c) 第三界主 2014
	代码使用MIT协议发布
*/

#include 
   
    
#include 
    
     
#include 
     
      
#include 
      
       
#include 
       
         #include 
        
          #include 
         
           #include 
          
            #include "wayland-hello.h" void pointer_enter(void *data, HPOINTER wl_pointer, uint32_t serial, HSURFACE surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { wlGetRegistry()->s_pointer_surface = surface; } void pointer_leave(void *data, HPOINTER wl_pointer, uint32_t serial, HSURFACE surface) { wlGetRegistry()->s_pointer_surface = NULL; } void pointer_motion(void *data, HPOINTER wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { } void pointer_button(void *data, HPOINTER wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { HSURFACE hSurface = wlGetRegistry()->s_pointer_surface; if (hSurface == NULL) return; if (BTN_LEFT == button && state == WL_POINTER_BUTTON_STATE_PRESSED) { HSHELLSURFACE hShellSurface = _wlGetSurfacePrivate(hSurface)->shell_surface; wl_shell_surface_move(hShellSurface, wlGetRegistry()->s_seat, serial); return; } } void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { } struct wl_pointer_listener pointer_listener = { .enter = pointer_enter, .leave = pointer_leave, .motion = pointer_motion, .button = pointer_button, .axis = pointer_axis }; void keyboard_keymap(LPVOID data, HKEYBOARD wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { } void keyboard_enter(LPVOID data, HKEYBOARD wl_keyboard, uint32_t serial, HSURFACE surface, struct wl_array *keys) { printf("keyboard focus.\n"); } void keyboard_leave(void *data, HKEYBOARD wl_keyboard, uint32_t serial, HSURFACE surface) { } void keyboard_key(void *data, HKEYBOARD wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { if (KEY_F4 == key && WL_KEYBOARD_KEY_STATE_PRESSED == state) { exit(0); } } void keyboard_modifiers(void *data, HKEYBOARD wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { } struct wl_keyboard_listener keyboard_listener = { .keymap = keyboard_keymap, .enter = keyboard_enter, .leave = keyboard_leave, .key = keyboard_key, .modifiers = keyboard_modifiers }; static void handle_ping(LPVOID data, HSHELLSURFACE shell_surface, uint32_t serial) { wl_shell_surface_pong(shell_surface, serial); } static void handle_configure(LPVOID data, HSHELLSURFACE shell_surface, uint32_t edges, int32_t width, int32_t height) { } static void handle_popup_done(LPVOID data, HSHELLSURFACE shell_surface){ } static const struct wl_shell_surface_listener shell_surface_listener = { .ping = handle_ping, .configure = handle_configure, .popup_done = handle_popup_done }; static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { wlGetRegistry()->shm_formats |= (1 << format); } struct wl_shm_listener shm_listenter = { shm_format }; void registry_global(LPVOID data, HREGISTRY registry, uint32_t id, const char *interface, uint32_t version) { if (strcmp(interface, "wl_compositor") == 0) { wlGetRegistry()->s_compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); } else if (strcmp(interface, "wl_shell") == 0) { wlGetRegistry()->s_shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); } else if (strcmp(interface, "wl_shm") == 0) { wlGetRegistry()->s_shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); wl_shm_add_listener(wlGetRegistry()->s_shm, &shm_listenter, NULL); } else if (strcmp(interface, "wl_seat") == 0) { wlGetRegistry()->s_seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); wlGetRegistry()->s_pointer = wl_seat_get_pointer(wlGetRegistry()->s_seat); wlGetRegistry()->s_keyboard = wl_seat_get_keyboard(wlGetRegistry()->s_seat); } } static void registry_global_remove(LPVOID data, HREGISTRY registry, uint32_t name) { } static struct wl_registry_listener registry_listener = { .global = registry_global, .global_remove = registry_global_remove }; int wlInit() { wlGetRegistry()->s_display = wl_display_connect(NULL); HREGISTRY registry = wl_display_get_registry(wlGetRegistry()->s_display); /* wayland的API是异步的,需要给registry设置回掉函数 */ wl_registry_add_listener(registry, &registry_listener, NULL); /* 处理消息 */ wl_display_roundtrip(wlGetRegistry()->s_display); wl_display_get_fd(wlGetRegistry()->s_display); /* 处理鼠标消息 */ wl_pointer_add_listener(wlGetPointer(), &pointer_listener, NULL); wl_keyboard_add_listener(wlGetKeyboard(), &keyboard_listener, NULL); } HSURFACE wlCreateSurface(const char* title, int width, int height) { /* wayland中,窗口被称作surface */ HSURFACE surface = wl_compositor_create_surface(wlGetCompositor()); /* shell_surface具有移动、改变大小、设置标题、最大化、最小化等功能 */ HSHELLSURFACE shell_surface = wl_shell_get_shell_surface(wlGetShell(), surface); /* 窗口的私有数据 */ LPSURFACEPRIVATE surface_priv = (LPSURFACEPRIVATE)malloc(sizeof(SURFACEPRIVATE)); memset(surface_priv, 0, sizeof(SURFACEPRIVATE)); surface_priv->surface = surface; surface_priv->shell_surface = shell_surface; surface_priv->width = width; surface_priv->height = height; wl_surface_set_user_data(surface, surface_priv); /* 设置响应函数 */ wl_shell_surface_add_listener(shell_surface, &shell_surface_listener, NULL); wl_shell_surface_set_title(shell_surface, title); wl_shell_surface_set_toplevel(shell_surface); wl_surface_damage(surface, 0, 0, width, height); return surface; } LPSURFACEPRIVATE _wlGetSurfacePrivate( HSURFACE surface ) { return (LPSURFACEPRIVATE)wl_surface_get_user_data(surface); } void frame_listener_done(void *data, HCALLBACK callback, uint32_t time) { HSURFACE surface = (HSURFACE)data; /* 每次都需要重新设置回调函数 */ _wlSetFrameListener(surface); /* 绘制一帧 */ _wlDrawFrame(surface, time); } static struct wl_callback_listener frame_listener = { .done = frame_listener_done }; void _wlSetFrameListener(HSURFACE surface) { HCALLBACK callback = wl_surface_frame(surface); wl_callback_add_listener(callback, &frame_listener, surface); } void _wlDrawFrame(HSURFACE surface, uint32_t time) { PAINTSTRUCTURE ps; memset(&ps, 0, sizeof(ps)); wlBeginPaint(surface, &ps); wlCallPaintProc(surface, &ps, time); wlEndPaint(surface, &ps); } void wlSetPaintProc(HSURFACE surface, REPAINTPROC surfaceproc) { _wlGetSurfacePrivate(surface)->surfaceproc = surfaceproc; _wlSetFrameListener(surface); _wlDrawFrame(surface, 0); } void wlTerminate() { wl_display_disconnect(wlGetDisplay()); } void buffer_release(void *data, struct wl_buffer *buffer) { LPPAINTBUFFER lpBuffer = data; lpBuffer->busy = 0; } static const struct wl_buffer_listener buffer_listener = { .release = buffer_release }; void _wlCreatePaintStructure(int width, int height, LPPAINTBUFFER lpBuffer) { int stride = width * 4; int size = stride * height; char filename[] = "/tmp/weston-shared-XXXXXX"; int fd = mkstemp(filename); fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); unlink(filename); ftruncate(fd, size); lpBuffer->busy = 0; lpBuffer->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); //lpBuffer->data == MAP_FAILED HSHMPOOL pool = wl_shm_create_pool(wlGetRegistry()->s_shm, fd, size); lpBuffer->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888); wl_buffer_add_listener(lpBuffer->buffer, &buffer_listener, lpBuffer); wl_shm_pool_destroy(pool); close(fd); } void wlBeginPaint(HSURFACE surface, LPPAINTSTRUCTURE lpPaint) { LPSURFACEPRIVATE _priv = _wlGetSurfacePrivate(surface); if (!_priv->buffer[0].busy && _priv->buffer[0].buffer) { lpPaint->buffer = &_priv->buffer[0]; } else if (!_priv->buffer[1].busy && _priv->buffer[1].buffer) { lpPaint->buffer = &_priv->buffer[1]; } else { SIZE sz = wlGetSurfaceSize(surface); _wlCreatePaintStructure(sz.width, sz.height, &_priv->buffer[0]); lpPaint->buffer = &_priv->buffer[0]; } } void wlEndPaint(HSURFACE surface, LPPAINTSTRUCTURE lpPaint) { lpPaint->buffer->busy = 1; wl_surface_attach(surface, lpPaint->buffer->buffer, 0, 0); SIZE sz = wlGetSurfaceSize(surface); wl_surface_damage(surface, 0, 0, sz.width, sz.height); wl_surface_commit(surface); } SIZE wlGetSurfaceSize(HSURFACE surface) { SIZE sz; sz.width = _wlGetSurfacePrivate(surface)->width; sz.height = _wlGetSurfacePrivate(surface)->height; return sz; } int wlDispatch() { return wl_display_dispatch(wlGetDisplay()); } void wlCallPaintProc(HSURFACE hSurface, LPPAINTSTRUCTURE lpPaint, uint32_t time) { LPSURFACEPRIVATE _private = _wlGetSurfacePrivate(hSurface); if (_private->surfaceproc) { _private->surfaceproc(hSurface, lpPaint, time); } } LPWAYLANDREGISTRY wlGetRegistry() { static WAYLANDREGISTRY registry; static int bInit = 1; if (bInit) { memset(&registry, 0, sizeof(registry)); bInit = 0; } return &registry; }
          
         
        
       
      
     
    
   
           

//main.c

void PaintProc(HSURFACE hSurface)
{
	PAINTSTRUCTURE ps;
	memset(&ps, 0, sizeof(ps));
	wlBeginPaint(hSurface, &ps);

	memset(ps.lpBuffer->lpPixelBuffer, 0xff, ps.lpBuffer->length);

	SIZE sz = wlGetSurfaceSize(hSurface);
	//paint_pixels(ps.lpBuffer->lpPixelBuffer, 20, sz.width, sz.height, ps.uTime);
	
	HCAIROSURFACE hCairoSurface = ps.lpBuffer->hCairoSurface; // 类似与 HWND
	HCAIRO hdc = cairo_create(hCairoSurface); // 类似于 HDC

 	cairo_set_source_rgb(hdc,0, 0.4, 0.8);
 	cairo_set_line_width(hdc, 50);
 	cairo_move_to(hdc, 0, 0);
 	cairo_line_to(hdc, sz.width, 0);
 
 	cairo_stroke(hdc);
 
 	cairo_set_source_rgb(hdc, 0 , 0, 0);
 	cairo_move_to(hdc, 10, 20);
 	cairo_set_font_size(hdc, 18);
 	cairo_show_text(hdc, "这是标题栏");
 	cairo_stroke(hdc);


	int btnCloseHeight = 20;
	int btnCloseWidth = 20;
	int btnCloseLineWidth = 2;
	cairo_set_source_rgb(hdc, 1, 0, 0);
	cairo_set_line_width(hdc, 2);
	cairo_move_to(hdc, sz.width-btnCloseWidth, btnCloseLineWidth/2); cairo_line_to(hdc, sz.width, btnCloseLineWidth/2);
	cairo_move_to(hdc, sz.width-btnCloseWidth, 0); cairo_line_to(hdc, sz.width-btnCloseWidth, btnCloseHeight);
	cairo_move_to(hdc, sz.width, 0); cairo_line_to(hdc, sz.width, btnCloseHeight);
	cairo_move_to(hdc, sz.width-btnCloseWidth, btnCloseHeight); cairo_line_to(hdc, sz.width, btnCloseHeight);
	cairo_move_to(hdc, sz.width-btnCloseWidth, btnCloseLineWidth/2); cairo_line_to(hdc, sz.width, btnCloseHeight);
	cairo_move_to(hdc, sz.width, btnCloseLineWidth/2); cairo_line_to(hdc, sz.width-btnCloseWidth, btnCloseHeight);

	cairo_stroke(hdc);

	cairo_set_source_rgb(hdc, 0 , 0, 0);
	cairo_move_to(hdc, 10, sz.height/2);
	cairo_set_font_size(hdc, 30);
	cairo_show_text(hdc, "你好, 中国!");
	cairo_stroke(hdc);

	cairo_set_source_rgb(hdc, 0 , 0, 0);
	cairo_move_to(hdc, 10, sz.height/2+30);
	cairo_set_font_size(hdc, 18);
	cairo_show_text(hdc, "--第三界主");
	cairo_stroke(hdc);


	cairo_destroy(hdc);

	wlRequestPaintDone(hSurface);
	wlEndPaint(hSurface, &ps);
}

void PaintDone(HSURFACE hSurface)
{
	printf("PaintDone\n");
	//wlRequestPaintDone(hSurface);
}

void PointerProc(HSURFACE hSurface, uint32_t button, uint32_t state, uint32_t serial)
{
	LPSURFACEPRIVATE lpSurfacePrivate = wlGetSurfacePrivate(hSurface);

	/* 鼠标左键按下了,移动窗口 */
	if (BTN_LEFT == button && state == WL_POINTER_BUTTON_STATE_PRESSED)
	{
		HSHELLSURFACE hShellSurface = lpSurfacePrivate->hShellSurface;
		wl_shell_surface_move(hShellSurface, wlGetRegistry()->s_seat, serial);
		return;
	}
}

int main(int argc, char **argv)
{
	wlInit();

	int width = 400, height = 300;

	HSURFACE surface = wlCreateSurface("wayland-hello", width, height);

	wlSetPaintProc(surface, PaintProc);
	wlSetPaintDone(surface, PaintDone);
	wlSetPointerProc(surface, PointerProc);

	wlShowSurface(surface);

	int ret = 0;
	while (ret != -1)
	{
		ret = wlDispatch();
	}

	return 0;
}
           

继续阅读