Mercurial > minori
changeset 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 | 031a257ee019 |
children | 47ddd6b638e3 |
files | dep/animia/.clang-format dep/animia/CMakeLists.txt dep/animia/README.md dep/animia/src/win/wayland.cc |
diffstat | 4 files changed, 129 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/dep/animia/.clang-format Sun Jan 07 11:44:40 2024 -0500 +++ b/dep/animia/.clang-format Sun Jan 07 12:42:10 2024 -0500 @@ -5,10 +5,8 @@ ColumnLimit: 120 IndentWidth: 4 TabWidth: 4 -AccessModifierOffset: 4 IndentCaseLabels: true -IndentAccessModifiers: true IndentPPDirectives: AfterHash BreakBeforeBraces: Attach
--- a/dep/animia/CMakeLists.txt Sun Jan 07 11:44:40 2024 -0500 +++ b/dep/animia/CMakeLists.txt Sun Jan 07 12:42:10 2024 -0500 @@ -138,6 +138,7 @@ list(APPEND SRC_FILES src/win/wayland.cc src/win/wayland/ext-foreign-toplevel-list-v1.c + src/win/wayland/wlr-foreign-toplevel-management-unstable-v1.c ) list(APPEND INCLUDE_DIRS ${WAYLAND_INCLUDE_DIRS}) list(APPEND LIBRARIES ${WAYLAND_LINK_LIBRARIES})
--- a/dep/animia/README.md Sun Jan 07 11:44:40 2024 -0500 +++ b/dep/animia/README.md Sun Jan 07 12:42:10 2024 -0500 @@ -8,7 +8,8 @@ ## Support Animia supports Windows, macOS, and Linux when dealing with file descriptors. When enumerating windows, it supports Windows, macOS (Quartz), X11, and -Wayland (only via the `ext_foreign_toplevel_handle_v1` interface). +Wayland (only via the `ext_foreign_toplevel_handle_v1` and +`wlr_foreign_toplevel_management_unstable_v1` interfaces). Unlike Anisthesia, Animia currently does not support UI automation, i.e., most web browsers will not work properly, if at all. @@ -36,8 +37,7 @@ [unreliable](https://stackoverflow.com/a/49970271). ### Wayland -Only Wayland servers that implement the `ext_foreign_toplevel_handle_v1` -interface will work with Animia. As of 2 January 2024, this means there are no -server implementations that will work. **However**, it is possible to implement -support for the wlroots-specific `wlr_foreign_toplevel_management_unstable_v1` -protocol, which will at least give support to window managers based off of it. +Only Wayland servers that implement the `ext_foreign_toplevel_handle_v1` or +`wlr_foreign_toplevel_management_unstable_v1` interfaces will work with Animia. +Currently, both Sway and Mir support the latter. Maybe some day we'll have +major compositor support for `ext_foreign_toplevel_handle_v1`.
--- a/dep/animia/src/win/wayland.cc Sun Jan 07 11:44:40 2024 -0500 +++ b/dep/animia/src/win/wayland.cc Sun Jan 07 12:42:10 2024 -0500 @@ -1,24 +1,90 @@ #include "animia/win/wayland.h" -#include "animia/win.h" #include "animia.h" +#include "animia/win.h" +#include <cstring> #include <iostream> -#include <cstring> #include "animia/win/wayland/ext-foreign-toplevel-list-v1.h" +#include "animia/win/wayland/wlr-foreign-toplevel-management-unstable-v1.h" #include <wayland-client.h> namespace animia::internal::wayland { -static void noop() {} +/* zwlr-foreign-toplevel-management-v1 implementation */ +static void zwlr_foreign_handle_handle_title(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, + const char* title) { + if (title) + reinterpret_cast<Window*>(data)->text = title; +} -/* ext_foreign_handle stuff */ -static void ext_foreign_handle_handle_app_id(void* data, struct ext_foreign_toplevel_handle_v1* handle, const char* app_id) { +static void zwlr_foreign_handle_handle_app_id(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, + const char* app_id) { if (app_id) reinterpret_cast<Window*>(data)->class_name = app_id; } -static void ext_foreign_handle_handle_title(void* data, struct ext_foreign_toplevel_handle_v1* handle, const char* title) { +static void zwlr_foreign_handle_handle_done(void* data, struct zwlr_foreign_toplevel_handle_v1* handle) { + if (handle) + zwlr_foreign_toplevel_handle_v1_destroy(handle); +} + +static void zwlr_foreign_handle_handle_state(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, + struct wl_array*) { +} + +static void zwlr_foreign_handle_handle_parent(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, + struct zwlr_foreign_toplevel_handle_v1*) { +} + +static void zwlr_foreign_handle_handle_output_enter(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, + struct wl_output*) { +} + +static void zwlr_foreign_handle_handle_output_leave(void* data, struct zwlr_foreign_toplevel_handle_v1* handle, + struct wl_output*) { +} + +static void zwlr_foreign_handle_handle_closed(void* data, struct zwlr_foreign_toplevel_handle_v1* handle) { +} + +static const struct zwlr_foreign_toplevel_handle_v1_listener zwlr_handle_listener = { + .title = zwlr_foreign_handle_handle_title, + .app_id = zwlr_foreign_handle_handle_app_id, + .output_enter = zwlr_foreign_handle_handle_output_enter, + .output_leave = zwlr_foreign_handle_handle_output_leave, + .state = zwlr_foreign_handle_handle_state, + .done = zwlr_foreign_handle_handle_done, + .closed = zwlr_foreign_handle_handle_closed, + .parent = zwlr_foreign_handle_handle_parent}; + +static void zwlr_toplevel_manager_handle_toplevel(void* data, struct zwlr_foreign_toplevel_manager_v1* manager, + struct zwlr_foreign_toplevel_handle_v1* handle) { + std::vector<Window>* windows = reinterpret_cast<std::vector<Window>*>(data); + if (!windows) + return; + + windows->push_back({0}); + zwlr_foreign_toplevel_handle_v1_add_listener(handle, &zwlr_handle_listener, &*windows->end()); +} + +static void zwlr_toplevel_manager_handle_finished(void*, struct zwlr_foreign_toplevel_manager_v1*) { +} + +static const struct zwlr_foreign_toplevel_manager_v1_listener zwlr_toplevel_manager_listener = { + .toplevel = zwlr_toplevel_manager_handle_toplevel, + .finished = zwlr_toplevel_manager_handle_finished, +}; + +/* ext_foreign_handle stuff */ +static void ext_foreign_handle_handle_app_id(void* data, struct ext_foreign_toplevel_handle_v1* handle, + const char* app_id) { + if (app_id) + reinterpret_cast<Window*>(data)->class_name = app_id; +} + +static void ext_foreign_handle_handle_title(void* data, struct ext_foreign_toplevel_handle_v1* handle, + const char* title) { if (title) reinterpret_cast<Window*>(data)->text = title; } @@ -28,18 +94,22 @@ ext_foreign_toplevel_handle_v1_destroy(handle); } -static void ext_foreign_handle_handle_closed(void*, struct ext_foreign_toplevel_handle_v1*) {} -static void ext_foreign_handle_handle_identifier(void*, ext_foreign_toplevel_handle_v1*, const char*) {} +static void ext_foreign_handle_handle_closed(void*, struct ext_foreign_toplevel_handle_v1*) { +} + +static void ext_foreign_handle_handle_identifier(void*, ext_foreign_toplevel_handle_v1*, const char*) { +} static const struct ext_foreign_toplevel_handle_v1_listener ext_handle_listener = { - .closed = ext_foreign_handle_handle_closed, - .done = ext_foreign_handle_handle_done, - .title = ext_foreign_handle_handle_title, - .app_id = ext_foreign_handle_handle_app_id, - .identifier = ext_foreign_handle_handle_identifier // for now + .closed = ext_foreign_handle_handle_closed, + .done = ext_foreign_handle_handle_done, + .title = ext_foreign_handle_handle_title, + .app_id = ext_foreign_handle_handle_app_id, + .identifier = ext_foreign_handle_handle_identifier // for now }; -static void ext_toplevel_list_handle_toplevel(void* data, struct ext_foreign_toplevel_list_v1* list, struct ext_foreign_toplevel_handle_v1* handle) { +static void ext_toplevel_list_handle_toplevel(void* data, struct ext_foreign_toplevel_list_v1* list, + struct ext_foreign_toplevel_handle_v1* handle) { std::vector<Window>* windows = reinterpret_cast<std::vector<Window>*>(data); if (!windows) return; @@ -48,35 +118,49 @@ ext_foreign_toplevel_handle_v1_add_listener(handle, &ext_handle_listener, &*windows->end()); } -static void ext_toplevel_list_handle_finished(void*, ext_foreign_toplevel_list_v1*) {} +static void ext_toplevel_list_handle_finished(void*, ext_foreign_toplevel_list_v1*) { +} static const struct ext_foreign_toplevel_list_v1_listener ext_toplevel_list_listener = { - .toplevel = ext_toplevel_list_handle_toplevel, - .finished = ext_toplevel_list_handle_finished -}; + .toplevel = ext_toplevel_list_handle_toplevel, .finished = ext_toplevel_list_handle_finished}; /* -- Global data -- */ struct global_data { - struct ext_foreign_toplevel_list_v1* ext_toplevel_list; + struct ext_foreign_toplevel_list_v1* ext_toplevel_list = nullptr; + struct zwlr_foreign_toplevel_manager_v1* zwlr_toplevel_mgr = nullptr; std::vector<Window> windows; }; -static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { +static void registry_handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, + uint32_t version) { struct global_data* global = reinterpret_cast<struct global_data*>(data); if (!std::strcmp(interface, ext_foreign_toplevel_list_v1_interface.name)) { - // bind to ext-foreign-toplevel-list-v1 - global->ext_toplevel_list = reinterpret_cast<struct ext_foreign_toplevel_list_v1*>(wl_registry_bind(registry, name, &ext_foreign_toplevel_list_v1_interface, 1)); - ext_foreign_toplevel_list_v1_add_listener(global->ext_toplevel_list, &ext_toplevel_list_listener, &global->windows); + if (!global->zwlr_toplevel_mgr || version < 3) + return; // we don't need this then + + global->ext_toplevel_list = reinterpret_cast<struct ext_foreign_toplevel_list_v1*>( + wl_registry_bind(registry, name, &ext_foreign_toplevel_list_v1_interface, 1)); + + ext_foreign_toplevel_list_v1_add_listener(global->ext_toplevel_list, &ext_toplevel_list_listener, + &global->windows); + } else if (!std::strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name)) { + if (!global->ext_toplevel_list) + return; // we don't need this then + + global->zwlr_toplevel_mgr = reinterpret_cast<struct zwlr_foreign_toplevel_manager_v1*>( + wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, 1)); + + zwlr_foreign_toplevel_manager_v1_add_listener(global->zwlr_toplevel_mgr, &zwlr_toplevel_manager_listener, + &global->windows); } } -static void registry_handle_global_remove(void*, wl_registry*, uint32_t) {} +static void registry_handle_global_remove(void*, wl_registry*, uint32_t) { +} -static const struct wl_registry_listener registry_listener = { - .global = registry_handle_global, - .global_remove = registry_handle_global_remove -}; +static const struct wl_registry_listener registry_listener = {.global = registry_handle_global, + .global_remove = registry_handle_global_remove}; /* BAH! humbug... */ struct sync_data { @@ -89,20 +173,22 @@ struct wl_display* display = nullptr; }; -static void sync_handle_done (void* data, struct wl_callback* callback, uint32_t other_data); +static void sync_handle_done(void* data, struct wl_callback* callback, uint32_t other_data); static const struct wl_callback_listener sync_callback_listener = { - .done = sync_handle_done, + .done = sync_handle_done, }; -static void sync_handle_done (void* data, struct wl_callback* callback, uint32_t other_data) { +static void sync_handle_done(void* data, struct wl_callback* callback, uint32_t other_data) { struct sync_data* sync = reinterpret_cast<struct sync_data*>(data); wl_callback_destroy(callback); sync->callback = nullptr; if (sync->sync == 0) { - if (!sync->global.ext_toplevel_list) { - std::cerr << "animia/wayland: Wayland server doesn't support ext-foreign-toplevel-list-v1!" << std::endl; + if (!sync->global.ext_toplevel_list || !sync->global.zwlr_toplevel_mgr) { + std::cerr << "animia/wayland: Wayland server doesn't support ext-foreign-toplevel-list-v1 nor " + "wlr-foreign-toplevel-management-unstable-v1!" + << std::endl; sync->loop = false; return; } @@ -115,7 +201,7 @@ * ext_foreign_toplevel_list. * * more info: https://git.sr.ht/~leon_plickat/lswt/tree/toplevel-info/item/lswt.c - */ + */ } else { /* we've received everything we need! */ sync->loop = false; @@ -124,9 +210,7 @@ /* here comes the actual function we can use */ bool EnumerateWindows(window_proc_t window_proc) { - struct sync_data sync = { - .display = wl_display_connect(NULL) - }; + struct sync_data sync = {.display = wl_display_connect(NULL)}; if (!sync.display) { std::cerr << "animia/wayland: Can't connect to display" << std::endl; @@ -152,4 +236,4 @@ return true; } -} +} // namespace animia::internal::wayland