在GTK / Linux中,获得DPI比例因子的正确方法是什么?

时间:2014-07-27 02:36:59

标签: linux user-interface ubuntu gtk

上下文:编写一个应该是跨平台的绘图程序。所以我有多个前端负责提供对Cairo上下文的后端类访问,基本事件处理和窗口小部件大小信息。我最近决定将当前的UI比例(用于高DPI显示)添加到最后一位,主要是因为我想将图形切换为渲染到图块缓存,所以我需要知道显示器可以支持的最高级别的细节

在我的小型跨平台世界中,我希望后端类I的前端适配器能够正确地将Cairo上下文配置为在虚拟像素中工作,然后再将其交给我。我只需要比例来限制我在瓷砖上使用的缩放比例。

在AppKit上这很简单:让NSView将1个虚拟像素的NSSize缩放到"支持商店坐标",并将其交给后端类。 Apple也非常聪明,可以提供预先扩展的CoreGraphics上下文,所以我所要做的就是请求翻转坐标并将CGContext推送到Cairo。

在GTK上,我有点困惑。似乎有太多方法可以做到这一点。 GtkWidget有一个" get scale factor" call,gint gtk_widget_get_scale_factor (GtkWidget *widget)返回一个整数值。这似乎有点过于严格,因为您无法处理这种情况之间的屏幕。即28" 3840x2160显示器我一直在关注应该是1.5倍显示器,但在GTK下,一切都会太小或太大。

Ubuntu也投入了自己的扳手,因为它拥有自己的DPI比例因子,似乎与其他一切不同。只有少数应用程序似乎真正支持它。我把它调到了1.5; Firefox和Brackets没有扩展,Nautilus和终端确实扩展,Empathy做了这个奇怪的事情,除了会话文本之外的所有内容。所以它显然不是全系统的,甚至没有内置到GTK ...... blarrgh。

此外,X11拥有自己的获取DPI信息的方式,我听说这是非常不准确的,无论如何都不值得考虑,因为Mir和Wayland无论如何都要替换它。

我无法找到有关这个超级特殊的Unity API的任何信息,以获取用户指定的UI比例。所以我现在要抓住GTK自己的整数尺度,我认为这是不够的。我真的很想知道如何获取Unity规模参数,或任何其他桌面环境自己的专有UI规模参数,但我有一种感觉,我可能还需要提供自定义首选项来配置UI缩放手动为这个特定的前端。

(对于那些好奇的人:我的代码可用here - 我正在讨论的后端类是在src / canvasview.cpp中以及前端"视图适配器的示例"分别位于前端/ gtk / src / CanvasWidget.cpp和frontends / appkit / src / ICAKCanvasView.m。请记住,当我忙于调试基于图块的渲染时,代码当前处于损坏状态。)

2 个答案:

答案 0 :(得分:3)

我还没有在GTK中看到dpi getter,但是有一些代码来自开源和一些更改,我通常会问X-server使用这个代码片段来获取x和y方向的dpi值。对于displayname,您可以通过argv []传递所需的值。

如果您将其命名为“getdpi.c”,则使用

进行编译
gcc -Wall -std=c99  -o getdpi getdpi.c -lX11

如果对您有所帮助,我们将表示赞赏。 : - )

#include <X11/Xlib.h>

#include <stdio.h>
#include <stdlib.h>

const static unsigned int FALSE = 0;
const static unsigned int TRUE = 1;
typedef unsigned int bool;

int getDpi(Display *dpy, int scr, bool xRes)
{
    /*
     * an inch is 25.4 millimeters.
     * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
     *     = N pixels / (M inch / 25.4)
     *     = N * 25.4 pixels / M inch
     */

    double res = xRes ? ((((double) DisplayWidth(dpy,scr)) * 25.4) / ((double) DisplayWidthMM(dpy,scr)))
        : ((((double) DisplayHeight(dpy,scr)) * 25.4) / ((double) DisplayHeightMM(dpy,scr)));

    return (int) (res + 0.5);
} // print_Screen_info

int main(int argc, char *argv[])
{
    Display *dpy;           /* X connection */
    char *displayname = NULL;       /* set to what you want or need */
    dpy = XOpenDisplay (displayname);
    if (!dpy) 
    {
    fprintf (stderr, "xdpi:  unable to open display \"%s\".\n",
         XDisplayName (displayname));
    exit (1);
    }

    for (int i = 0; i < ScreenCount(dpy); ++i)
        printf ("Xdpi: %d, Ydpi %d\n", 
                getDpi(dpy, i, TRUE),
                getDpi(dpy, i, FALSE));
} // main

答案 1 :(得分:0)

export GDK_DPI_SCALE=1.5; run_your_application_to_be_scaled

更重要的是,您可以仅为特定应用程序创建专用启动器,设置自己的比例因子:-)