Открытие полноэкранного окна OpenGL

Я пытаюсь открыть окно OpenGL в полноэкранном режиме, используя GLFW на Linux Red Hat. У меня есть рабочий стол, который охватывает два монитора с общим разрешением 3840 * 1080.

У меня две проблемы: 1. Окно открывается только на одном мониторе с максимальной шириной окна 1920 (ширина одного монитора). 2. Максимальная высота окна составляет 1003 (я думаю, что высота экрана минус высота панели задач и верхней панели).

Это код, который я использую, чтобы открыть окно:

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";

выход: ширина = 1920 высота = 1003

РЕДАКТИРОВАТЬ: Я использовал xrandr для проверки доступного режима экрана и получил:

Экран 0: минимум 3840 x 1080, текущий 3840 x 1080, максимум 3840 x 1080 подключено по умолчанию 3840x1080 + 0 + 0 0 мм x 0 мм    3840x1080 50,0 *

EDIT2: Я изменил свой код, чтобы открыть окно с помощью 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";

выход:

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

кажется, что когда окно отображается, его размер уменьшается.

 Nicol Bolas05 июн. 2012 г., 15:06
Вы пытались перечислить доступные видео режимы и проверить, что доступно?
 datenwolf05 июн. 2012 г., 18:01
Если размер вашего окна после создания изменяется, то ваш оконный менеджер думает, что знает лучше, чем вы, что делать. В этом случае я просто изменяю WM или подаю отчет об ошибке разработчику (ам) WM.
 Tal Darom05 июн. 2012 г., 16:09
Я использую GLFW, чтобы открыть окно, поэтому нет. Я использовал «xrandr» запросить режим видео: Экран 0: минимум 3840 x 1080, текущий 3840 x 1080, максимум 3840 x 1080. В настоящее время я изменяю код для непосредственного открытия окна с помощью X. Можете ли вы указать мне функцию, которая перечисляет доступные режимы видео ? подключено по умолчанию 3840x1080 + 0 + 0 0 мм x 0 мм 3840x1080 50,0 *
 Tal Darom05 июн. 2012 г., 16:37
@NicolBolas, пожалуйста, смотрите последнее изменение вопроса.

Ответы на вопрос(1)

Решение Вопроса

возможно, он глючит, но полноэкранные окна X11 не работают таким образом. Любой оконный менеджер, достойный его соли, заставит окно соответствовать (одному, не виртуальному) экрану.

Вы хотите полностью обойти оконный менеджер (используйтеOverrideRedirect атрибут окна), или попросите WM сотрудничать (используйте свойство окна_NET_WM_STATE_FULLSCREEN). Первый подход имеет множество недостатков, поэтому давайте использовать второй. Следующая программа отобразит окно на вашем дисплее, а затем переключит его в полноэкранный режим:

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

}

Вы, вероятно, используете свои реальные размеры экрана для окна с самого начала, чтобы избежать какого-либо эффекта изменения размера анимации.

Я не пробовал это в системе с несколькими головками, потому что у меня ее нет, но в системе с одним дисплеем она работает правильно (закрывает панель, удаляет декорации окон и т. Д.). Пожалуйста, дайте мне знать, если это работает для вас.

Update Говорят, чтобы мультиголовка работала, нужно использовать_NET_WM_FULLSCREEN_MONITORS собственность (см.Вот). Это массив из 4 целых чисел, который должен быть установлен следующим образом:

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

Благодаря этому вы сможете настроить полноэкранные окна на один монитор, весь рабочий стол или (для более чем 2 мониторов) что-либо промежуточное.

Я не проверял это, потому что у меня нет многоголовочной системы.

 Tal Darom06 июн. 2012 г., 15:15
Спасибо за подробный ответ. Прежде чем я увидел ваш ответ, я попытался использовать OverrideRedirect (ваш первый предложенный подход). В конце концов я включил режим Xinerama в xorg.conf (режим, который заставляет WM думать, что есть только один большой монитор).
 19 мар. 2018 г., 08:50
Большое спасибо, это единственный ответ, который мне подходит для полноэкранного режима X11, кроме того: xev.xclient.data.l [0] = 1; можно изменить на = 0 для восстановления или = 2 для переключения.

Ваш ответ на вопрос