我在Ubuntu上遇到了一些有關全屏行爲的奇怪問題。窗口模式工作正常,但「假」(SDL_WINDOW_FULLSCREEN
)和「真實」(SDL_WINDOW_FULLSCREEN_DESKTOP
)全屏模式都沒有。Ubuntu中的全屏模式(SDL + OpenGL)
在Windows上,「假」全屏模式會更改視頻模式,並且我們將窗口的內容看到整個顯示屏。 「真實」全屏模式需要桌面的大小。在這種模式下,我在左上角繪製窗口的內容,並將其餘區域留空。
在Ubuntu上,「假」全屏模式會改變視頻模式,並且窗口的內容會被拉伸到整個顯示屏,但只會繪製其中的一部分內容。它可以是頂部(顯示器的90%以上)或底部(顯示器的10%以下)。未繪製的部分爲黑色或包含應用程序定義之前在屏幕上繪製的內容。有時候應用程序在退出時不會改變視頻模式。即使只繪製底部部分,光標也會鎖定在頂部內部。
「真實」全屏模式可能是全黑或在顯示屏中央顯示窗口內容。內容轉移到頂部,並且該區域周圍的所有內容都是黑色的(儘管背景顏色不是)。在這種模式下,光標被鎖定在該區域內。
如果我在運行時更改全屏模式,繪製區域(也是光標被鎖定的區域)的行爲會有所不同,它不僅可以位於任何位置,不僅可以位於「假」模式的頂部/底部,也可以位於「真實」 。
- 在Windows上 「打假」 全屏模式:
(800×600:視頻模式)
- 「真實」 在Windows全屏模式:
(800×600窗口的內容繪製在角落裏,其他面積空)
- 「假」全屏Ubuntu的模式:
(800×600:視頻模式,但不是整個區域可見你可以看到,雖然gedit中的一部分。 )
- 「真正的」全屏Ubuntu的模式:
(800x600的區域中心,但圖像轉移到頂部(紅方意味着要在角落))
我很手動使用OpenGL在屏幕上繪製而不是SDL。我寫了一個小例子來說明問題。它創建一個800x600的窗口,並在它的中心繪製一個藍色三角形。綠色正方形畫在屏幕的角落,紅色正方形畫在窗口的角落(這些可以在同一個地方,所以綠色方塊比較大,紅色正方形畫在上面)。可以分別使用'1','2'或'3'鍵輸入窗口化的「假」或「真實」全屏模式。退出鍵關閉應用程序。
#include <SDL.h>
#include <GL/gl.h>
#define FULLSCREEN 0
#define WIDTH 800
#define HEIGHT 600
//fullscreen:
// 0 - windowed mode,
// 1 - "fake" fullscreen mode,
// 2 - "real" fullscreen mode
int real_width;
int real_height;
//screen width & height - to draw green square that shows us actual screen size
void set_viewport(SDL_Window* window);
void draw(SDL_Window* window);
int main(int argc, char* argv[]) {
SDL_Init(SDL_INIT_VIDEO);
int position;
#if FULLSCREEN == 0
position = SDL_WINDOWPOS_CENTERED;
#else
position = 0;
#endif
//the only thing I've found - some guy said it works
//if window is in (0,0) while entering fullscreen
//well, it's not, but I've kept it
int flags = SDL_WINDOW_OPENGL;
#if FULLSCREEN == 1
flags |= SDL_WINDOW_FULLSCREEN;
#elif FULLSCREEN == 2
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
#endif
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window* window = SDL_CreateWindow(
"",
position, position, /* centered/(0,0) */
WIDTH, HEIGHT, /* request 800x600 window */
flags /* needed mode */
);
//setup GL
SDL_GLContext glcontext = SDL_GL_CreateContext(window);
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
//viewport and projection
set_viewport(window);
draw(window);
bool done = false;
while(!done) {
draw(window);
SDL_Event event;
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT: done = true; break;
case SDL_KEYDOWN:
if(event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
done = true;
else if(event.key.keysym.scancode == SDL_SCANCODE_1) {
SDL_SetWindowFullscreen(window, 0);
set_viewport(window);
} else if(event.key.keysym.scancode == SDL_SCANCODE_2) {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
set_viewport(window);
} else if(event.key.keysym.scancode == SDL_SCANCODE_3) {
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
set_viewport(window);
}
break;
}
}
}
SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
void set_viewport(SDL_Window* window) {
SDL_GetWindowSize(window, &real_width, &real_height);
glClearColor(1, 1, 1, 1);
glViewport(0, 0, real_width, real_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, real_width, real_height, 0, -1, 0);
}
void draw_triangle();
void draw_square(int x, int y, float side);
void draw(SDL_Window* window) {
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//triangle on while background
glClearColor(1, 1, 1, 1);
draw_triangle();
//green square at screen corner
glColor3f(0, 1, 0);
draw_square(real_width, real_height, 20);
//red square at window corner
glColor3f(1, 0, 0);
draw_square(WIDTH, HEIGHT, 10);
SDL_GL_SwapWindow(window);
}
void draw_triangle() {
const float w = 460;
const float h = 400;
float colorBuffer[9] = {
0, 0.43f, 0.85f /*#006dd9*/,
0, 0.22f, 0.43f /*#00376e*/,
0, 0.43f, 0.85f /*#006dd9*/
};
float vertexBuffer[9] = {
0, 0, 0,
w/2, h, 0,
w, 0, 0
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glTranslatef((WIDTH-w)/2,(HEIGHT-h)/2,0);
glColorPointer(3, GL_FLOAT, 0, colorBuffer);
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
glTranslatef(-(WIDTH-w)/2,-(HEIGHT-h)/2,0);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
void draw_square(int x, int y, float side) {
float vertexBuffer[12] = {
0, 0, 0, /*top left*/
0, side, 0, /*bottom left*/
side, side, 0, /*bottom right*/
side, 0, 0 /*top right*/
};
glEnableClientState(GL_VERTEX_ARRAY);
glTranslatef(x-side/2, y-side/2, 0);
glVertexPointer(3, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glTranslatef(-x+side/2, -y+side/2, 0);
glDisableClientState(GL_VERTEX_ARRAY);
}
SDL_WINDOW_FULLSCREEN意思是「按照用戶請求的最接近的匹配視頻模式進行全屏顯示」,而SDL_WINDOW_FULLSCREEN_DESKTOP表示「以當前桌面分辨率全屏顯示」,我不明白你的意思。根據窗口管理器,顯卡驅動程序,顯示器數量,xrandr支持等(在我的系統上運行KDE + nVidia blob + Twinview),Linux上更改模式可能會也可能不會正常工作。如果您的系統沒有按預期運行,請儘可能詳細地填寫錯誤。 – gabomdq