Anonymous
Уэйленд композитор с использованием wlroots: xdg_surface не карты, и wlr_surface_get_texture () всегда возвращает Null
Сообщение
Anonymous » 19 июл 2025, 22:40
Я пишу пользовательский композитор Wayland в C ++, используя WLROOTS-0.19. Я обрабатываю новое создание wlr_xdg_surface
Код: Выделить всё
void Server::_handle_new_xdg_shell_surface(struct wl_listener * listener, void * data) {
Server * server = wl_container_of(listener, server, _new_xdg_shell_surface_listener);
auto xdg_surface = static_cast(data);
auto output = server->preferred_output();
auto workspace = output->current_workspace();
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL || xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
return;
}
wlr_xdg_surface_ping(xdg_surface);
auto window = new Window(server, workspace, xdg_surface, nullptr, nullptr, nullptr, nullptr);
for (auto & cb : server->_on_new_xdg_shell_surface) {
cb(window, xdg_surface, output);
}
}
Window::Window(Server * server, Workspace * workspace,
struct wlr_xdg_surface * xdg_surface, struct wlr_xwayland_surface * xwayland_surface,
const char * title, const char * app_id, const Handler & callback):
_server(server), _workspace(workspace),
_xdg_surface(xdg_surface), _xwayland_surface(xwayland_surface),
_x(0.0), _y(0.0), _width(1.0), _height(1.0),
_mapped(false), _minimized(false), _maximized(false), _fullscreened(false),
_ready(false), _dirty(false), _resizing(false), _data(nullptr) {
_workspaces_history = new WorkspacesHistory();
if (_xdg_surface) {
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
_title = strdup(title ? title : _xdg_surface->toplevel->title ? _xdg_surface->toplevel->title : "");
_app_id = strdup(app_id ? app_id : _xdg_surface->toplevel->app_id ? _xdg_surface->toplevel->app_id : "");
_setup_xdg();
}
else {
auto * pending = new PendingXDG{
.listener = {},
.window = this,
.title = title,
.app_id = app_id,
};
pending->listener.notify = [](struct wl_listener * listener, void * data) {
struct PendingXDG * pending = wl_container_of(listener, pending, listener);
auto toplevel = static_cast(data);
auto window = pending->window;
wl_list_remove(&pending->listener.link);
window->set_title(pending->title ? pending->title : toplevel->title ? toplevel->title : "");
window->set_app_id(pending->app_id ? pending->app_id : toplevel->app_id ? toplevel->app_id : "");
window->_setup_xdg();
delete pending;
};
wl_signal_add(&_xdg_surface->surface->events.map, &pending->listener);
}
}
else {
_title = strdup(title ? title : "");
_app_id = strdup(app_id ? app_id : "");
_server->add_window(this);
if (_workspace) {
_workspace->add_window(this);
_workspaces_history->shift(_workspace);
}
_ready = true;
}
if (callback) {
_on_create.push_back(std::move(callback));
callback(this);
}
}
void Window::_setup_xdg() {
bool failed = false;
auto scene = Node::alloc_scene_tree(_server->root()->staging(), &failed);
if (!failed) {
wlr_scene_xdg_surface_create(scene, _xdg_surface);
}
// xdg_shell_view->image_capture_tree =
// wlr_scene_xdg_surface_create(&xdg_shell_view->view.image_capture_scene->tree, xdg_toplevel->base);
_server->add_window(this);
if (_workspace) {
_workspace->add_window(this);
_workspaces_history->shift(_workspace);
}
_set_title_listener.notify = _handle_set_title;
wl_signal_add(&_xdg_surface->toplevel->events.set_title, &_set_title_listener);
_map_listener.notify = _handle_map;
wl_signal_add(&_xdg_surface->surface->events.map, &_map_listener);
_unmap_listener.notify = _handle_unmap;
wl_signal_add(&_xdg_surface->surface->events.unmap, &_unmap_listener);
_configure_listener.notify = _handle_configure;
wl_signal_add(&_xdg_surface->events.configure, &_configure_listener);
_commit_listener.notify = _handle_commit;
wl_signal_add(&_xdg_surface->surface->events.commit, &_commit_listener);
_destroy_listener.notify = _handle_destroy;
wl_signal_add(&_xdg_surface->surface->events.destroy, &_destroy_listener);
wl_signal_add(&_xdg_surface->events.destroy, &_destroy_listener);
_configure_xdg();
_ready = true;
}
< /code>
В обработчике коммита я стараюсь получить текстуру такой: < /p>
wlr_texture *texture = wlr_surface_get_texture(xdg_surface->surface);
< /code>
Но текстура всегда нулевая. Тем не менее, я получаю события коммита, но не получаю карту. Клиент (например, котенка или нога) работает, и я вижу его заголовок окна Toplevel и APP_ID. Окно также присутствует в моем списке окон. < /P>
Я попытался добавить это при настройке окна: < /p>
void Window::_configure_xdg() {
wl_array states;
wl_array_init(&states);
if (_maximized) {
wl_array_add(&states, XDG_TOPLEVEL_STATE_MAXIMIZED);
}
if (_fullscreened) {
wl_array_add(&states, XDG_TOPLEVEL_STATE_FULLSCREEN);
}
if (_resizing) {
wl_array_add(&states, XDG_TOPLEVEL_STATE_RESIZING);
}
wl_array_add(&states, XDG_TOPLEVEL_STATE_ACTIVATED);
xdg_toplevel_send_configure(_xdg_surface->toplevel->resource, _width, _height, &states);
}
... но это не помогло.
Подробнее здесь:
https://stackoverflow.com/questions/797 ... urface-get
1752954002
Anonymous
Я пишу пользовательский композитор Wayland в C ++, используя WLROOTS-0.19. Я обрабатываю новое создание wlr_xdg_surface[code]void Server::_handle_new_xdg_shell_surface(struct wl_listener * listener, void * data) { Server * server = wl_container_of(listener, server, _new_xdg_shell_surface_listener); auto xdg_surface = static_cast(data); auto output = server->preferred_output(); auto workspace = output->current_workspace(); if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL || xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { return; } wlr_xdg_surface_ping(xdg_surface); auto window = new Window(server, workspace, xdg_surface, nullptr, nullptr, nullptr, nullptr); for (auto & cb : server->_on_new_xdg_shell_surface) { cb(window, xdg_surface, output); } } Window::Window(Server * server, Workspace * workspace, struct wlr_xdg_surface * xdg_surface, struct wlr_xwayland_surface * xwayland_surface, const char * title, const char * app_id, const Handler & callback): _server(server), _workspace(workspace), _xdg_surface(xdg_surface), _xwayland_surface(xwayland_surface), _x(0.0), _y(0.0), _width(1.0), _height(1.0), _mapped(false), _minimized(false), _maximized(false), _fullscreened(false), _ready(false), _dirty(false), _resizing(false), _data(nullptr) { _workspaces_history = new WorkspacesHistory(); if (_xdg_surface) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { _title = strdup(title ? title : _xdg_surface->toplevel->title ? _xdg_surface->toplevel->title : ""); _app_id = strdup(app_id ? app_id : _xdg_surface->toplevel->app_id ? _xdg_surface->toplevel->app_id : ""); _setup_xdg(); } else { auto * pending = new PendingXDG{ .listener = {}, .window = this, .title = title, .app_id = app_id, }; pending->listener.notify = [](struct wl_listener * listener, void * data) { struct PendingXDG * pending = wl_container_of(listener, pending, listener); auto toplevel = static_cast(data); auto window = pending->window; wl_list_remove(&pending->listener.link); window->set_title(pending->title ? pending->title : toplevel->title ? toplevel->title : ""); window->set_app_id(pending->app_id ? pending->app_id : toplevel->app_id ? toplevel->app_id : ""); window->_setup_xdg(); delete pending; }; wl_signal_add(&_xdg_surface->surface->events.map, &pending->listener); } } else { _title = strdup(title ? title : ""); _app_id = strdup(app_id ? app_id : ""); _server->add_window(this); if (_workspace) { _workspace->add_window(this); _workspaces_history->shift(_workspace); } _ready = true; } if (callback) { _on_create.push_back(std::move(callback)); callback(this); } } void Window::_setup_xdg() { bool failed = false; auto scene = Node::alloc_scene_tree(_server->root()->staging(), &failed); if (!failed) { wlr_scene_xdg_surface_create(scene, _xdg_surface); } // xdg_shell_view->image_capture_tree = // wlr_scene_xdg_surface_create(&xdg_shell_view->view.image_capture_scene->tree, xdg_toplevel->base); _server->add_window(this); if (_workspace) { _workspace->add_window(this); _workspaces_history->shift(_workspace); } _set_title_listener.notify = _handle_set_title; wl_signal_add(&_xdg_surface->toplevel->events.set_title, &_set_title_listener); _map_listener.notify = _handle_map; wl_signal_add(&_xdg_surface->surface->events.map, &_map_listener); _unmap_listener.notify = _handle_unmap; wl_signal_add(&_xdg_surface->surface->events.unmap, &_unmap_listener); _configure_listener.notify = _handle_configure; wl_signal_add(&_xdg_surface->events.configure, &_configure_listener); _commit_listener.notify = _handle_commit; wl_signal_add(&_xdg_surface->surface->events.commit, &_commit_listener); _destroy_listener.notify = _handle_destroy; wl_signal_add(&_xdg_surface->surface->events.destroy, &_destroy_listener); wl_signal_add(&_xdg_surface->events.destroy, &_destroy_listener); _configure_xdg(); _ready = true; } < /code> В обработчике коммита я стараюсь получить текстуру такой: < /p> wlr_texture *texture = wlr_surface_get_texture(xdg_surface->surface); < /code> Но текстура всегда нулевая. Тем не менее, я получаю события коммита, но не получаю карту. Клиент (например, котенка или нога) работает, и я вижу его заголовок окна Toplevel и APP_ID. Окно также присутствует в моем списке окон. < /P> Я попытался добавить это при настройке окна: < /p> void Window::_configure_xdg() { wl_array states; wl_array_init(&states); if (_maximized) { wl_array_add(&states, XDG_TOPLEVEL_STATE_MAXIMIZED); } if (_fullscreened) { wl_array_add(&states, XDG_TOPLEVEL_STATE_FULLSCREEN); } if (_resizing) { wl_array_add(&states, XDG_TOPLEVEL_STATE_RESIZING); } wl_array_add(&states, XDG_TOPLEVEL_STATE_ACTIVATED); xdg_toplevel_send_configure(_xdg_surface->toplevel->resource, _width, _height, &states); } [/code] ... но это не помогло. Подробнее здесь: [url]https://stackoverflow.com/questions/79707533/wayland-compositor-using-wlroots-xdg-surface-doesnt-maps-and-wlr-surface-get[/url]