我必须编写几个函数来对用户屏幕执行一些操作,例如获取屏幕分辨率、显示器数量等。我有适用于 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, ®istry_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
或我可以使用哪个函数的信息,但我没有找到任何有用的信息。
我自己最近也遇到了同样的问题,我设法使用在 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 年了,但我想我仍然应该发布这个答案,以防将来有人遇到这个问题。