当前位置: 首页 > 知识库问答 >
问题:

打开全屏OpenGL窗口

贺栋
2023-03-14

我试图在linux red hat上使用GLFW打开一个OpenGL全屏窗口。我有一个桌面,它跨越两个显示器,总分辨率为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毫米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

似乎当窗口被显示时,它的大小会缩小。

共有2个答案

任长卿
2023-03-14

xcb版本:

    xcb_connection_t *xcbConnection = xcb_connect(":0", &screenp);
    xcb_intern_atom_cookie_t type = xcb_intern_atom(xcbConnection, false, strlen("_NET_WM_FULLSCREEN_MONITORS"), "_NET_WM_FULLSCREEN_MONITORS");
    xcb_intern_atom_reply_t *reply_st = xcb_intern_atom_reply(xcbConnection, type, NULL);

    xcb_client_message_event_t event;
    memset(&event, 0, sizeof(event));
    event.response_type = XCB_CLIENT_MESSAGE;
    event.type = reply_st->atom;
    event.window =  this->winId();
    event.format = 32;
    event.data.data32[0] =  0; // top
    event.data.data32[1] =  0; // bottom
    event.data.data32[2] =  0; // left
    event.data.data32[3] =  1; // right

    event.data.data32[4] = 1;
    uint32_t eventMask = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT|XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
    xcb_send_event(xcbConnection, false, pScreen0->root, eventMask, reinterpret_cast<const char*>(&event));
    xcb_flush(xcbConnection);
顾曾笑
2023-03-14

我不知道GLFW,也许它有缺陷,但X11全屏窗口不是这样工作的。任何称职的窗口管理器都会迫使窗口适应(单一的、非虚拟的)屏幕。

您想要完全绕过窗口管理器(使用OverrideRedirectwindow属性),或者要求WM配合(使用window属性\u NET\u WM\u STATE\u 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);

}

您可能需要从一开始就使用窗口的真实屏幕尺寸,以避免任何调整大小的动画效果。

我没有在多头系统上尝试这个,因为我没有,但在单显示系统上它工作正常(覆盖面板、移除窗户装饰等)。请让我知道它是否适合你。

更新他们说,要让multihead工作,你需要使用\u NET\u WM\u全屏\u监视器属性(参见此处)。它是一个由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);

有了这个功能,你就可以将你的全屏窗口设置为占据一个显示器、整个桌面,或者(对于超过两个显示器)中间的任何东西。

我没有检查这个,因为我没有多头系统。

 类似资料:
  • 我有两台显示器;创建 LWJGL 窗口时: 它总是出现在我的左侧屏幕上。是否有一个参数可以设置以更改它出现在哪个屏幕上,例如:

  • 我尝试使用OpenGL绘制贝塞尔曲面。我的程序读取一个输入文件,其中包含用于绘图的采样点数量、用于表面着色的控制点和调色板。它必须输出一个带有曲面图的新窗口,我可以在其中操纵曲面和控制点的属性。 从Bernstein多项式生成的点被三角化,并通过从三角形的最小和最大高度映射它来按调色板分配颜色。 不幸的是,它打开了一个窗口,其中当前窗口的一部分在操作系统中打开,而没有为surface创建新界面。

  • 我在Firefox中远程使用Webdriver。 我想全屏打开我的浏览器。浏览器是全屏打开的,但立即最小化,并移动到其他程序,在我的操作系统上打开。当我在本地运行我的webdriver时,broser是全屏打开的,并且不会最小化(它留在浏览器中,不会移动到其他程序)。我希望我的浏览器会在全屏打开,并且保持在浏览器中,即使我运行我的测试Remottley。 原因是我使用了Java机器人,我必须在浏览

  • 我的Android应用程序需要显示一个全屏位图作为背景,然后在上面使用OpenGL ES显示一些动态的3D图形(1.1或2.0--尚未决定)。背景图像是同一个应用程序中WebView组件的快照,因此它的尺寸已经完全适合屏幕。 我是OpenGL新手,但我知道显示位图的常规方法包括将其缩放成一个POT纹理(glTexImage2D)、配置矩阵、为矩形创建一些顶点并使用GLDraWarrays来显示。似

  • 我有一些问题与GLFW的窗口创建。我希望有一个程序能够在窗口和全屏模式之间切换。要在GLFW 2.7.8中做到这一点,必须首先销毁活动窗口,然后创建一个新的窗口。我读到3.0版本支持多个窗口,但它仍在开发中。 我提供了自己的功能来处理键盘输入。使用最初的400×400窗口,程序按预期运行;它将在f或F上进入全屏,当按下转义键时退出,当按下任何其他键时都会抱怨。 但是,当进入全屏模式时,窗口对我提供