SDL_SetWindowSize调整窗口大小,但是SDL_GetWindowSize报告旧大小-在Unix中

时间:2019-07-16 06:47:21

标签: c++ linux x11 sdl-2

我不能使用SDL_GetWindowSize跨平台,因为在Unix中它不知道窗口大小发生了变化(尽管我看到了)。 Visual Studio和MinGW没问题。 (我经常遇到Unix异常的情况,但一直都是我做错了事,而其他两个平台却没有注意到。)

我在VirtualBox的64位Ubuntu 4.18.0上运行了SDL2的2.0.8 + dfsg1-4ubuntu版本;自此已在Ubuntu 5.0.0上升级到SDL2 2.0.9 + dfsg1-1ubuntu1,但行为是相同的。它在X11上使用GNOME Shell。

SDL_PollEvent的交互很奇怪。但是我确实认为有时可以称呼它为可能和合理!

那么我如何获得SDL_GetWindowSize来准确报告尺寸?

MCVE:

#include <cassert>
#include <SDL.h>

using namespace std;

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

    SDL_Window* window = SDL_CreateWindow("",0, 0,640, 480,0);      
    if (!window) return -1;

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    if (!renderer) return -1;

    //I need to be able to resize at times, so this is in the MCVE
    SDL_SetWindowSize(window, 600, 100);

    //Without this line, no problem
    SDL_PollEvent(nullptr); 

    //Assertions fail -- in Unix, not Visual Studio
    int w, h; SDL_GetWindowSize (window, &w, &h);
    assert (w == 600);
    assert (h == 100);

    return 0;
}

编辑:根据评论者的建议尝试新的测试:

#include <cassert>
#include <SDL.h>
#include <stdio.h>

using namespace std;

static void flush_event_queue(void) {
    SDL_Event ev;
    while(SDL_PollEvent(&ev)) {
        printf("ev.type=%d\n", ev.type);
        if(ev.type == SDL_WINDOWEVENT) {
            printf("window event %d\n", ev.window.event);
            if(ev.window.event == SDL_WINDOWEVENT_RESIZED || ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                printf("resized %d %dx%d\n", ev.window.event, ev.window.data1, ev.window.data2);
            }
        }
    }
}

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

    SDL_Window* window = SDL_CreateWindow("",0, 0,640, 480,0);      
    if (!window) return -1;

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    if (!renderer) return -1;

    flush_event_queue();

    SDL_SetWindowSize(window, 600, 100);
    printf("SetWindowSize\n");

    flush_event_queue();

    int w, h; SDL_GetWindowSize (window, &w, &h);
    printf("%dx%d\n", w, h);
    assert (w == 600);
    assert (h == 100);

    //Now let's draw something and see if it shows up. No--
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_Rect rect1 = {0, 0, 100, 100};
    SDL_RenderFillRect(renderer, &rect1);
    SDL_RenderPresent (renderer);

    SDL_Event sdlEvent; //Wait for key hit, so we can see rect
    do
        SDL_WaitEvent (&sdlEvent);
    while (sdlEvent.type != SDL_KEYDOWN);


    return 0;
}

结果输出为

ev.type=4352
ev.type=4352
ev.type=512
window event 1
ev.type=512
window event 2
ev.type=512
window event 1
ev.type=512
window event 4
ev.type=512
window event 3
ev.type=512
window event 12
ev.type=512
window event 15
ev.type=770
SetWindowSize
ev.type=512
window event 6
resized 6 600x100
600x100

如果我注释掉了新测试中的第一个flush_event_queue()调用,我将永远无法获得输出-它会在我的assert上崩溃。

我还添加了一些代码来绘制内容。矩形会显示-但只有当我先注释掉flush_event_queue()时。

编辑:一个可以正常工作的版本-可是个丑陋的骇客!我不相信必须有一种正确的方式来做到这一点。

#include <cassert>
#include <SDL.h>
#include <stdio.h>

using namespace std;

static void flush_event_queue(void) {
    SDL_Event ev;
    while(SDL_PollEvent(&ev)) {
        printf("ev.type=%d\n", ev.type);
        if(ev.type == SDL_WINDOWEVENT) {
            printf("window event %d\n", ev.window.event);
            if(ev.window.event == SDL_WINDOWEVENT_RESIZED || ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                printf("resized %d %dx%d\n", ev.window.event, ev.window.data1, ev.window.data2);
            }
        }
    }
}

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

    SDL_Window* window = SDL_CreateWindow("",0, 0,640, 480,0);      
    if (!window) return -1;

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    if (!renderer) return -1;

    flush_event_queue();

    SDL_SetWindowSize(window, 600, 300);
    printf("SetWindowSize\n");

    SDL_RenderPresent(renderer);
    for (int i = 0; i < 6; ++i) //Must be 6 or more to be reliable
        SDL_Delay(10);          //10 works; 1 doesn't
                                //A single SDL_Delay(60); usually works
                                //but sometimes does not

    SDL_Event event; while (SDL_PollEvent(&event)); //This isn't needed but OK

    //flush_event_queue();     //But this makes things draw too far down

    int w, h; SDL_GetWindowSize (window, &w, &h);
    printf("%dx%d\n", w, h);

    //Now let's draw something and see if it shows up. Yes, it does
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_Rect rect1 = {0, 0, 100, 100};
    SDL_RenderFillRect(renderer, &rect1);
    SDL_RenderPresent (renderer);

    SDL_Event sdlEvent; //Wait for key hit, so we can see rect
    do
        SDL_WaitEvent (&sdlEvent);
    while (sdlEvent.type != SDL_KEYDOWN);


    return 0;
}

这确实会在位置0、0处绘制一个矩形,并准确报告新窗口的大小:

ev.type=4352
ev.type=4352
ev.type=512
window event 1
ev.type=512
window event 2
ev.type=512
window event 1
ev.type=512
window event 4
ev.type=512
window event 3
ev.type=512
window event 10
ev.type=512
window event 12
ev.type=512
window event 15
ev.type=770
SetWindowSize
600x300

0 个答案:

没有答案