打开全屏OpenGL窗口 [英] Opening a fullscreen OpenGL window

查看:115
本文介绍了打开全屏OpenGL窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正准备在Linux red-hat上使用GLFW打开OpenGL全屏窗口.我的台式机横跨两台显示器,总分辨率为3840 * 1080.

I am tring to open an OpenGL full screen window using GLFW on linux red-hat. I have a desktop that spans two monitors with total resolution of 3840*1080.

我有两个问题: 1.窗口仅在一台监视器上打开,最大窗口宽度为1920(一台监视器的宽度). 2.窗口的最大高度为1003(我认为这是屏幕的高度减去任务栏和顶部栏的高度).

I have two problems: 1. The window is opened just on one monitor with maximum window width of 1920 (the width of a single monitor). 2. The maximum height of the window is 1003 (which I think is the height of the screen minus the height of the task bar and the top bar).

这是我用来打开窗口的代码:

This is the code I use to open the window:

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

output: width = 1920 height = 1003

我使用xrandr检查可用的屏幕模式并得到:

I used xrandr to check available screen mode and got:

屏幕0:最小3840 x 1080,当前3840 x 1080,最大3840 x 1080 默认连接3840x1080 + 0 + 0 0mm x 0mm 3840x1080 50.0 *

Screen 0: minimum 3840 x 1080, current 3840 x 1080, maximum 3840 x 1080 default connected 3840x1080+0+0 0mm x 0mm 3840x1080 50.0*

我已更改代码以使用X11打开窗口

I have changed my code to open the window using 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

似乎显示窗口时,其大小会缩小.

it seems that when the window is get displayed its size shrinks.

推荐答案

不了解GLFW,也许是越野车,但是X11全屏窗口无法正常工作.任何值钱的窗口管理器都将迫使窗口适合(单个非虚拟)屏幕.

Don't know about GLFW, perhaps it's buggy, but X11 fullscreen windows don't work like that. Any window manager worth its salt will force the window to fit the (single, non-virtual) screen.

您要完全绕开窗口管理器(使用OverrideRedirect window属性),或者要求您的WM合作(使用窗口属性_NET_WM_STATE_FULLSCREEN).第一种方法有很多缺点,所以让我们使用第二种方法.以下程序将在您的显示器上显示一个窗口,然后将其切换到全屏模式:

You want to either bypass the window manager completely (use OverrideRedirect window attribute), or ask your WM to cooperate (use window property _NET_WM_STATE_FULLSCREEN). The first approach has numerous drawbacks, so let's use the second one. The following program will display a window on your display, and then toggle it to the full-screen mode:

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

}

您可能从一开始就使用窗口的实际屏幕尺寸,以避免调整动画效果.

You probably to use your real screen dimensions for the window from the start, in order to avoid any resize animation effect.

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

I didn't try this on a multihead system because I don't have one, but on a single display system it works properly (covers the panel, removes window decorations etc). Please let me know if it works for you.

更新他们说,要使多头工作,您需要使用_NET_WM_FULLSCREEN_MONITORS属性(请参见

Update They say for multihead to work, you need to use _NET_WM_FULLSCREEN_MONITORS property (see here). It's an array of 4 integers that should be set like this:

    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个以上的显示器)介于两者之间的任何空间.

With this, you should be able to set your fullscreen windows to occupy a single monitor, the entire desktop, or (for more than 2 monitors) anything in between.

我没有检查此内容,因为我没有多头系统.

I have not checked this because I don't have a multihead system.

这篇关于打开全屏OpenGL窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆