系列索引地址:Wayland入门系列教程索引
上一篇:Wayland入门13:输入设备管理器
之前文章中我们创建了一个空白窗口,接下来我们处理一下窗口上的鼠标操作。
先把新建窗口的代码复制过来。然后把seat的部分代码复制过来,在注册函数中添加seat处理部分。
Wayland只提供了wl_pointer_listener,要想获取鼠标相关的消息需要首先设置监听器。
wl_pointer的消息有:
- enter 进入窗口范围
- leave 离开窗口范围
- motion 鼠标移动
- button 鼠标点击,鼠标按键id定义位于文件<linux/input.h>中,例如BTN_LEFT表示鼠标左键。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| static void global_registry_handler(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { if (strcmp(interface, "wl_compositor") == 0) { BIND_WL_REG(registry, compositor, id, &wl_compositor_interface, 1); }else if (strcmp(interface, "wl_shell") == 0){ BIND_WL_REG(registry, shell, id, &wl_shell_interface, 1); }else if (strcmp(interface, "wl_shm") == 0){ BIND_WL_REG(registry, shm, id, &wl_shm_interface, 1); wl_shm_add_listener(shm, &shm_listener, NULL); }else if(strcmp(interface, "wl_seat")==0){ BIND_WL_REG(registry, seat, id, &wl_seat_interface, 1); wl_seat_add_listener(seat,&seat_listener,NULL); } }
|
添加一个seat_listener结构体
| static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, };
|
添加seat_listener的回调函数
| static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) { if ((caps & WL_SEAT_CAPABILITY_POINTER) && !pointer) { pointer = wl_seat_get_pointer(seat); wl_pointer_add_listener(pointer, &pointer_listener, NULL); }else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && pointer){ wl_pointer_destroy(pointer); pointer = NULL; } }
|
分两种情况,第一种是输入设备是鼠标并且指针不为空那么就表示当前状态有效,第二种是输入设备为鼠标但是指针为空表示鼠标已经离开窗口了。
添加pointer_listener函数。
| static const struct wl_pointer_listener pointer_listener = { pointer_handle_enter, pointer_handle_leave, pointer_handle_motion, pointer_handle_button, pointer_handle_axis, };
|
有四种情况:进入、离开、移动、点击、坐标系。四种情况对应的函数为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy) { fprintf(stderr, "Pointer entered surface %p at %d %d\n", surface, sx, sy); }
static void pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { fprintf(stderr, "Pointer left surface %p\n", surface); }
static void pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy) { printf("Pointer moved at %d %d\n", sx, sy); }
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { printf("Pointer button\n"); if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) wl_shell_surface_move(shell_surface, seat, serial); }
static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { printf("Pointer handle axis\n"); }
|
效果为:

可以看到坐标点的数据不对劲,坐标数据类型为int32_t wl_fixed_t
,根据wayland-util.h
描述其为带一个有符号位的24.8有符号定点数、带8位十进制的23位整型数。wayland提供了函数用于转换。
效果为:

这样看起来就正常了。
EGL版本只是替换了窗口显示部分,其他的代码一样。
完整代码在Wayland_Freshman中的14.pointer
、14.pointer_EGL
下。
下一篇:Wayland入门15:窗口操作