Программное определение отдельных значений ширины / высоты экрана в Linux (с Xinerama, TwinView и / или BigDesktop) - PullRequest
4 голосов
/ 07 мая 2009

Я разрабатываю небольшой побочный проект для отображения нескольких обоев на нескольких экранах в GNOME (что, очевидно, не может быть сделано самим GNOME или чем-либо еще). Я понял, как сделать основную часть этого (используя компоненты ImageMagick, для любопытных); Я пытаюсь автоматизировать конфигурацию системы.

Для этого мне нужен способ определения размеров отдельных экранов. Кто-нибудь может дать мне подсказку, где это искать? Я полагаю, что сам X-сервер обладает информацией, но я не уверен, как моя программа может запросить ее.

Ответы [ 4 ]

6 голосов
/ 07 мая 2009

Похоже, есть libXinerama API, который может получить эту информацию. Пока я не нашел никакой подробной информации.

Общая информация о программировании на X.org здесь (файл PDF). Информацию о функциях, предоставляемых libXinerama, можно найти здесь (онлайн-копия руководства, не так много информации).

Вот небольшая программа на C ++, которую я вытащил из этих ссылок, чтобы получить размеры и смещения каждого монитора, подключенного к Xinerama. Это также работает для nVidia TwinView; В настоящее время у меня нет карты ATI для тестирования в их системе BigDesktop, но я подозреваю, что она будет работать и на ней.

#include <cstdlib>
#include <iostream>

#include <X11/extensions/Xinerama.h>

using std::cout;
using std::endl;

int main(int argc, char *argv[]) {
    bool success=false;
    Display *d=XOpenDisplay(NULL);
    if (d) {
        int dummy1, dummy2;
        if (XineramaQueryExtension(d, &dummy1, &dummy2)) {
            if (XineramaIsActive(d)) {
                int heads=0;
                XineramaScreenInfo *p=XineramaQueryScreens(d, &heads);
                if (heads>0) {
                    for (int x=0; x<heads; ++x)
                        cout << "Head " << x+1 << " of " << heads << ": " <<
                            p[x].width << "x" << p[x].height << " at " <<
                            p[x].x_org << "," << p[x].y_org << endl;
                    success=true;
                } else cout << "XineramaQueryScreens says there aren't any" << endl;
                XFree(p);
            } else cout << "Xinerama not active" << endl;
        } else cout << "No Xinerama extension" << endl;
        XCloseDisplay(d);
    } else cout << "Can't open display" << endl;

    return (success ? EXIT_SUCCESS : EXIT_FAILURE);
}
5 голосов
/ 16 июля 2009

Попробуйте что-то вроде

GdkScreen *screen;
int num_monitors;
int i;

screen = gdk_screen_get_default ();
num_monitors = gdk_screen_get_n_monitors ();

for (i = 0; i < num_monitors; i++) {
    GdkRectangle rect;

    gdk_screen_get_monitor_geometry (screen, i, &rect);
    printf ("monitor %d: offsets (%d, %d), size (%d, %d)\n",
        i,
        rect.x, rect.y,
        rect.width, rect.height);
}

Внутренне это использует API libXrandr. Xinerama более или менее устарела, но все еще работает; RANDR - это новый способ обработки нескольких мониторов в X.

2 голосов
/ 07 июля 2010

Это работает для TwinView, другие я не проверял:

#!/usr/bin/python
# Print some information about the X environment, the monitor setup, currently active window and cursor position
import gtk.gdk

screen = gtk.gdk.screen_get_default()
print "X default screen size: %d x %d" % (screen.get_width(), screen.get_height())
print "xid of root window: %d" % screen.get_root_window().xid

monitors = int(screen.get_n_monitors())
print "== %d monitors ==" % monitors
for m in range(0, monitors):
    print " - geometry of monitor %d: %s" % (m, screen.get_monitor_geometry(m))

window = screen.get_active_window()
win_x, win_y, win_w, win_h, win_bit_depth = window.get_geometry()
print "active window on monitor: %d" % screen.get_monitor_at_point((win_x+(win_w/2)),(win_y+(win_h/2)))
print "window geometry (x,y,w,h): %d, %d, %d, %d" % (win_x,win_y,win_w,win_h)

display = gtk.gdk.display_get_default()
pointer = display.get_pointer()
print "cursor position (x, y): %d, %d" % (pointer[1], pointer[2])
print "cursor on monitor: %d" % screen.get_monitor_at_point(pointer[1],pointer[2])
1 голос
/ 08 мая 2009

Я всегда использую команду "xdpyinfo", чтобы определить размер экрана; выполните команду, затем посмотрите на вторую или третью страницу вывода, где написано что-то вроде:

screen #0:
  dimensions:    1280x800 pixels (339x212 millimeters)
  resolution:    96x96 dots per inch
  depths (7):    24, 1, 4, 8, 15, 16, 32
  root window id:    0xac
  depth of root window:    24 planes
  ...

Вы можете либо выполнить эту команду извне и получить измерения с помощью обработки текста, либо вы можете быстро загрузить код xdpyinfo и скопировать вызовы C, которые он делает, для создания этой строки вывода. Удачи!

...