Programaticamente determinar individuais tela larguras / alturas em Linux (w / Xinerama, TwinView, e / ou BigDesktop)

StackOverflow https://stackoverflow.com/questions/836086

Pergunta

Estou desenvolvendo um projeto paralelo pouco para exibir vários papéis de parede em várias telas no GNOME (algo que, aparentemente, não pode ser feito por si mesmo ou qualquer outra coisa GNOME). Eu descobri como fazer a parte principal dele (usando os componentes ImageMagick, para os curiosos); Eu estou tentando automatizar o sistema de configuração.

Para fazer isso, eu preciso de uma maneira de determinar as dimensões das telas individuais são. Alguém pode me dar uma dica para onde olhar para isso? Eu presumo que o servidor X em si tem a informação, mas eu não sei como o meu programa pode perguntar para ele.

Foi útil?

Solução

Parece que há uma API libXinerama que podem recuperar essa informação. Eu não encontrei nenhuma informação detalhada sobre ele ainda though.

General X.org informações de programação pode ser encontrada aqui (arquivo PDF). Informações sobre as funções fornecidas pelo libXinerama pode ser encontrada aqui (online cópia de uma página de manual, e não um monte de informações no mesmo).

Aqui está um pequeno programa C ++ que eu chicoteado até a partir dessas referências para recuperar as dimensões e deslocamentos de cada um dos monitores ligados em Xinerama. Ele também funciona para nVidia TwinView; Eu atualmente não tem uma placa ATI para testá-lo em seu sistema BigDesktop, mas eu suspeito que iria trabalhar com ele também.

#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);
}

Outras dicas

Tente algo como

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);
}

Internamente este usa a API libXrandr. Xinerama é mais ou menos obsoleto, mas ainda funciona; RANDR é a nova maneira de lidar com vários monitores no X.

Isso funciona para TwinView, eu não testei os outros:

#!/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])

Eu sempre uso o comando "xdpyinfo" para determinar o tamanho da tela; executar o comando, em seguida, olhar para a segunda ou terceira página de saída para onde ele diz algo como:

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
  ...

Você pode executar este comando externamente e agarrar as dimensões através de processamento de texto, ou você pode baixar rapidamente o código do xdpyinfo e copiar as chamadas C que faz para produzir essa linha de saída. Boa sorte!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top