XWayland开发入门系列8:获取全局对象

系列索引地址:X11/Wayland开发入门系列教程索引

上一篇:XWayland开发入门系列7:连接server

Wayland全局对象

几乎所有的Wayland API都需要Wayland全局对象作为参数。Wayland全局对象:

  • wl_display:表示与服务器的连接。
  • wl_registry:全局对象注册表,全局对象需要通过它获取。
  • wl_compositor:窗口合成器,也是服务器。
  • wl_shm:内存管理器,与窗口合成器共享内存用。
  • wl_shell:支持窗口操作功能。
  • wl_seat:输入设备管理器。
  • wl_pointer:代表鼠标设备。
  • wl_keyboard:代表键盘设备。

Wayland没有提供Get函数来获取以上全局对象,只能通过wl_registry获取全局对象。

首先创建wl_registry_listener对象:

1
2
3
4
5
static struct wl_registry_listener s_registryListener
{
.global = on_global_added,
.global_remove = on_global_removed
};

.global和.global_remove是此结构体提供的两个回调函数指针,我们要自己实现这些函数。

也可以直接写

1
2
3
4
5
static struct wl_registry_listener s_registryListener
{
on_global_added,
on_global_removed
};

看你喜欢哪一种写法。

然后设置回调函数

1
2
3
4
5
6
7
8
9
struct wl_registry *reg = wl_display_get_registry(disp);
if (!reg) {
std::cerr << "Faild to get registry!" << std::endl;
}

std::cerr << "Got registry OK!" << std::endl;

wl_registry_add_listener(reg, &s_registryListener, nullptr);
// wl_registry_destroy(reg);

在回调函数中继续处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
static void on_global_added(void *data,
struct wl_registry *wl_registry,
uint32_t name,
const char *interface,
uint32_t version)
{
(void)data;
(void)wl_registry;
std::cerr << " Global added: " << interface
<< ", v" << version
<< " (name " << name << ")"
<< std::endl;
}

在此就只是输出名称、版本。

编译运行,Ubuntu21.04输出为:

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
XDG_RUNTIME_DIR = /run/user/1000
Connect OK!
Got registry OK!
Global added: wl_drm, v2 (name 1)
Global added: wl_compositor, v4 (name 2)
Global added: wl_shm, v1 (name 3)
Global added: wl_output, v2 (name 4)
Global added: zxdg_output_manager_v1, v3 (name 5)
Global added: wl_data_device_manager, v3 (name 6)
Global added: zwp_primary_selection_device_manager_v1, v1 (name 7)
Global added: gtk_primary_selection_device_manager, v1 (name 8)
Global added: wl_subcompositor, v1 (name 9)
Global added: xdg_wm_base, v3 (name 10)
Global added: zxdg_shell_v6, v1 (name 11)
Global added: wl_shell, v1 (name 12)
Global added: gtk_shell1, v3 (name 13)
Global added: wp_viewporter, v1 (name 14)
Global added: zwp_pointer_gestures_v1, v1 (name 15)
Global added: zwp_tablet_manager_v2, v1 (name 16)
Global added: wl_seat, v5 (name 17)
Global added: zwp_relative_pointer_manager_v1, v1 (name 18)
Global added: zwp_pointer_constraints_v1, v1 (name 19)
Global added: zxdg_exporter_v1, v1 (name 20)
Global added: zxdg_importer_v1, v1 (name 21)
Global added: zwp_linux_dmabuf_v1, v3 (name 22)
Global added: zwp_keyboard_shortcuts_inhibit_manager_v1, v1 (name 23)
Global added: zwp_text_input_manager_v3, v1 (name 24)
Global added: gtk_text_input_manager, v1 (name 25)
Sleeping for 3 secs...

在回调函数中我们并没有使用最关键的wl_registry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define BIND_WL_REG(registry, ptr, id, intf, n)\
do { (ptr) = (typeof(ptr))wl_registry_bind(\
registry, id, intf, n); } while(0)

static void
global_registry_handler(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version) {
printf("Got a registry event for %s id %d\n", interface, id);
if (strcmp(interface, "wl_compositor") == 0) {
//compositor = (struct wl_compositor *)wl_registry_bind(registry, id,
// &wl_compositor_interface, 1);
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);
}
}

获取并绑定全局变量和registry。

然后获取渲染器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if (compositor == NULL) {
fprintf(stderr, "Can't find compositor\n");
exit(1);
} else {
fprintf(stderr, "Found compositor\n");
}

surface = wl_compositor_create_surface(compositor);
if (surface == NULL) {
fprintf(stderr, "Can't create surface\n");
exit(1);
} else {
fprintf(stderr, "Created surface\n");
}

shell_surface = wl_shell_get_shell_surface(shell, surface);
if (shell_surface == NULL) {
fprintf(stderr, "Can't create shell surface\n");
exit(1);
} else {
fprintf(stderr, "Created shell surface\n");
}
wl_shell_surface_set_toplevel(shell_surface);

输出为:

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
connected to display
Got a registry event for wl_drm id 1
Got a registry event for wl_compositor id 2
Got a registry event for wl_shm id 3
Got a registry event for wl_output id 4
Got a registry event for zxdg_output_manager_v1 id 5
Got a registry event for wl_data_device_manager id 6
Got a registry event for zwp_primary_selection_device_manager_v1 id 7
Got a registry event for gtk_primary_selection_device_manager id 8
Got a registry event for wl_subcompositor id 9
Got a registry event for xdg_wm_base id 10
Got a registry event for zxdg_shell_v6 id 11
Got a registry event for wl_shell id 12
Got a registry event for gtk_shell1 id 13
Got a registry event for wp_viewporter id 14
Got a registry event for zwp_pointer_gestures_v1 id 15
Got a registry event for zwp_tablet_manager_v2 id 16
Got a registry event for wl_seat id 17
Got a registry event for zwp_relative_pointer_manager_v1 id 18
Got a registry event for zwp_pointer_constraints_v1 id 19
Got a registry event for zxdg_exporter_v1 id 20
Got a registry event for zxdg_importer_v1 id 21
Got a registry event for zwp_linux_dmabuf_v1 id 22
Got a registry event for zwp_keyboard_shortcuts_inhibit_manager_v1 id 23
Got a registry event for zwp_text_input_manager_v3 id 24
Got a registry event for gtk_text_input_manager id 25
Found compositor
Created surface
Created shell surface
disconnected from display

完整代码在Wayland_Frashman的8.interface中。

如果是使用wldbg进行测试,需要注意的是wldbg捕获到连接信号后阻塞,如果要继续输出registry信息需要按下c

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
hyper@ubuntu:~$ wldbg -s
Listening for incoming connections...
Stopped on the first message
[interface2 ] C: wl_display@1.get_registry(new id wl_registry@2)
(wldbg) c
[interface2 ] S: wl_registry@2.global(1, 7:"wl_drm", 2)
[interface2 ] S: wl_registry@2.global(2, 14:"wl_compositor", 4)
[interface2 ] S: wl_registry@2.global(3, 7:"wl_shm", 1)
[interface2 ] S: wl_registry@2.global(4, 10:"wl_output", 2)
[interface2 ] S: wl_registry@2.global(5, 23:"zxdg_output_manager_v1", 3)
[interface2 ] S: wl_registry@2.global(6, 23:"wl_data_device_manager", 3)
[interface2 ] S: wl_registry@2.global(7, 40:"zwp_primary_selection_device_manager_v1", 1)
[interface2 ] S: wl_registry@2.global(8, 37:"gtk_primary_selection_device_manager", 1)
[interface2 ] S: wl_registry@2.global(9, 17:"wl_subcompositor", 1)
[interface2 ] S: wl_registry@2.global(10, 12:"xdg_wm_base", 3)
[interface2 ] S: wl_registry@2.global(11, 14:"zxdg_shell_v6", 1)
[interface2 ] S: wl_registry@2.global(12, 9:"wl_shell", 1)
[interface2 ] S: wl_registry@2.global(13, 11:"gtk_shell1", 3)
[interface2 ] S: wl_registry@2.global(14, 14:"wp_viewporter", 1)
[interface2 ] S: wl_registry@2.global(15, 24:"zwp_pointer_gestures_v1", 1)
[interface2 ] S: wl_registry@2.global(16, 22:"zwp_tablet_manager_v2", 1)
[interface2 ] S: wl_registry@2.global(17, 8:"wl_seat", 5)
[interface2 ] S: wl_registry@2.global(18, 32:"zwp_relative_pointer_manager_v1", 1)
[interface2 ] S: wl_registry@2.global(19, 27:"zwp_pointer_constraints_v1", 1)
[interface2 ] S: wl_registry@2.global(20, 17:"zxdg_exporter_v1", 1)
[interface2 ] S: wl_registry@2.global(21, 17:"zxdg_importer_v1", 1)
[interface2 ] S: wl_registry@2.global(22, 20:"zwp_linux_dmabuf_v1", 3)
[interface2 ] S: wl_registry@2.global(23, 42:"zwp_keyboard_shortcuts_inhibit_manager_v1", 1)
[interface2 ] S: wl_registry@2.global(24, 26:"zwp_text_input_manager_v3", 1)
[interface2 ] S: wl_registry@2.global(25, 23:"gtk_text_input_manager", 1)
[interface2 ] C: wl_registry@2.bind(2, 14:"wl_compositor", 1, new id [unknown]@3)
[interface2 ] C: wl_registry@2.bind(12, 9:"wl_shell", 1, new id [unknown]@4)
[interface2 ] C: wl_display@1.sync(new id wl_callback@5)
[interface2 ] S: wl_callback@5.done(6998)
[interface2 ] S: wl_display@1.delete_id(5)

下一篇:XWayland开发入门系列9:第一个窗口