SDL2: How to properly toggle fullscreen? - sdl

I have problems deactivating fullscreen mode with my program. Entering fullscreen happens correctly, but trying to go back to windowed mode doesn't work, the only effect is that the cursor gets shown again.
Here's the MCVE/SSCCE that reproduces the issue for me:
void ToggleFullscreen(SDL_Window* Window) {
Uint32 FullscreenFlag = SDL_WINDOW_FULLSCREEN;
bool IsFullscreen = SDL_GetWindowFlags(Window) & FullscreenFlag;
SDL_SetWindowFullscreen(Window, IsFullscreen ? 0 : FullscreenFlag);
SDL_ShowCursor(IsFullscreen);
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* Window = SDL_CreateWindow("",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
bool Exit = false;
for (SDL_Event Event; !Exit;) {
SDL_WaitEvent(&Event);
if (Event.type == SDL_KEYDOWN) {
switch (Event.key.keysym.sym) {
case SDLK_f: ToggleFullscreen(Window); break;
case SDLK_q: Exit = true; break;
}
}
}
SDL_DestroyWindow(Window);
SDL_Quit();
}
SDL_SetWindowFullscreen returns 0, as if the operation was successful. What am I doing wrong? (I'm using SDL 2.0.3 on OS X 10.10.3.)

It looks like a known issue. Hopefully the SDL developers will fix it. I found the following bug report.
https://github.com/libsdl-org/SDL/issues/1428

Even now there still appears to be a problem with SDL_SetWindowFullscreen. I tried to add fullscreen functionality to my video player with this function. However, it would randomly crash when transitioning between fullscreen and windowed mode.
I found a temporary work around that appears to be working correctly for now.
SDL_DisplayMode dm;
if (SDL_GetDesktopDisplayMode(0, &dm))
{
printf("Error getting desktop display mode\n");
return -1;
}
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYUP:
switch (event.key.keysym.sym)
{
case SDLK_f:
SDL_RestoreWindow(screen); //Incase it's maximized...
SDL_SetWindowSize(screen, dm.w, dm.h + 10);
SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
}
break;
}
}
It's basically "fake" fullscreen. It resizes the window so the client area covers the whole screen and the minimize, maximize, exit buttons are off screen.
Hope this helps.

I know this may be 5 years after date, but I was facing the same problem, and I found your code way more complex then need be. So I just wanted to add for however comes here:
//somewhere outside the loop
bool isFullScreen = true;
void toggleFullScreen(SDL_Window* window, bool currentState)
{
isFullScreen = !currentState;
SDL_SetWindowFullscreen(window, !currentState);
SDL_ShowCursor(currentState);
}
just place the isFullscreen at the currenState and you have a good toggle with a keypress event.

This works fine for me in SDL2(pressing f toggles it on/off and q quits):
SDL_Window* window = SDL_CreateWindow("Fullscreen demo", 0, 0, 640, 480, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
SDL_Event event;
bool fullScreen = false;
SDL_bool running = SDL_TRUE;
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = SDL_FALSE;
break;
case SDL_KEYDOWN:
if(event.key.keysym.scancode == SDL_SCANCODE_F){
fullScreen = !fullScreen;
if(fullScreen){
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
}
else{
SDL_SetWindowFullscreen(window, 0);
}
}
if(event.key.keysym.scancode == SDL_SCANCODE_Q){
running = SDL_FALSE;
}
break;
default: break;
}
}
// drawing stuff here...
// swap and display buffer
SDL_RenderPresent(renderer);
}

Related

Why doesn't the default case run here?

I wrote these following lines of codes:
#include <sdl.h>
#include <iostream>
#include <stdio.h>
#include <string>
bool running = true;
enum KeyPressSurfaces {
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
//de deallocate surface
KEY_PRESS_SURFACE_TOTAL
};
int main(int argc, char** argv) {
//standard stuffs
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("vibin' with smug pika", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 300, 300, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface* loadSurface(std::string path);
SDL_Surface* surface = SDL_GetWindowSurface(window);
SDL_Surface* keypress [KEY_PRESS_SURFACE_TOTAL];
//anh hien tai dang duoc load, de BlitSurface len surface
//SDL_BlitSurface(current --> surface)
SDL_Surface* current = NULL;
//set windows icon
SDL_Surface* icon = SDL_LoadBMP("../pikachu/keypress_bmp/icon.bmp");
SDL_SetWindowIcon(window, icon);
SDL_Event event;
//load each image into the keypress array
keypress[KEY_PRESS_SURFACE_DEFAULT] = SDL_LoadBMP("../pikachu/keypress_bmp/default.bmp");
keypress[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("../pikachu/keypress_bmp/up.bmp");
keypress[KEY_PRESS_SURFACE_DOWN] = SDL_LoadBMP("../pikachu/keypress_bmp/down.bmp");
keypress[KEY_PRESS_SURFACE_LEFT] = SDL_LoadBMP("../pikachu/keypress_bmp/left.bmp");
keypress[KEY_PRESS_SURFACE_RIGHT] = SDL_LoadBMP("../pikachu/keypress_bmp/right.bmp");
while (running) {
while (SDL_PollEvent(&event)){
switch (event.type) {
//user click x
case SDL_QUIT:
running = false;
break;
//where all the user inputs are handled
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_UP:
current = keypress[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
current = keypress[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
current = keypress[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
current = keypress[KEY_PRESS_SURFACE_RIGHT];
break;
case SDLK_SPACE:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
break;
default:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
}
}
}
SDL_BlitSurface(current, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
}
//deallocating surfaces
for(int i=0; i<KEY_PRESS_SURFACE_TOTAL; ++i) {
SDL_FreeSurface(keypress[i]);
keypress[i] = NULL;
}
//destroy everythangggg
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}
However, this bit:
default:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
does not run at all, no matter where I put it. The program should have shown the default image at the beginning, but there's only black when I compiled. Everything else runs fine and I cannot determine what mistake I make.
I'm using CodeBlock version 20.03 and the latest version of SDL2.
I created a solution for you, and I have some notes to check from your end,
Check if the file path is correct
../pikachu/keypress_bmp/default.bmp.
When you want to trigger the default, you should press another key
e.i Enter, A, B, etc.
I have downloaded an SDL library I am not sure if you are using the
same, but mine is V2.
I have commented on your code, which I didn't use here in the image
path.
here is my code and result:
//#include <sdl.h>
#include <SDL.h>
#include <iostream>
#include <stdio.h>
#include <string>
bool running = true;
enum KeyPressSurfaces {
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
//de deallocate surface
KEY_PRESS_SURFACE_TOTAL
};
int main(int argc, char** argv) {
//standard stuffs
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("vibin' with smug pika", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 300, 300, 0);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface* loadSurface(std::string path);
SDL_Surface* surface = SDL_GetWindowSurface(window);
SDL_Surface* keypress[KEY_PRESS_SURFACE_TOTAL];
//anh hien tai dang duoc load, de BlitSurface len surface
//SDL_BlitSurface(current --> surface)
SDL_Surface* current = NULL;
//set windows icon
//SDL_Surface* icon = SDL_LoadBMP("../pikachu/keypress_bmp/icon.bmp");
SDL_Surface* icon = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img1.bmp");
SDL_SetWindowIcon(window, icon);
SDL_Event event;
//load each image into the keypress array
/*
keypress[KEY_PRESS_SURFACE_DEFAULT] = SDL_LoadBMP("../pikachu/keypress_bmp/default.bmp");
keypress[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("../pikachu/keypress_bmp/up.bmp");
keypress[KEY_PRESS_SURFACE_DOWN] = SDL_LoadBMP("../pikachu/keypress_bmp/down.bmp");
keypress[KEY_PRESS_SURFACE_LEFT] = SDL_LoadBMP("../pikachu/keypress_bmp/left.bmp");
keypress[KEY_PRESS_SURFACE_RIGHT] = SDL_LoadBMP("../pikachu/keypress_bmp/right.bmp");
*/
keypress[KEY_PRESS_SURFACE_DEFAULT] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/imgD.bmp");
keypress[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img3.bmp");
keypress[KEY_PRESS_SURFACE_DOWN] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img4.bmp");
keypress[KEY_PRESS_SURFACE_LEFT] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img5.bmp");
keypress[KEY_PRESS_SURFACE_RIGHT] = SDL_LoadBMP("C:/Users/Awat/Desktop/bmp/img6.bmp");
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
//user click x
case SDL_QUIT:
running = false;
break;
//where all the user inputs are handled
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_UP:
current = keypress[KEY_PRESS_SURFACE_UP];
break;
case SDLK_DOWN:
current = keypress[KEY_PRESS_SURFACE_DOWN];
break;
case SDLK_LEFT:
current = keypress[KEY_PRESS_SURFACE_LEFT];
break;
case SDLK_RIGHT:
current = keypress[KEY_PRESS_SURFACE_RIGHT];
break;
case SDLK_SPACE:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
break;
default:
current = keypress[KEY_PRESS_SURFACE_DEFAULT];
}
}
}
SDL_BlitSurface(current, NULL, surface, NULL);
SDL_UpdateWindowSurface(window);
}
//deallocating surfaces
for (int i = 0; i < KEY_PRESS_SURFACE_TOTAL; ++i) {
SDL_FreeSurface(keypress[i]);
keypress[i] = NULL;
}
//destroy everythangggg
SDL_DestroyWindow(window);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}

How can I handle input in SDL?

My SDL program wont work. It was supposed to change the image when I pressed Up. However, it changes the image only when I click on the x in the Window
#include "SDL.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
int main(int argc, char* argv[])
{
enum KeyPressSurfaces {
KEY_PRESS_SURFACE_DEFAULT,
KEY_PRESS_SURFACE_UP,
KEY_PRESS_SURFACE_LEFT,
KEY_PRESS_SURFACE_RIGHT,
KEY_PRESS_SURFACE_DOWN,
KEY_PRESS_SURFACE_TOTAL
};
SDL_Init(SDL_INIT_VIDEO);
SDL_Event e;
SDL_Window* window = SDL_CreateWindow("antena1", // window's title
10, 25, // coordinates on the screen, in pixels, of the window's upper left corner
640, 420, // window's length and height in pixels
SDL_WINDOW_OPENGL);
SDL_Surface* key_press_surface[KEY_PRESS_SURFACE_TOTAL];
SDL_Surface* gImage = NULL;
SDL_Surface* gScreenSurface = NULL;
bool quit = false;
key_press_surface[KEY_PRESS_SURFACE_UP] = SDL_LoadBMP("hello_world.bmp");
gScreenSurface = SDL_GetWindowSurface(window);
gImage = SDL_LoadBMP("nick.bmp");
if (gImage == NULL) {
printf("Erro", SDL_GetError);
}
SDL_BlitSurface(gImage, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(window);
gScreenSurface = SDL_GetWindowSurface(window);
while (!quit) {
while (SDL_PollEvent(&e) == 0) {
if (e.type == SDL_QUIT) {
quit = true;
//SDL_DestroyWindow(window);#
}
else if (e.type == SDL_KEYDOWN) {
switch (e.key.keysym.sym) {
case SDLK_LEFT:
gImage = key_press_surface[KEY_PRESS_SURFACE_UP];
break;
default:
gScreenSurface = NULL;
break;
}
}
}
};
SDL_BlitSurface(gImage, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(30000);
return 0;
}
https://wiki.libsdl.org/SDL_PollEvent
SDL_PollEvent returns 0 if there are no events available. So per the example in the above article, in order to get into the while statement for SDL_PollEvent, there must be events in the queue. However, your code only goes into the loop if there are NO events in the queue. So anything that happens once you get there is undefined.
IOW, just remove the "== 0".

SDL_WINDOWEVENT_SIZE_CHANGED and SDL_WINDOWEVENT_RESIZED not working?

I'm trying to detect, when the size of a SDL2 window changed. But neither SDL_WINDOWEVENT_RESIZED nor SDL_WINDOWEVENT_SIZE_CHANGED are working, at least on MacOS.
This is my code:
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *win = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100, 100, SDL_WINDOW_RESIZABLE);
SDL_Renderer *ren = SDL_CreateRenderer(win, 0, 0);
bool running = true;
SDL_Event event;
while (running) {
while(SDL_PollEvent(&event) != 0) {
if(event.type == SDL_QUIT) {
running = false;
}
if(event.type == SDL_WINDOWEVENT_SIZE_CHANGED) {
return 3;
}
if(event.type == SDL_WINDOWEVENT_RESIZED) {
return 4;
}
}
SDL_RenderClear(ren);
}
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
When running the program and resizing the window nothing happens. Am I doing something wrong or is it a bug?
Edit: I looked up the documentation on window events(https://wiki.libsdl.org/SDL_WindowEvent).
It says to write something like this:
event.window.type == SDL_WINDOWEVENT_SIZE_CHANGED
But this also isn't working.
SDL_WINDOWEVENT_* are not event types but SDL_WindowEventID. That is, if your event.type is SDL_WINDOWEVENT, you can access window union field for extra data, including event, e.g.
while(SDL_PollEvent(&event)) {
if(event.type == SDL_WINDOWEVENT) {
if(event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
// ...
}
}
}

Weird SDL Keyboard Issues

So I've tried this on two machines running two different OS's and the same thing happens between them.
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, char *argv[])
{
bool running = true;
SDL_Init( SDL_INIT_EVERYTHING);
SDL_Window* win = SDL_CreateWindow("test", 100, 100, 800, 600,
SDL_WINDOW_SHOWN);
SDL_Renderer* ren = SDL_CreateRenderer(win, -1, 0);
int r = 0;
while(running)
{
SDL_Event event;
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_d:
r++;
break;
case SDLK_RIGHT:
r++;
break;
}
break;
}
SDL_SetRenderDrawColor(ren, r, 255, 255, 255);
SDL_RenderClear(ren);
SDL_RenderPresent(ren);
}
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
When holding down the right arrow key, it flickers, r is increasing much faster.
When holding down d, it slowly increases.
Why?
SDL_PollEvent returns 1 if there is a pending event or 0 if there are none available. You don't check return status and look into event anyway, even if you have no reason to. What you'll find here is pretty much undefined (most likely just old data - reading the same event over and over again, even if it didn't happen that often).
Correct event handling is done within a loop:
while(running) {
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
// process event here
}
// draw here
}

Error during compilation of SDL test

I'm learning to programming with SDL2. Currently, I'm making a basic exercise. My program load a background image, and a complete sprite sheet on the background. But I'm having problems while executing the program. When I execute the binary, the program window closes immediately by itself; I cant see anything. I think it is a problem with the main loop, but it looks right for me. This is my code
#include "SDL.h"
void main () {
int gameover = 0;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* TheWindow;
SDL_Renderer* RenderEngine;
SDL_Surface* LoadedSurface;
SDL_Surface* LoadedImage;
SDL_Texture* CharacterImg;
SDL_Texture* BackgroundImg;
TheWindow = SDL_CreateWindow("Character Test",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 580, SDL_WINDOW_RESIZABLE);
RenderEngine = SDL_CreateRenderer( TheWindow, -1, SDL_RENDERER_ACCELERATED);
LoadedSurface= SDL_LoadBMP("./maptest.bmp");
BackgroundImg = SDL_CreateTextureFromSurface( RenderEngine, LoadedSurface);
SDL_FreeSurface(LoadedSurface);
LoadedImage = SDL_LoadBMP("./sprite.bmp");
CharacterImg = SDL_CreateTextureFromSurface( RenderEngine, LoadedImage);
SDL_FreeSurface(LoadedImage);
SDL_Event event;
while (!gameover)
{
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
gameover = 1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
gameover = 1;
break;
}
}
break;
}
SDL_RenderClear(RenderEngine);
SDL_RenderCopy(RenderEngine, BackgroundImg, NULL, NULL);
SDL_RenderCopy(RenderEngine, CharacterImg, 120, 80);
SDL_RenderPresent(RenderEngine);
}
SDL_Quit();
}
Your code will quit the while-loop if any SDL_PollEvent happens:
while (!gameover)
{
if (SDL_PollEvent(&event)) //Any SDL_PollEvent that gets into if...
{
switch (event.type)
{
case SDL_QUIT:
gameover = 1;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
case SDLK_q:
gameover = 1;
break;
}
}
break; //...will eventually hit this break if it didn't break before
}
SDL_RenderClear(RenderEngine);
SDL_RenderCopy(RenderEngine, BackgroundImg, NULL, NULL);
SDL_RenderCopy(RenderEngine, CharacterImg, 120, 80);
SDL_RenderPresent(RenderEngine);
}