6

在 Windows 中,winapi 提供了一个报告监视器信息的函数:

DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);

EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);

int FPS = dm.dmDisplayFrequency;

在 Linux 上这相当于什么?Linux 手册页将我引导至 allegro 库函数,但我不仅没有使用 allegro,而且该函数来自所述库的非常过时的版本,据报道仅适用于 Windows。

4

3 回答 3

5

使用 XRandr API(man 3 Xrandr)。请参阅此处的示例:

您还可以查看 xrandr(1) 的代码。


编辑1:为了后代:

示例代码稍作调整,因此更像是一个演示:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>

int main()
{
    int num_sizes;
    Rotation current_rotation;

    Display *dpy = XOpenDisplay(NULL);
    Window root = RootWindow(dpy, 0);
    XRRScreenSize *xrrs = XRRSizes(dpy, 0, &num_sizes);
    //
    //     GET CURRENT RESOLUTION AND FREQUENCY
    //
    XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
    short current_rate = XRRConfigCurrentRate(conf);
    SizeID current_size_id = XRRConfigCurrentConfiguration(conf, &current_rotation);

    int current_width = xrrs[current_size_id].width;
    int current_height = xrrs[current_size_id].height;
    std::cout << "current_rate = " << current_rate << std::endl;
    std::cout << "current_width = " << current_width << std::endl;
    std::cout << "current_height = " << current_height << std::endl;

    XCloseDisplay(dpy);
}

编译:

g++ 17797636.cpp -o 17797636 -lX11 -lXrandr

输出:

$ ./17797636 
current_rate = 50
current_width = 1920
current_height = 1080
于 2013-07-22T22:05:49.523 回答
2

一个简单的例子:

#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>

int main(int argc, char *argv[])
{
  Display *display = XOpenDisplay(NULL);
  Window default_root_window = XDefaultRootWindow(display);

  XRRScreenResources *screen_resources = XRRGetScreenResources(display, default_root_window);

  RRMode active_mode_id = 0;
  for (int i = 0; i < screen_resources->ncrtc; ++i) {
    XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(display, screen_resources, screen_resources->crtcs[i]);
    // If None, then is not displaying the screen contents
    if (crtc_info->mode != None) {
      active_mode_id = crtc_info->mode; 
    }
  }

  double active_rate = 0;
  for (int i = 0; i < screen_resources->nmode; ++i) {
    XRRModeInfo mode_info = screen_resources->modes[i];
    if (mode_info.id == active_mode_id) {
      active_rate = (double)mode_info.dotClock / ((double)mode_info.hTotal * (double)mode_info.vTotal);
    }
  }

  printf("Active rate is: %.1f\n", active_rate);

  return 0;
}
于 2021-03-30T06:11:19.723 回答
1

伊万的回答对我不起作用;我猜 xrandr 自 2013 年以来发生了变化?命令行工具xrandr可以正确读取我的刷新率,但是它的源代码太复杂了,我不愿意复制它这样做的方式。相反,我选择笨拙地将工作委派给整个xrandr程序。我的糟糕解决方案粘贴在下面。

请注意,当连接多个显示设备时,此解决方案可能不可靠,并且可能有一天xrandr再次更改时会中断。

(pstream.h 由 Jonathan Wakely 的 PStreams 库提供,此处引用: https ://stackoverflow.com/a/10702464/1364776

我只是用它把命令的输出变成std::string; 显然还有其他各种方法可以做到这一点,因此如果您愿意,可以使用其中一种。)

#include <pstream.h>
#include <cctype>
#include <cstdlib>
#include <cmath>

float getRefreshRate()
{
    try
    {
        redi::ipstream queryStream("xrandr");
        std::string chunk;
        while (queryStream >> chunk)
        {
            auto rateEnd = chunk.find("*");
            if (rateEnd != std::string::npos)
            {
                auto rateBeginning = rateEnd;
                while (std::isdigit(chunk[rateBeginning]) || std::ispunct(chunk[rateBeginning]))
                    --rateBeginning;
                ++rateBeginning;

                auto numberString = chunk.substr(rateBeginning, rateEnd - rateBeginning);
                float rate = std::strtof(numberString.data(), nullptr);
                if (rate != 0 && rate != HUGE_VALF)
                    return rate;
            }
        }
    }
    catch (...)
    {
    }

    return 60; // I am not proud of any of this :(
}
于 2019-11-04T10:10:53.230 回答