2012-06-05 11 views
6

Sto cercando di aprire una finestra a schermo intero OpenGL utilizzando GLFW su Linux red-hat. Ho un desktop che si estende su due monitor con una risoluzione totale di 3840 * 1080.Apertura di una finestra OpenGL a schermo intero

Ho due problemi: 1. La finestra viene aperta su un solo monitor con una larghezza massima della finestra di 1920 (la larghezza di un singolo monitor). 2. L'altezza massima della finestra è 1003 (che penso sia l'altezza dello schermo meno l'altezza della barra delle attività e la barra superiore).

Questo è il codice che uso per aprire la finestra:

if (glfwInit() == GL_FALSE) 
    std::cout<< "Unable to initialize GLFW\n"; 
glfwOpenWindowHint(GLFW_STEREO, GL_FALSE); 
if (glfwOpenWindow(3840,1080,8,8,8,0,24,0,GLFW_FULLSCREEN) == GL_FALSE) 
    std::cout<< "Unable to open window\n"; 
int width, height; 
glfwGetWindowSize(&width, &height); 
std::cout << "width = " << width << " height = " << height << "\n"; 

uscita: width = 1920 height = 1003

EDIT: Ho usato xrandr per controllare la modalità a schermo disponibili e ci hanno dato:

Schermo 0: minimo 3840 x 1080, corrente 3840 x 1080, massimo 3840 x 1080 predefinito collegato 3840x1080 + 0 + 0 0mm x 0mm 3840x1080 50.0 *

.210

EDIT2: ho cambiato il mio codice per aprire la finestra utilizzando X11

int doubleBufferAttributes[] = { 
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 
GLX_RENDER_TYPE, GLX_RGBA_BIT, 
GLX_DOUBLEBUFFER, True, /* Request a double-buffered color buffer with */ 
GLX_RED_SIZE,  1,  /* the maximum number of bits per component */ 
GLX_GREEN_SIZE, 1, 
    GLX_BLUE_SIZE,  1, 
    None 
}; 

static Bool WaitForNotify(Display *dpy, XEvent *event, XPointer arg) { 
    return (event->type == MapNotify) && (event->xmap.window == (Window) arg); 
} 
int main(int argc, char *argv[]) 
{ 
    Display    *dpy; 
    Window    xWin; 
    XEvent    event; 
    XVisualInfo   *vInfo; 
    XSetWindowAttributes swa; 
    GLXFBConfig   *fbConfigs; 
    GLXContext   context; 
    GLXWindow    glxWin; 
    int     swaMask; 
    int     numReturned; 
    int     swapFlag = True; 

    /* Open a connection to the X server */ 

dpy = XOpenDisplay(NULL); 
if (dpy == NULL) { 
    printf("Unable to open a connection to the X server\n"); 
    exit(EXIT_FAILURE); 
} 

/* Request a suitable framebuffer configuration - try for a double 
** buffered configuration first */ 
fbConfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), 
           doubleBufferAttributes, &numReturned); 

/* Create an X colormap and window with a visual matching the first 
** returned framebuffer config */ 
vInfo = glXGetVisualFromFBConfig(dpy, fbConfigs[0]); 

swa.border_pixel = 0; 
swa.event_mask = StructureNotifyMask; 
swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vInfo->screen), 
           vInfo->visual, AllocNone); 

swaMask = CWBorderPixel | CWColormap | CWEventMask; 

xWin = XCreateWindow(dpy, RootWindow(dpy, vInfo->screen), 0, 0, 3840, 1080, 
         0, vInfo->depth, InputOutput, vInfo->visual, 
         swaMask, &swa); 
XWindowAttributes attt; 

XGetWindowAttributes(dpy,xWin, &attt); 
std::cout << "he = " << attt.height << " wi = " << attt.width << "\n"; 

/* Create a GLX context for OpenGL rendering */ 
context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, 
      NULL, True); 
XGetWindowAttributes(dpy,xWin, &attt); 
std::cout << "2he = " << attt.height << " wi = " << attt.width << "\n"; 


/* Create a GLX window to associate the frame buffer configuration 
** with the created X window */ 
glxWin = glXCreateWindow(dpy, fbConfigs[0], xWin, NULL); 
XGetWindowAttributes(dpy,xWin, &attt); 
std::cout << "3he = " << attt.height << " wi = " << attt.width << "\n"; 

/* Map the window to the screen, and wait for it to appear */ 
XMapWindow(dpy, xWin); 
XGetWindowAttributes(dpy,xWin, &attt); 
std::cout << "4he = " << attt.height << " wi = " << attt.width << "\n"; 

XIfEvent(dpy, &event, WaitForNotify, (XPointer) xWin); 
XGetWindowAttributes(dpy,xWin, &attt); 
std::cout << "5he = " << attt.height << " wi = " << attt.width << "\n"; 


/* Bind the GLX context to the Window */ 
glXMakeContextCurrent(dpy, glxWin, glxWin, context); 
XGetWindowAttributes(dpy,xWin, &attt); 
std::cout << "6he = " << attt.height << " wi = " << attt.width << "\n"; 

l'output è:

he = 1080 wi = 3840 
2he = 1080 wi = 3840 
3he = 1080 wi = 3840 
4he = 1080 wi = 3840 
5he = 1003 wi = 1920 
6he = 1003 wi = 1920 

sembra che quando la finestra è visualizzata ottenere la sua dimensione si restringe.

+0

Hai provato a elencare le modalità video disponibili e a verificare quali sono disponibili? –

+0

Io uso GLFW per aprire la finestra, quindi no. Ho usato 'xrandr' per interrogare la modalità video: Schermo 0: minimo 3840 x 1080, corrente 3840 x 1080, massimo 3840 x 1080. Attualmente sto cambiando il codice per aprire direttamente la finestra usando X. Puoi indicarmi a una funzione che enumera le modalità video disponibili? predefinito collegato 3840x1080 + 0 + 0 0mm x 0mm 3840x1080 50.0 * –

+0

@NicolBolas per favore vedi l'ultima modifica della domanda. –

risposta

15

Non so di GLFW, forse è bacato, ma le finestre a schermo intero X11 non funzionano così. Qualsiasi window manager che ne valga la pena forzerà la finestra ad adattarsi allo schermo (singolo, non virtuale).

Si desidera o bypass window manager completamente (utilizzare OverrideRedirect attributo finestra), o chiedere il vostro WM a collaborare (finestra alcune stanze sono _NET_WM_STATE_FULLSCREEN). Il primo approccio presenta numerosi inconvenienti, quindi usiamo il secondo. Il seguente programma visualizzerà una finestra dello schermo, e poi a ginocchiera alla modalità a schermo intero:

#include <X11/X.h> 
#include <X11/Xlib.h> 
#include <strings.h> 
#include <memory.h> 
#include <stdlib.h> 
#include <stdio.h> 

int main() 
{ 
    Display* dis = XOpenDisplay(NULL); 
    Window win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 0, 0, 10, 10, 
            0, BlackPixel (dis, 0), BlackPixel(dis, 0)); 

    Atom wm_state = XInternAtom(dis, "_NET_WM_STATE", False); 
    Atom fullscreen = XInternAtom(dis, "_NET_WM_STATE_FULLSCREEN", False); 

    XEvent xev; 
    memset(&xev, 0, sizeof(xev)); 
    xev.type = ClientMessage; 
    xev.xclient.window = win; 
    xev.xclient.message_type = wm_state; 
    xev.xclient.format = 32; 
    xev.xclient.data.l[0] = 1; 
    xev.xclient.data.l[1] = fullscreen; 
    xev.xclient.data.l[2] = 0; 

    XMapWindow(dis, win); 

    XSendEvent (dis, DefaultRootWindow(dis), False, 
        SubstructureRedirectMask | SubstructureNotifyMask, &xev); 

    XFlush(dis); 
    /*Sleep 5 seconds before closing.*/ 
    sleep(5); 
    return(0); 

} 

Probabilmente per usare le vostre dimensioni dello schermo reali per la finestra fin dall'inizio, al fine di evitare qualsiasi ridimensionamento effetto di animazione.

Non l'ho provato su un sistema multihead perché non ne ho uno, ma su un singolo sistema di visualizzazione funziona correttamente (copre il pannello, rimuove le decorazioni delle finestre ecc.). Per favore fatemi sapere se funziona per voi.

Aggiornamento Si dice per multitesta al lavoro, è necessario utilizzare _NET_WM_FULLSCREEN_MONITORS proprietà (vedi here). Si tratta di una serie di 4 numeri interi che devono essere impostati in questo modo:

Atom fullmons = XInternAtom(dis, "_NET_WM_FULLSCREEN_MONITORS", False); 
    XEvent xev; 
    memset(&xev, 0, sizeof(xev)); 
    xev.type = ClientMessage; 
    xev.xclient.window = win; 
    xev.xclient.message_type = fullmons; 
    xev.xclient.format = 32; 
    xev.xclient.data.l[0] = 0; /* your topmost monitor number */ 
    xev.xclient.data.l[1] = 0; /* bottommost */ 
    xev.xclient.data.l[2] = 0; /* leftmost */ 
    xev.xclient.data.l[3] = 1; /* rightmost */ 
    xev.xclient.data.l[4] = 0; /* source indication */ 

    XSendEvent (dis, DefaultRootWindow(dis), False, 
        SubstructureRedirectMask | SubstructureNotifyMask, &xev); 

Con questo, si dovrebbe essere in grado di impostare le finestre a schermo intero per occupare un singolo monitor, l'intero desktop, o (per più di 2 monitor) qualsiasi cosa nel mezzo

Non l'ho verificato perché non ho un sistema multihead.

+0

Grazie per la risposta dettagliata. Prima di vedere la tua risposta ho provato a utilizzare OverrideRedirect (il tuo primo approccio suggerito). Alla fine ho attivato la modalità Xinerama in xorg.conf (una modalità che induce la WM a pensare che ci sia solo un grande monitor). –