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