2013-10-17 2 views
3

우분투에서 전체 화면 동작과 관련하여 이상한 점이 있습니다. 창 모드는 정상적으로 작동하지만 "fake"(SDL_WINDOW_FULLSCREEN) 및 "실제"(SDL_WINDOW_FULLSCREEN_DESKTOP) 전체 화면 모드는 아닙니다.우분투의 전체 화면 모드 (SDL + OpenGL)

Windows에서 "fake"전체 화면 모드는 비디오 모드를 변경하고 전체 내용이 창에 표시되는 것을 보았습니다. "실제"전체 화면 모드는 데스크톱 크기를 사용합니다. 이 모드에서는 윈도우 왼쪽 상단 모서리에 윈도우 내용을 그리고 여분의 영역을 비워 둡니다.

우분투에서 "가짜"전체 화면 모드는 비디오 모드 변경을 수행하고 창의 내용은 전체 디스플레이로 확장되지만 일부분 만 그려집니다. 상단 부분 (디스플레이의 90 % 이상) 또는 하단 부분 (디스플레이의 10 % 미만) 중 하나입니다. 그려지지 않은 부분은 검은 색이거나 응용 프로그램이 설치되기 전에 화면에 그려진 것을 포함합니다. 때로는 응용 프로그램이 종료시 다시 비디오 모드를 변경하지 않습니다. 하단 부분 만 그려지더라도 커서는 상단 부분 내부에 고정됩니다.

"실제"전체 화면 모드는 완전히 검은 색이거나 디스플레이의 가운데에 창의 내용을 표시합니다. 내용이 상단으로 이동하고 해당 영역 주변의 모든 것이 검은 색입니다 (배경색은 그렇지 않음). 이 모드에서는 커서가 해당 영역 내에서 잠 깁니다.

런타임에서 전체 화면 모드를 변경하면 동작이 조금씩 달라집니다. 즉, 커서가 잠겨있는 영역 인 "그리기 영역"은 "실제"모드의 위/아래뿐만 아니라 "실제" .

  • Windows에서 "가짜"전체 화면 모드 : (800 × 600 비디오 모드)는
  • Windows에서 "진짜"전체 화면 모드 :real windows (800 × 600 윈도우의 내용이 구석에 그려, 다른 지역은 빈) 우분투에
  • "가짜"전체 화면 모드 :fake ubuntu (800 × 600 비디오 모드가 아닌 전체 영역을 볼 수 있습니다 당신은 생각의 gedit의 일부를 볼 수 있습니다..)
  • "진짜"전체 화면 우분투 모드 :real ubuntu

내가 수동 해요) (센터 800 × 600 지역 있지만, 이미지가 위로 이동 (빨간색 사각형은 모서리에 될 운명) OpenGL을 사용하여 SDL 대신 화면에 그립니다. 문제를 보여주는 작은 예제를 썼습니다. 800x600 창을 만들고 중심에 파란색 삼각형을 그립니다. 녹색 사각형은 화면 모서리에 그려지고 빨간색 사각형은 창 모서리에 그려집니다 (녹색 사각형은 더 크고 빨간색 사각형은 그 위에 그려집니다). 하나는 각각 '1', '2'또는 '3'키를 사용하여 윈도우화된 "가짜"또는 "실제"전체 화면 모드로 들어갈 수 있습니다. Esc 키를 누르면 응용 프로그램이 닫힙니다.

#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); 
} 
+0

SDL_WINDOW_FULLSCREEN은 "사용자가 요청한 것보다 가장 가까운 일치하는 비디오 모드로 전체 화면으로 이동"을 의미하는 반면 SDL_WINDOW_FULLSCREEN_DESKTOP은 "현재 데스크톱 해상도로 전체 화면으로 이동"을 의미합니다. Linux에서 모드를 변경하면 윈도우 관리자, 그래픽 카드 드라이버, 모니터 수, xrandr 지원 등에 따라 제대로 작동하지 않을 수도 있습니다 (예 : KDE + nVidia blob + Twinview). 시스템이 예상대로 작동하지 않으면 가능한 한 자세하게 버그를 기입하십시오. – gabomdq

답변

3

특히 멀티 디스플레이 환경에서 모드 변경은 특히 그렇습니다.

대신 국경, 바탕 화면 크기의 창을 시도해보십시오
#include <GL/glew.h> 
#include <SDL2/SDL.h> 

// use border state as proxy for fullscreenedness 
SDL_Rect ToggleFakeFullscreen(SDL_Window* window, const SDL_Rect& oldBounds) 
{ 
    if(SDL_GetWindowFlags(window) & SDL_WINDOW_BORDERLESS) 
    { 
     SDL_SetWindowBordered(window, SDL_TRUE); 
     SDL_SetWindowSize(window, oldBounds.w, oldBounds.h); 
     SDL_SetWindowPosition(window, oldBounds.x, oldBounds.y); 
     return oldBounds; 
    } 
    else 
    { 
     SDL_Rect curBounds; 
     SDL_GetWindowPosition(window, &curBounds.x, &curBounds.y); 
     SDL_GetWindowSize(window, &curBounds.w, &curBounds.h); 

     int idx = SDL_GetWindowDisplayIndex(window); 
     SDL_Rect bounds; 
     SDL_GetDisplayBounds(idx, &bounds); 
     SDL_SetWindowBordered(window, SDL_FALSE); 
     SDL_SetWindowPosition(window, bounds.x, bounds.y); 
     SDL_SetWindowSize(window, bounds.w, bounds.h); 

     return curBounds; 
    } 
} 

int main(int argc, char **argv) 
{ 
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) 
     return -1; 

    SDL_Window* window = SDL_CreateWindow 
     (
     "Test", 
     SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
     640, 480, 
     SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL 
     ); 
    if(NULL == window) 
     return -1; 

    SDL_GLContext ctx = SDL_GL_CreateContext(window); 
    if(GLEW_OK != glewInit()) 
     return -1; 

    SDL_Rect curBounds; 

    bool running = true; 
    while(running) 
    { 
     SDL_Event ev; 
     while(SDL_WaitEventTimeout(&ev, 16)) 
     { 
      if(ev.type == SDL_QUIT) 
       running = false; 
      if(ev.type == SDL_KEYUP && 
       ev.key.keysym.sym == SDLK_ESCAPE) 
       running = false; 

      if(ev.type == SDL_KEYUP && 
       ev.key.keysym.sym == SDLK_f) 
       curBounds = ToggleFakeFullscreen(window, curBounds); 
     } 

     int w, h; 
     SDL_GetWindowSize(window, &w, &h); 
     glViewport(0, 0, w, h); 

     glClearColor(0, 0, 0, 1); 
     glClear(GL_COLOR_BUFFER_BIT); 

     glMatrixMode(GL_PROJECTION); 
     glLoadIdentity(); 

     glMatrixMode(GL_MODELVIEW); 
     glLoadIdentity(); 

     glColor3ub(255, 0, 0); 
     glBegin(GL_TRIANGLES); 
     glVertex2i(-1, -1); 
     glVertex2i( 1, -1); 
     glVertex2i( 0, 1); 
     glEnd(); 

     SDL_GL_SwapWindow(window); 
    } 

    SDL_GL_DeleteContext(ctx); 
    SDL_DestroyWindow(window); 
    SDL_Quit(); 

    return 0; 
} 

은 "전체 화면"을 전환 할 f을 누르십시오.

+0

음, 재미있는 아이디어. 가짜 전체 화면으로 인해 올바른 해결책이 아닌 것처럼 보이지만, 적어도 작동합니다 =) 고마워요. 내가 더 좋은 것을 찾지 못한다면 나는 이것을 사용할 것이라고 생각한다. 우분투에서는 상단 패널이 항상 창 위에 있습니다. 나에게는 괜찮은 편이지만 실제 전체 화면과는 다릅니다. –

+0

창에서 크기를 조정할 수있는 경우 가짜 전체 화면 모드에서 하단 가장자리와 왼쪽 가장자리에 작은 테두리가 표시됩니다. – manylegged