第一个Wayland程序

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

效果图:

第一个Wayland程序_第1张图片


程序源代码:

//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, ®istry_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(®istry, 0, sizeof(registry));
		bInit = 0;
	}

	return ®istry;
}

//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;
}


你可能感兴趣的:(第一个Wayland程序)