在 Wayland C++ 中确定屏幕大小

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

我必须编写几个函数来对用户屏幕执行一些操作,例如获取屏幕分辨率、显示器数量等。我有适用于 Windows 和 Linux 的工作解决方案,但在 Linux 上我只能使用 Wayland。在 X11 上可以轻松确定屏幕尺寸,但 Wayland 相对较新,并且没有像 X11 那样有如此详细的记录。

我尝试过以下代码:

static void global_handler(void* data, wl_registry* registry, uint32_t name,
                           const char* interface, uint32_t version) {
    wl_output* output = static_cast<wl_output*>(
        wl_registry_bind(registry, name, &wl_output_interface, 1));
    if (!output) {
        // Handle error
    }
}

    std::string GetDisplaySize(std::string args) {

        if (getenv("WAYLAND_DISPLAY") != nullptr) {

            static std::uint16_t width, height;

            wl_display* display = wl_display_connect(nullptr);
            if (!display) { return "0"; }

            wl_registry* registry = wl_display_get_registry(display);

            static const wl_registry_listener registry_listener = {
                .global = +[](void* data, wl_registry* registry, uint32_t name,
                              const char* interface, uint32_t version) -> void {
                    wl_output* output = static_cast<wl_output*>(
                        wl_registry_bind(registry, name, &wl_output_interface,
                                         1));
                    if (!output) { return; }

                    wl_output_get_geometry(output, nullptr, nullptr, &width,
                                           &height);

                    wl_output_destroy(output);
                },
                .global_remove =
                    [](void* data, wl_registry* registry, uint32_t name) {
                    },
            };
            wl_registry_add_listener(registry, &registry_listener, nullptr);

            wl_display_roundtrip(display);

            wl_display_disconnect(display);

            return "{\"width\":" + std::to_string(width) +
                   ",\"height\":" + std::to_string(height) + "}";
        } // namespace api
        else {
            GdkRectangle workarea = {0};
            gdk_monitor_get_workarea(
                gdk_display_get_primary_monitor(gdk_display_get_default()),
                &workarea);

            return "{\"width\":" + std::to_string(workarea.width) +
                   ",\"height\":" + std::to_string(workarea.height) + "}";
        }
    }

这适用于 X11,但在 Wayland 上我遇到编译器错误

error: ‘wl_output_get_geometry’ was not declared in this scope

我正在使用 GCC C++ 编译器。我试图找到一些有关

wl_output_get_geometry
或我可以使用哪个函数的信息,但我没有找到任何有用的信息。

c++ linux wayland
1个回答
0
投票

我自己最近也遇到了同样的问题,我设法使用在 GLFW 库中找到的一些代码找到了解决方案,显然适合我的目的。它是用 C 编写的,但也应该适用于 C++。

// Monitor.h

typedef struct wl_output monitor_information_t;
typedef struct wl_output_listener monitor_information_monitor_t;

typedef struct
{
    int32_t physical_width, physical_height;
    int32_t x, y;
    int32_t width, height;
    int16_t refresh_rate, scale;
} monitor_t;

extern monitor_t monitor_rendered_to;
extern monitor_information_t* monitor_information;
extern const monitor_information_monitor_t monitor_listener;
// Monitor.c

#include "Monitor.h"
#include <math.h>
#include <wayland-client-protocol.h>

monitor_t monitor_rendered_to;
monitor_information_t* monitor_information;

static void HandleMonitorGeometry(
    void* data, monitor_information_t* wl_output, int32_t x, int32_t y,
    int32_t physical_width, int32_t physical_height, int32_t subpixel,
    const char* make, const char* model, int32_t transform)
{
    monitor_rendered_to.x = x;
    monitor_rendered_to.y = y;
    monitor_rendered_to.physical_width = physical_width;
    monitor_rendered_to.physical_height = physical_height;
}

static void HandleMonitorPixelContents(void* data,
                                       monitor_information_t* wl_output,
                                       uint32_t flags, int32_t width,
                                       int32_t height, int32_t refresh)
{
    monitor_rendered_to.width = width;
    monitor_rendered_to.height = height;
    monitor_rendered_to.refresh_rate = (int16_t)round(refresh / 1000.0);
}

static void HandleMonitorInformationSent(void* data,
                                         monitor_information_t* wl_output)
{
    // No operation.
}

static void HandleMonitorScale(void* data,
                               monitor_information_t* wl_output,
                               int32_t factor)
{
    monitor_rendered_to.scale = factor;
}

static void HandleMonitorName(void* data, struct wl_output* wl_output,
                              const char* name)
{
    // No operation.
}

static void HandleMonitorDescription(void* data,
                                     struct wl_output* wl_output,
                                     const char* description)
{
    // No operation.
}

const monitor_information_monitor_t monitor_listener = {
    HandleMonitorGeometry,
    HandleMonitorPixelContents,
    HandleMonitorInformationSent,
    HandleMonitorScale,
    HandleMonitorName,
    HandleMonitorDescription};

然后在您绑定注册表对象的任何地方;

static void HandleInterfaceAddition(void* data,
                                    struct wl_registry* registry,
                                    uint32_t name, const char* interface,
                                    uint32_t version)
{
    // [...]
    if (strcmp(interface, wl_output_interface.name) == 0)
    {
        monitor_information = wl_registry_bind(
            registry, name, &wl_output_interface, version);
        wl_output_add_listener(monitor_information, &monitor_listener,
                               NULL);
    }
    // [...]
}

static const interface_monitor_t registry_listener = {
    HandleInterfaceAddition};

我知道这个问题已经有近 2 年了,但我想我仍然应该发布这个答案,以防将来有人遇到这个问题。

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