在介绍这些类的时候我必须给大家把wayland的interface分个类.
- Global Object, 我把它叫做服务类, 就是提供给客户端各种功能的接口. 就相当于是说,对于客户端来说,我给你提供了哪些服务,你就只能通过这些服务来进行各种操作,因此,服务越多,肯定功能越多.服务类,根据实际情况是不一样的,并且可以根据需要服务端再添加更多的服务,wayland标准提供的服务接口有以下一些:
- wl_compositor
- wl_shm
- wl_shell
- wl_seat
- wl_output
- wl_subcompositor
- wl_data_device_manager
- 依赖服务创建的接口类. 为什么这么说呢? 因为这样的接口对象,都是通过服务类提供的接口产生的.
理解wayland就要明白, wayland的所有对象都是道生一,一生二,二生三,三生万物. 通俗一点,就是wayland给你提供了道(wl_display), 后续的所有对象都是基于它产生的. 你最终能产生多少对象完全看你怎么去发挥了。
- wl_display
这个是wayland协议的核心类,它作为客户端的标识,一个wl_display对象代表着一个客户端,因为这个对象建立了和wayland服务器通信的socket,所有和服务器交互都是通过这个socket。这个也是客户端必须第一个创建的wayland对象。也就是我上面所说的‘道’。
wl_display接口类提供了两个请求函数,和两个事件函数。前面我说过了,关于什么是请求和事件。但是,对于wl_display这个接口对象,它的事件处理函数,是wayland源码里面提供的。用户在不修改源码的情况下,是不能再设置的。接下来说说这几个函数:
- sync,这个请求函数的作用是返回一个wl_callback对象,这个对象有个事件release,是当服务器端处理你这个sync请求后主动调用的,也就是说,当你调用sync之后,你设置了release事件处理函数,那么当你的release处理函数被调用的时候,就代表你当前的请求已经得到响应了。这个接口的作用是提供客户端一个确认你前面所有的请求都被处理的保证。(wayland有个接口wl_display_roundtrip就是利用了这一点,因此,你完全可以自己实现这个功能,通过这个请求。)
- get_registry,这个请求基本是客户端调用的第二个wayland函数(第一个是获取wl_display的函数),然后返回一个wl_registry对象,这个对象是干什么的?这个对象就是可以告诉你,wayland服务器端给你通过了哪些你可以使用的服务。这些服务才是你创建wayland窗口的核心。
- error, 这个函数是在服务器端向客户端报错用的。
- delete_id,这个接口是在服务器端删除客户端对象的时候用的,目的是告诉客户端,某一个对象可以安全的delete了。
- wl_registry
这个也是wayland的核心类,这个类对象通过wl_display的请求函数得到,然后服务器端收到这个请求之后就会传递给客户端,目前可以使用的所有服务信息。客户端再根据自己的需要,通过bind这个请求函数得到服务的对象,就可以使用这些服务提供的接口了。
- bind,请求函数,得到指定服务的对象,后面的操作就需要这些服务对象来调用接口。
- global,事件函数,通过这个函数客户端(一次调用得到一个服务信息,服务器端有多少服务,这个事件函数就会调用多少次。)
- global_remove, 事件函数,这个函数也很明了,和上一个相反,当服务器端某一个服务停止了,就会调用这个事件告诉客户端这个服务已经不提供了,不能再通过这个服务获取请求。
- wl_callback
这个接口就是单纯通过给客户端,同步各类请求的接口。只有一个事件函数,done,当服务器端收到创建这个对象的时候,立马就往客户端发送done事件。
- done,事件函数,当wl_callback对象创建请求被服务器端收到并创建的时候,立马调用。这个函数有个参数,提供给客户端用来修改,方便知道这个函数已经被调用了。
- wl_compositor
这个就是创建窗口的灵魂,因为它是wayland提供创建窗口的服务。
- create_surface,这个请求函数用来创建窗口绘制的实体,但是它不是真正的窗口,只是窗口上面的内容,意思就是,可能存在很多的窗口,这些窗口上面的内容都是这个surface。后面我会专门拿一章来详细说明这一点。这个接口返回wl_surface对象。
- create_region,这个请求函数返回一个wl_region对象,这个对象的作用是描述一块wl_surface上的区域,以便对这个区域进行操作。
- wl_region
窗口区域。
请求函数:
- destroy
- add
- subtract
- wl_shm
这个是wayland提供的客户端和服务器端共享内存的服务。共享内存一般是用来作为窗口绘制内容的容器(相当于保存图片内容的内存)。因此,这个接口提供了一个枚举类型format来描述这个内存是什么格式的,因为不同的屏幕使用不同的图片格式。这个服务还提供了一个错误类型的枚举error。
- create_pool,这个是请求函数,用来得到一个共享内存的对象wl_shm_pool,用于客户端和服务器端的共享。(原理是客户端传递给服务器端内存的文件描述符句柄fd,服务器端再通过这个文件描述符句柄操作那段内存)
- format,这个是事件函数,当服务器端收到这个服务的绑定请求的时候就会发送给客户端。告诉客户端目前支持的图片格式有哪些。(应该也是一种格式调用一次)
- wl_shm_pool
这个就是共享内存对象,一般操作方式就是客户端创建一个fd,然后mmap到一段内存,以供客户端使用,最后把这个fd传递给服务器端,让服务器端去读取它(一般情况是,客户端写,服务器端读)。但是,对于窗口的绘制,不是使用这个对象,而是通过这个对象的请求函数create_buffer函数返回的wl_buffer对象作为真正保存客户端绘制窗口内容的实体。因此,很多情况下都是需要多大的wl_buffer就创建对应多大的wl_shm_pool,至少我在Qtwayland的源码里面就发现是这样的,因此wl_buffer和wl_shm_pool是1:1的关系。
- create_buffer,请求函数,利用共享内存的空间来创建窗口绘制使用的wl_buffer。如果,想一个wl_shm_pool对象创建多个wl_buffer就需要去切割内存,并管理,这个是比较麻烦的一件事,因此使wl_shm_pool和wl_buffer 1:1对应,最简单。
- destroy, 请求函数,用来销毁共享内存池
- resize,请求函数,用来改变内存池大小,这个是很麻烦的,因为客户端需要你自己去重新映射内存,并且只能变大不能变小。因此,一般不用这个接口,想要更大的空间就重新再申请一个,也不去调用这个接口扩大。
- wl_buffer
这个对象就是wl_shm_pool提供的接口返回的(wayland文档描述,wl_buffer还可以通过其他的途径创建,比如wl_drm),并且这个wl_buffer基本是和wl_surface大小绑定的,也就是wl_surface有多大,wl_buffer就有多大。
- destroy,这个请求函数用来销毁一个wl_buffer
- release,这个事件函数,是在服务器端已经读取过该wl_buffer之后,主动发送的事件,告诉客户端这个buffer客户端可以重复使用了,一般用来再重绘。如果没有收到这个事件,那么这个wl_buffer理论上就不能再修改。
- wl_surface
这个是由wl_compositor通过的接口创建的窗口绘制的抽象实体,但并不是真正的显示屏上看到的窗口,所以这个就是合成器管理的核心,他把所有的窗口都抽象成这样的数据结构,然后最终再输出到不同的外设,显示真正的窗口(wl_shell_surface等)。这个对象实际的内容保存在wl_buffer中。
请求函数:
- destroy
- attach,绑定wl_buffer到wl_surface
- damage
- frame
- set_opaque_region
- set_input_region
- set_buffer_transform
- set_buffer_scale
- damage_buffer
- commit
事件函数:
- enter
- leave
- wl_shell
这个是管理真正窗口的服务接口类。通过这个接口,可以创建某一个wl_surface的显示用窗口,当然,你也可以创建多个同一个wl_surface的窗口,这样就显示多个一模一样的窗口了。这个服务接口有很多同类的服务(比如xdg_shell等)。就相当于,你可以窗口linux下的窗口,也可以创建winodws下的窗口一样。这个有点像Qt的思想,这个就相当于Qt的显示后端一样。
- get_shell_surface,请求函数,创建指定wl_surface的显示窗口对象wl_shell_surface。一般情况下,一个wl_surface对应一个wl_shell_surface。但,你完全可以一对多。
- wl_shell_surface
这个就是真正的窗口了。但是由于wl_shell协议功能不完善,无法支持一些功能特性,所以官方在文档都说明了,将会用xdg_shell替代,创建xdg_shell_surface窗口。但,这两种协议的窗口本来就是同等的,可以同时存在。
请求函数
- pong, 用来响应ping事件函数,相当于网络通信的心跳包,确认有效性,如果不调用,就相当于窗口无响应,可能被杀掉该窗口。
- move
- resize
- set_toplevel
- transient
- set_transient
- set_fullscreen
- set_popup
- set_maximized
- set_title
- set_class
事件函数:
- ping
- configure
- popup_done
- wl_seat
这个是服务类接口,提供客户端获取键盘鼠标事件的能力以及触摸屏。并且设备可能有很多套,因此,用name去区分不同的设备。
请求函数:
- get_pointer
- get_keyboard
- get_touch
- release
事件函数:
- capabilities,首先提供事件事件函数获取到,当前这个seat支持哪些事件的监听,再创建对应的可以使用的对象(请求函数的返回对象)。
- name
- wl_pointer
监听鼠标数据的对象。
请求函数
- set_cursor
- release
事件函数
- enter
- leave
- motion
- button
- axis
- frame
- axis_source
- axis_stop
- axis_discrete
- wl_keyboard
监听键盘事件的对象。
请求函数:
- release
事件函数:
- keymap
- enter
- leave
- key
- repeat_info
- wl_touch
监听触摸屏事件的对象。
请求函数:
- release
事件函数:
- down
- up
- motion
- frame
- cancel
- shape,看到没有,纯天然的手势支持服务(当然要看服务端有没有实现了T_T)
- orientation
- wl_output
这个是服务对象,代表着屏幕。一个屏幕对应一个服务对象,因此,如果有多屏幕,这个服务就有多个。屏幕可以通过事件函数获取它的大小,刷新率等属性
请求函数:
- release
事件函数:
- geometry
- mode
- done
- scale
以下子窗口系统暂时没怎么用过,不熟悉,暂时不说
- wl_subcompositor
子窗口服务提供类。感觉没有这个也不影响。
- wl_subsurface
wl_subcompositor接口创建的子窗口。
以下是用于进程间拖拽使用的接口类,我没怎么用过,暂时不说。
- wl_data_device_manager
拖拽服务接口类
- wl_data_source
- wl_data_device
以上就是所有wayland.xml里面的接口类了,通过这些接口就可以创建窗口,并完成操作,但是还有一些功能这里还不够,因为目前还有一些协议在weston这个项目里面使用的,还没有纳入wayland标准协议,比如:xdg_shell: 另一种替代wl_shell的窗口协议,zwp_text_input_v1: 输入法管理协议,wl_drm协议(这个是在libdrm这个库里面提供的)等等。(具体的可以查看:https://github.com/wayland-project/wayland-protocols)