Mercurial > minori
comparison dep/animia/src/win/wayland.cc @ 199:9f3534f6b8c4
dep/animia: initial Wayland support, drop non-working kvm fd plugin
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Tue, 02 Jan 2024 02:34:27 -0500 |
parents | |
children | 8a482049b968 |
comparison
equal
deleted
inserted
replaced
198:bc1ae1810855 | 199:9f3534f6b8c4 |
---|---|
1 #include "animia/win/wayland.h" | |
2 #include "animia/win.h" | |
3 #include "animia.h" | |
4 | |
5 #include <iostream> | |
6 #include <cstring> | |
7 | |
8 #include "animia/win/wayland/ext-foreign-toplevel-list-v1.h" | |
9 #include <wayland-client.h> | |
10 | |
11 namespace animia::internal::wayland { | |
12 | |
13 static void noop() {} | |
14 | |
15 /* ext_foreign_handle stuff */ | |
16 static void ext_foreign_handle_handle_app_id(void* data, struct ext_foreign_toplevel_handle_v1* handle, const char* app_id) { | |
17 if (app_id) | |
18 reinterpret_cast<Window*>(data)->class_name = app_id; | |
19 } | |
20 | |
21 static void ext_foreign_handle_handle_title(void* data, struct ext_foreign_toplevel_handle_v1* handle, const char* title) { | |
22 if (title) | |
23 reinterpret_cast<Window*>(data)->text = title; | |
24 } | |
25 | |
26 static void ext_foreign_handle_handle_done(void* data, struct ext_foreign_toplevel_handle_v1* handle) { | |
27 if (handle) | |
28 ext_foreign_toplevel_handle_v1_destroy(handle); | |
29 } | |
30 | |
31 static void ext_foreign_handle_handle_closed(void*, struct ext_foreign_toplevel_handle_v1*) {} | |
32 static void ext_foreign_handle_handle_identifier(void*, ext_foreign_toplevel_handle_v1*, const char*) {} | |
33 | |
34 static const struct ext_foreign_toplevel_handle_v1_listener ext_handle_listener = { | |
35 .closed = ext_foreign_handle_handle_closed, | |
36 .done = ext_foreign_handle_handle_done, | |
37 .title = ext_foreign_handle_handle_title, | |
38 .app_id = ext_foreign_handle_handle_app_id, | |
39 .identifier = ext_foreign_handle_handle_identifier // for now | |
40 }; | |
41 | |
42 static void ext_toplevel_list_handle_toplevel(void* data, struct ext_foreign_toplevel_list_v1* list, struct ext_foreign_toplevel_handle_v1* handle) { | |
43 std::vector<Window>* windows = reinterpret_cast<std::vector<Window>*>(data); | |
44 if (!windows) | |
45 return; | |
46 | |
47 windows->push_back({0}); | |
48 ext_foreign_toplevel_handle_v1_add_listener(handle, &ext_handle_listener, &*windows->end()); | |
49 } | |
50 | |
51 static void ext_toplevel_list_handle_finished(void*, ext_foreign_toplevel_list_v1*) {} | |
52 | |
53 static const struct ext_foreign_toplevel_list_v1_listener ext_toplevel_list_listener = { | |
54 .toplevel = ext_toplevel_list_handle_toplevel, | |
55 .finished = ext_toplevel_list_handle_finished | |
56 }; | |
57 | |
58 /* -- Global data -- */ | |
59 struct global_data { | |
60 struct ext_foreign_toplevel_list_v1* ext_toplevel_list; | |
61 std::vector<Window> windows; | |
62 }; | |
63 | |
64 static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { | |
65 struct global_data* global = reinterpret_cast<struct global_data*>(data); | |
66 | |
67 if (!std::strcmp(interface, ext_foreign_toplevel_list_v1_interface.name)) { | |
68 // bind to ext-foreign-toplevel-list-v1 | |
69 global->ext_toplevel_list = reinterpret_cast<struct ext_foreign_toplevel_list_v1*>(wl_registry_bind(registry, name, &ext_foreign_toplevel_list_v1_interface, 1)); | |
70 ext_foreign_toplevel_list_v1_add_listener(global->ext_toplevel_list, &ext_toplevel_list_listener, &global->windows); | |
71 } | |
72 } | |
73 | |
74 static void registry_handle_global_remove(void*, wl_registry*, uint32_t) {} | |
75 | |
76 static const struct wl_registry_listener registry_listener = { | |
77 .global = registry_handle_global, | |
78 .global_remove = registry_handle_global_remove | |
79 }; | |
80 | |
81 /* BAH! humbug... */ | |
82 struct sync_data { | |
83 bool loop = true; | |
84 int sync = 0; | |
85 | |
86 struct global_data global = {0}; | |
87 | |
88 struct wl_callback* callback = nullptr; | |
89 struct wl_display* display = nullptr; | |
90 }; | |
91 | |
92 static void sync_handle_done (void* data, struct wl_callback* callback, uint32_t other_data); | |
93 static const struct wl_callback_listener sync_callback_listener = { | |
94 .done = sync_handle_done, | |
95 }; | |
96 | |
97 static void sync_handle_done (void* data, struct wl_callback* callback, uint32_t other_data) { | |
98 struct sync_data* sync = reinterpret_cast<struct sync_data*>(data); | |
99 | |
100 wl_callback_destroy(callback); | |
101 sync->callback = nullptr; | |
102 | |
103 if (sync->sync == 0) { | |
104 if (!sync->global.ext_toplevel_list) { | |
105 std::cerr << "animia/wayland: Wayland server doesn't support ext-foreign-toplevel-list-v1!" << std::endl; | |
106 sync->loop = false; | |
107 return; | |
108 } | |
109 | |
110 sync->sync++; | |
111 sync->callback = wl_display_sync(sync->display); | |
112 wl_callback_add_listener(sync->callback, &sync_callback_listener, sync); | |
113 | |
114 /* we may need another sync here if there are protocol extensions for | |
115 * ext_foreign_toplevel_list. | |
116 * | |
117 * more info: https://git.sr.ht/~leon_plickat/lswt/tree/toplevel-info/item/lswt.c | |
118 */ | |
119 } else { | |
120 /* we've received everything we need! */ | |
121 sync->loop = false; | |
122 } | |
123 } | |
124 | |
125 /* here comes the actual function we can use */ | |
126 bool EnumerateWindows(window_proc_t window_proc) { | |
127 struct sync_data sync = { | |
128 .display = wl_display_connect(NULL) | |
129 }; | |
130 | |
131 if (!sync.display) { | |
132 std::cerr << "animia/wayland: Can't connect to display" << std::endl; | |
133 return false; | |
134 } | |
135 | |
136 struct global_data global; | |
137 | |
138 struct wl_registry* registry = wl_display_get_registry(sync.display); | |
139 wl_registry_add_listener(registry, ®istry_listener, &sync.global); | |
140 | |
141 sync.callback = wl_display_sync(sync.display); | |
142 wl_callback_add_listener(sync.callback, &sync_callback_listener, &sync); | |
143 | |
144 while (sync.loop && wl_display_dispatch(sync.display)); | |
145 | |
146 for (const auto& window : global.windows) | |
147 if (!window_proc({0}, window)) | |
148 return false; | |
149 | |
150 wl_display_disconnect(sync.display); | |
151 | |
152 return true; | |
153 } | |
154 | |
155 } |