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 |
