Mercurial > minori
comparison dep/animia/src/win/wayland.cc @ 216:8a482049b968
dep/animia: win/wayland: add UNTESTED support for wlroots protocols
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Sun, 07 Jan 2024 12:42:10 -0500 |
parents | 9f3534f6b8c4 |
children | 2f6d27fcdf7d |
comparison
equal
deleted
inserted
replaced
215:031a257ee019 | 216:8a482049b968 |
---|---|
1 #include "animia/win/wayland.h" | 1 #include "animia/win/wayland.h" |
2 #include "animia.h" | |
2 #include "animia/win.h" | 3 #include "animia/win.h" |
3 #include "animia.h" | 4 |
4 | 5 #include <cstring> |
5 #include <iostream> | 6 #include <iostream> |
6 #include <cstring> | |
7 | 7 |
8 #include "animia/win/wayland/ext-foreign-toplevel-list-v1.h" | 8 #include "animia/win/wayland/ext-foreign-toplevel-list-v1.h" |
9 #include "animia/win/wayland/wlr-foreign-toplevel-management-unstable-v1.h" | |
9 #include <wayland-client.h> | 10 #include <wayland-client.h> |
10 | 11 |
11 namespace animia::internal::wayland { | 12 namespace animia::internal::wayland { |
12 | 13 |
13 static void noop() {} | 14 /* zwlr-foreign-toplevel-management-v1 implementation */ |
14 | 15 static void zwlr_foreign_handle_handle_title(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, |
15 /* ext_foreign_handle stuff */ | 16 const char* title) { |
16 static void ext_foreign_handle_handle_app_id(void* data, struct ext_foreign_toplevel_handle_v1* handle, const char* app_id) { | 17 if (title) |
18 reinterpret_cast<Window*>(data)->text = title; | |
19 } | |
20 | |
21 static void zwlr_foreign_handle_handle_app_id(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, | |
22 const char* app_id) { | |
17 if (app_id) | 23 if (app_id) |
18 reinterpret_cast<Window*>(data)->class_name = app_id; | 24 reinterpret_cast<Window*>(data)->class_name = app_id; |
19 } | 25 } |
20 | 26 |
21 static void ext_foreign_handle_handle_title(void* data, struct ext_foreign_toplevel_handle_v1* handle, const char* title) { | 27 static void zwlr_foreign_handle_handle_done(void* data, struct zwlr_foreign_toplevel_handle_v1* handle) { |
28 if (handle) | |
29 zwlr_foreign_toplevel_handle_v1_destroy(handle); | |
30 } | |
31 | |
32 static void zwlr_foreign_handle_handle_state(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, | |
33 struct wl_array*) { | |
34 } | |
35 | |
36 static void zwlr_foreign_handle_handle_parent(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, | |
37 struct zwlr_foreign_toplevel_handle_v1*) { | |
38 } | |
39 | |
40 static void zwlr_foreign_handle_handle_output_enter(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, | |
41 struct wl_output*) { | |
42 } | |
43 | |
44 static void zwlr_foreign_handle_handle_output_leave(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, | |
45 struct wl_output*) { | |
46 } | |
47 | |
48 static void zwlr_foreign_handle_handle_closed(void* data, struct zwlr_foreign_toplevel_handle_v1* handle) { | |
49 } | |
50 | |
51 static const struct zwlr_foreign_toplevel_handle_v1_listener zwlr_handle_listener = { | |
52 .title = zwlr_foreign_handle_handle_title, | |
53 .app_id = zwlr_foreign_handle_handle_app_id, | |
54 .output_enter = zwlr_foreign_handle_handle_output_enter, | |
55 .output_leave = zwlr_foreign_handle_handle_output_leave, | |
56 .state = zwlr_foreign_handle_handle_state, | |
57 .done = zwlr_foreign_handle_handle_done, | |
58 .closed = zwlr_foreign_handle_handle_closed, | |
59 .parent = zwlr_foreign_handle_handle_parent}; | |
60 | |
61 static void zwlr_toplevel_manager_handle_toplevel(void* data, struct zwlr_foreign_toplevel_manager_v1* manager, | |
62 struct zwlr_foreign_toplevel_handle_v1* handle) { | |
63 std::vector<Window>* windows = reinterpret_cast<std::vector<Window>*>(data); | |
64 if (!windows) | |
65 return; | |
66 | |
67 windows->push_back({0}); | |
68 zwlr_foreign_toplevel_handle_v1_add_listener(handle, &zwlr_handle_listener, &*windows->end()); | |
69 } | |
70 | |
71 static void zwlr_toplevel_manager_handle_finished(void*, struct zwlr_foreign_toplevel_manager_v1*) { | |
72 } | |
73 | |
74 static const struct zwlr_foreign_toplevel_manager_v1_listener zwlr_toplevel_manager_listener = { | |
75 .toplevel = zwlr_toplevel_manager_handle_toplevel, | |
76 .finished = zwlr_toplevel_manager_handle_finished, | |
77 }; | |
78 | |
79 /* ext_foreign_handle stuff */ | |
80 static void ext_foreign_handle_handle_app_id(void* data, struct ext_foreign_toplevel_handle_v1* handle, | |
81 const char* app_id) { | |
82 if (app_id) | |
83 reinterpret_cast<Window*>(data)->class_name = app_id; | |
84 } | |
85 | |
86 static void ext_foreign_handle_handle_title(void* data, struct ext_foreign_toplevel_handle_v1* handle, | |
87 const char* title) { | |
22 if (title) | 88 if (title) |
23 reinterpret_cast<Window*>(data)->text = title; | 89 reinterpret_cast<Window*>(data)->text = title; |
24 } | 90 } |
25 | 91 |
26 static void ext_foreign_handle_handle_done(void* data, struct ext_foreign_toplevel_handle_v1* handle) { | 92 static void ext_foreign_handle_handle_done(void* data, struct ext_foreign_toplevel_handle_v1* handle) { |
27 if (handle) | 93 if (handle) |
28 ext_foreign_toplevel_handle_v1_destroy(handle); | 94 ext_foreign_toplevel_handle_v1_destroy(handle); |
29 } | 95 } |
30 | 96 |
31 static void ext_foreign_handle_handle_closed(void*, struct ext_foreign_toplevel_handle_v1*) {} | 97 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*) {} | 98 } |
99 | |
100 static void ext_foreign_handle_handle_identifier(void*, ext_foreign_toplevel_handle_v1*, const char*) { | |
101 } | |
33 | 102 |
34 static const struct ext_foreign_toplevel_handle_v1_listener ext_handle_listener = { | 103 static const struct ext_foreign_toplevel_handle_v1_listener ext_handle_listener = { |
35 .closed = ext_foreign_handle_handle_closed, | 104 .closed = ext_foreign_handle_handle_closed, |
36 .done = ext_foreign_handle_handle_done, | 105 .done = ext_foreign_handle_handle_done, |
37 .title = ext_foreign_handle_handle_title, | 106 .title = ext_foreign_handle_handle_title, |
38 .app_id = ext_foreign_handle_handle_app_id, | 107 .app_id = ext_foreign_handle_handle_app_id, |
39 .identifier = ext_foreign_handle_handle_identifier // for now | 108 .identifier = ext_foreign_handle_handle_identifier // for now |
40 }; | 109 }; |
41 | 110 |
42 static void ext_toplevel_list_handle_toplevel(void* data, struct ext_foreign_toplevel_list_v1* list, struct ext_foreign_toplevel_handle_v1* handle) { | 111 static void ext_toplevel_list_handle_toplevel(void* data, struct ext_foreign_toplevel_list_v1* list, |
112 struct ext_foreign_toplevel_handle_v1* handle) { | |
43 std::vector<Window>* windows = reinterpret_cast<std::vector<Window>*>(data); | 113 std::vector<Window>* windows = reinterpret_cast<std::vector<Window>*>(data); |
44 if (!windows) | 114 if (!windows) |
45 return; | 115 return; |
46 | 116 |
47 windows->push_back({0}); | 117 windows->push_back({0}); |
48 ext_foreign_toplevel_handle_v1_add_listener(handle, &ext_handle_listener, &*windows->end()); | 118 ext_foreign_toplevel_handle_v1_add_listener(handle, &ext_handle_listener, &*windows->end()); |
49 } | 119 } |
50 | 120 |
51 static void ext_toplevel_list_handle_finished(void*, ext_foreign_toplevel_list_v1*) {} | 121 static void ext_toplevel_list_handle_finished(void*, ext_foreign_toplevel_list_v1*) { |
122 } | |
52 | 123 |
53 static const struct ext_foreign_toplevel_list_v1_listener ext_toplevel_list_listener = { | 124 static const struct ext_foreign_toplevel_list_v1_listener ext_toplevel_list_listener = { |
54 .toplevel = ext_toplevel_list_handle_toplevel, | 125 .toplevel = ext_toplevel_list_handle_toplevel, .finished = ext_toplevel_list_handle_finished}; |
55 .finished = ext_toplevel_list_handle_finished | |
56 }; | |
57 | 126 |
58 /* -- Global data -- */ | 127 /* -- Global data -- */ |
59 struct global_data { | 128 struct global_data { |
60 struct ext_foreign_toplevel_list_v1* ext_toplevel_list; | 129 struct ext_foreign_toplevel_list_v1* ext_toplevel_list = nullptr; |
130 struct zwlr_foreign_toplevel_manager_v1* zwlr_toplevel_mgr = nullptr; | |
61 std::vector<Window> windows; | 131 std::vector<Window> windows; |
62 }; | 132 }; |
63 | 133 |
64 static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { | 134 static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, |
135 uint32_t version) { | |
65 struct global_data* global = reinterpret_cast<struct global_data*>(data); | 136 struct global_data* global = reinterpret_cast<struct global_data*>(data); |
66 | 137 |
67 if (!std::strcmp(interface, ext_foreign_toplevel_list_v1_interface.name)) { | 138 if (!std::strcmp(interface, ext_foreign_toplevel_list_v1_interface.name)) { |
68 // bind to ext-foreign-toplevel-list-v1 | 139 if (!global->zwlr_toplevel_mgr || version < 3) |
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)); | 140 return; // we don't need this then |
70 ext_foreign_toplevel_list_v1_add_listener(global->ext_toplevel_list, &ext_toplevel_list_listener, &global->windows); | 141 |
142 global->ext_toplevel_list = reinterpret_cast<struct ext_foreign_toplevel_list_v1*>( | |
143 wl_registry_bind(registry, name, &ext_foreign_toplevel_list_v1_interface, 1)); | |
144 | |
145 ext_foreign_toplevel_list_v1_add_listener(global->ext_toplevel_list, &ext_toplevel_list_listener, | |
146 &global->windows); | |
147 } else if (!std::strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name)) { | |
148 if (!global->ext_toplevel_list) | |
149 return; // we don't need this then | |
150 | |
151 global->zwlr_toplevel_mgr = reinterpret_cast<struct zwlr_foreign_toplevel_manager_v1*>( | |
152 wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 1)); | |
153 | |
154 zwlr_foreign_toplevel_manager_v1_add_listener(global->zwlr_toplevel_mgr, &zwlr_toplevel_manager_listener, | |
155 &global->windows); | |
71 } | 156 } |
72 } | 157 } |
73 | 158 |
74 static void registry_handle_global_remove(void*, wl_registry*, uint32_t) {} | 159 static void registry_handle_global_remove(void*, wl_registry*, uint32_t) { |
75 | 160 } |
76 static const struct wl_registry_listener registry_listener = { | 161 |
77 .global = registry_handle_global, | 162 static const struct wl_registry_listener registry_listener = {.global = registry_handle_global, |
78 .global_remove = registry_handle_global_remove | 163 .global_remove = registry_handle_global_remove}; |
79 }; | |
80 | 164 |
81 /* BAH! humbug... */ | 165 /* BAH! humbug... */ |
82 struct sync_data { | 166 struct sync_data { |
83 bool loop = true; | 167 bool loop = true; |
84 int sync = 0; | 168 int sync = 0; |
87 | 171 |
88 struct wl_callback* callback = nullptr; | 172 struct wl_callback* callback = nullptr; |
89 struct wl_display* display = nullptr; | 173 struct wl_display* display = nullptr; |
90 }; | 174 }; |
91 | 175 |
92 static void sync_handle_done (void* data, struct wl_callback* callback, uint32_t other_data); | 176 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 = { | 177 static const struct wl_callback_listener sync_callback_listener = { |
94 .done = sync_handle_done, | 178 .done = sync_handle_done, |
95 }; | 179 }; |
96 | 180 |
97 static void sync_handle_done (void* data, struct wl_callback* callback, uint32_t other_data) { | 181 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); | 182 struct sync_data* sync = reinterpret_cast<struct sync_data*>(data); |
99 | 183 |
100 wl_callback_destroy(callback); | 184 wl_callback_destroy(callback); |
101 sync->callback = nullptr; | 185 sync->callback = nullptr; |
102 | 186 |
103 if (sync->sync == 0) { | 187 if (sync->sync == 0) { |
104 if (!sync->global.ext_toplevel_list) { | 188 if (!sync->global.ext_toplevel_list || !sync->global.zwlr_toplevel_mgr) { |
105 std::cerr << "animia/wayland: Wayland server doesn't support ext-foreign-toplevel-list-v1!" << std::endl; | 189 std::cerr << "animia/wayland: Wayland server doesn't support ext-foreign-toplevel-list-v1 nor " |
190 "wlr-foreign-toplevel-management-unstable-v1!" | |
191 << std::endl; | |
106 sync->loop = false; | 192 sync->loop = false; |
107 return; | 193 return; |
108 } | 194 } |
109 | 195 |
110 sync->sync++; | 196 sync->sync++; |
113 | 199 |
114 /* we may need another sync here if there are protocol extensions for | 200 /* we may need another sync here if there are protocol extensions for |
115 * ext_foreign_toplevel_list. | 201 * ext_foreign_toplevel_list. |
116 * | 202 * |
117 * more info: https://git.sr.ht/~leon_plickat/lswt/tree/toplevel-info/item/lswt.c | 203 * more info: https://git.sr.ht/~leon_plickat/lswt/tree/toplevel-info/item/lswt.c |
118 */ | 204 */ |
119 } else { | 205 } else { |
120 /* we've received everything we need! */ | 206 /* we've received everything we need! */ |
121 sync->loop = false; | 207 sync->loop = false; |
122 } | 208 } |
123 } | 209 } |
124 | 210 |
125 /* here comes the actual function we can use */ | 211 /* here comes the actual function we can use */ |
126 bool EnumerateWindows(window_proc_t window_proc) { | 212 bool EnumerateWindows(window_proc_t window_proc) { |
127 struct sync_data sync = { | 213 struct sync_data sync = {.display = wl_display_connect(NULL)}; |
128 .display = wl_display_connect(NULL) | |
129 }; | |
130 | 214 |
131 if (!sync.display) { | 215 if (!sync.display) { |
132 std::cerr << "animia/wayland: Can't connect to display" << std::endl; | 216 std::cerr << "animia/wayland: Can't connect to display" << std::endl; |
133 return false; | 217 return false; |
134 } | 218 } |
150 wl_display_disconnect(sync.display); | 234 wl_display_disconnect(sync.display); |
151 | 235 |
152 return true; | 236 return true; |
153 } | 237 } |
154 | 238 |
155 } | 239 } // namespace animia::internal::wayland |