如何在 Wayland 中创建 EGL 窗口并设置其在屏幕上的位置?

问题描述 投票:0回答:1

我有一个可以在 Wayland 中创建 EGL 窗口的工作程序。我可以控制窗口大小,但不能控制它在屏幕上的位置。现在,如果我将尺寸设置为与屏幕尺寸相匹配,它将全屏运行,但如果我设置的尺寸小于该尺寸,它每次都会出现在不同的随机位置。

我读到顶面无法移动,如果我想控制表面的位置,我必须使用次表面。但是,我找不到任何有用的例子。特别是,我找不到 EGL 的任何示例,它有一些空洞。

无论如何,这是我的程序中的重要部分:

static struct waylandContext {
    struct wl_display* display;
    struct wl_registry* registry;
    struct wl_compositor* compositor;
    struct wl_shell* shell;
    struct wl_surface* surface;
    struct wl_shell_surface* shell_surface;
    struct wl_egl_window* egl_window;
} wlContext;

static void registry_add_object(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
{
    if (!strcmp(interface, "wl_compositor")) {
        wlContext.compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
    } else if (!strcmp(interface, "wl_shell")) {
        wlContext.shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
    }
}

static void registry_remove_object(void* data, struct wl_registry* registry, uint32_t name)
{
}

static struct wl_registry_listener registry_listener = {
    &registry_add_object,
    &registry_remove_object
};

static void shell_surface_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
{
    wl_shell_surface_pong(shell_surface, serial);
}

static void shell_surface_configure(void* data, struct wl_shell_surface* shell_surface, uint32_t edges, int32_t width, int32_t height)
{
    struct window* window = data;
    wl_egl_window_resize(wlContext.egl_window, width, height, 0, 0);
}

static void shell_surface_popup_done(void* data, struct wl_shell_surface* shell_surface)
{
}

static struct wl_shell_surface_listener shell_surface_listener = {
    &shell_surface_ping,
    &shell_surface_configure,
    &shell_surface_popup_done
};

static bool initWayland(int width, int height)
{
    wlContext.display = wl_display_connect(NULL);
    if (!wlContext.display) {
        fprintf(stderr, "failed to connect to display\n");
        return false;
    }

    wlContext.registry = wl_display_get_registry(wlContext.display);
    wl_registry_add_listener(wlContext.registry, &registry_listener, NULL);
    wl_display_dispatch(wlContext.display);
    wl_display_roundtrip(wlContext.display);

    wlContext.surface = wl_compositor_create_surface(wlContext.compositor);
    wlContext.shell_surface = wl_shell_get_shell_surface(wlContext.shell, wlContext.surface);
    wl_shell_surface_add_listener(wlContext.shell_surface, &shell_surface_listener, NULL);
    wl_shell_surface_set_toplevel(wlContext.shell_surface);
    wlContext.egl_window = wl_egl_window_create(wlContext.surface, width, height);

    return true;
}

我尝试将代码更改为:

static struct waylandContext {
    struct wl_display* display;
    struct wl_registry* registry;
    struct wl_compositor* compositor;
    struct wl_subcompositor* subcompositor;
    struct wl_shell* shell;
    struct wl_surface* parent_surface;
    struct wl_surface* child_surface;
    struct wl_subsurface* subsurface;
    struct wl_shell_surface* shell_surface;
    struct wl_egl_window* egl_window;
    struct wl_egl_window* egl_window2;
} wlContext;

static void registry_add_object(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
{
    if (!strcmp(interface, "wl_compositor")) {
        wlContext.compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
    } else if (!strcmp(interface, "wl_subcompositor")) {
        wlContext.subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
    } else if (!strcmp(interface, "wl_shell")) {
        wlContext.shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
    }
}

static void registry_remove_object(void* data, struct wl_registry* registry, uint32_t name)
{
}

static struct wl_registry_listener registry_listener = {
    &registry_add_object,
    &registry_remove_object
};

static void shell_surface_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
{
    wl_shell_surface_pong(shell_surface, serial);
}

static void shell_surface_configure(void* data, struct wl_shell_surface* shell_surface, uint32_t edges, int32_t width, int32_t height)
{
    struct window* window = data;
    wl_egl_window_resize(wlContext.egl_window, width, height, 0, 0);
}

static void shell_surface_popup_done(void* data, struct wl_shell_surface* shell_surface)
{
}

static struct wl_shell_surface_listener shell_surface_listener = {
    &shell_surface_ping,
    &shell_surface_configure,
    &shell_surface_popup_done
};

static bool initWayland(int width, int height)
{
    wlContext.display = wl_display_connect(NULL);
    if (!wlContext.display) {
        fprintf(stderr, "failed to connect to display\n");
        return false;
    }

    wlContext.registry = wl_display_get_registry(wlContext.display);
    wl_registry_add_listener(wlContext.registry, &registry_listener, NULL);
    wl_display_dispatch(wlContext.display);
    wl_display_roundtrip(wlContext.display);

    wlContext.parent_surface = wl_compositor_create_surface(wlContext.compositor);
    wlContext.shell_surface = wl_shell_get_shell_surface(wlContext.shell, wlContext.parent_surface);
    wl_shell_surface_add_listener(wlContext.shell_surface, &shell_surface_listener, NULL);
    wl_shell_surface_set_toplevel(wlContext.shell_surface);

    wlContext.child_surface = wl_compositor_create_surface(wlContext.compositor);
    wlContext.subsurface = wl_subcompositor_get_subsurface(wlContext.subcompositor, wlContext.child_surface, wlContext.parent_surface);

    wlContext.egl_window = wl_egl_window_create(wlContext.child_surface, width, height);

    return true;
}

在我获取子合成器的地方,创建一个子表面并从该子表面创建 EGL 窗口。然而,这不起作用,我不知道为什么。

也许我应该补充一下,我如何使用 EGL,但这只是标准的东西。创建 EGL 窗口后,我会执行常规调用序列,如

eglInitialize
eglCreateContext
等。然后我创建一个 OpenGL 上下文,绘制一些内容并调用
eglSwapBuffers
。当我在地下执行此操作时,
eglSwapBuffers
运行一次但没有任何显示,然后当我第二次调用
eglSwapBuffers
时,它永远冻结。

c window egl wayland
1个回答
0
投票

不是自我推销,但你应该看看我的存储库,unstatistical/engine。当我开始这个项目时,我对 Wayland 和 EGL 开发相当陌生,但我相信某些代码可能仍然相关。 Wayland 代码可以在 src/wayland 中找到。

我相信控制窗口位置的最佳方法是使用

wl_region
对象。您可以使用此功能创建一个区域:

wlContext.region = wl_compositor_create_region(wlContext.compositor);

然后,您可以像这样设置窗口的位置:

wl_region_add(wlContext.region, x, y, w, h);

祝您的项目好运。

© www.soinside.com 2019 - 2024. All rights reserved.