Get the updated screen resolution in SDL2 - sdl

With SDL2, I manage to get the resolutions and positions of my displays just fine using SDL_GetCurrentDisplayMode() and SDL_GetDisplayBounds(), however when I change the resolution externally (in this case with the Windows 7 control panel) or the respective position of the displays and call these two functions again I get the same old values, not the new resolutions and positions. That is until I restart my program of course.
I suppose SDL doesn't update those. What do I need to do to get updated values without restarting the program?

AFAIK it is not possible with SDL to get the updated resolutions (anybody please correct me if I am wrong).
A way you could approach this though, is use your OS's API. In your case you were saying that you are using Windows. So you could go ahead and use the Windows API to retrieve updated resolution information. This obviously is not portable to other OS's - so you would have to do this for every OS you want to support.
I have added a minimal example at the bottom of my answer, that shows how you can retrieve the resolution of the primary display in C++. If you want to do more elaborate handling of multiple monitors and their relative positions etc., you should take a look at this question.
#include "wtypes.h"
#include <SDL.h>
#include <iostream>
using namespace std;
void GetDesktopResolution(int& w, int& h)
{
RECT r;
GetWindowRect(GetDesktopWindow(), &r);
w = r.right;
h = r.bottom;
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("SDL", 0, 0, 640, 480, SDL_WINDOW_RESIZABLE);
bool running = true;
while(running) {
SDL_Event game_event;
if(SDL_PollEvent(&game_event)) {
switch(game_event.type) {
case SDL_QUIT:
running = false;
break;
}
}
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
cout << "SDL" << current.w << "," << current.h << '\n';
int w, h;
GetDesktopResolution(w, h);
cout << "winapi" << w << "," << h << '\n';
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}

Related

Why isn't SDL_CreateWindow showing a window when called from another class?

Rewriting this to try to provide some clarity and update the code with some things that have changed.
I am restructuring a project that used SDL2, and have encountered issues trying to create a blank window. I have attempted to structure the project similarly to the original by separating all functionality dealing with SDL_Window into its own class. If I move the call to SDL_CreateWindow into the same class as the event loop or move the event loop to the same class as the window, the window is created and shown as expected, however as it is now, the window appears to be created successfully (SDL_CreateWindow is not returning NULL) and the program doesn't seem to be hanging, but it does not display a window while the program is running.
The SDL_Window is created in the Graphics class and stored in a member variable:
Graphics::Graphics(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
screen = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h,
flags);
status = 0;
if (screen == NULL)
status = 1;
}
Graphics is instantiated in the Window class and stored in a member variable.
Window::Window(const char* title, unsigned int w, unsigned int h, unsigned int flags, int& status) {
g = Graphics(title, w,h, flags, status);
}
Window is instantiated in main, and if the window is created successfully, it starts the event loop.
{
int status;
Window window("Mirari", 640,480, SDL_WINDOW_SHOWN, status);
if (status == 0) {
window.eventLoop();
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window and renderer: %s", SDL_GetError());
return 1;
}
}
The event loop itself to be thorough (update and draw are both currently empty functions).
void Window::eventLoop() {
SDL_Event ev;
bool running = true;
while (running) {
const int start_time = SDL_GetTicks();
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
//update();
//draw();
std::cout << "." << std::endl;
const int elapsed = SDL_GetTicks() - start_time;
if (elapsed < 1000 / FPS)
SDL_Delay(1000 / FPS - elapsed);
}
}
SDL is initialized with this static function and these flags.
void Window::init(unsigned int sdl_flags, IMG_InitFlags img_flags) {
SDL_Init(sdl_flags);
IMG_Init(img_flags);
TTF_Init();
}
...
Window::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER, IMG_INIT_PNG);
I know that a window can be created in a separate class because the first version of this project did that and it worked, I'm just not sure what has changed that is causing the window not to show up.
As said by some programmer dude, you design is not perfect and should be thought again.
Nevertheless, from what we can see on your code : If the Window constructor is called (and the SDL_Init was called before, which I assume so), then the windows should be created.
From there we only can guess what we can't see (as it's not part of what you are displaying) :
is the definition of SDL_WINDOWPOS_UNDEFINED, the same in both context ?
is the screen variable definition the same in both context ?
is the "screen" used in "update", or "draw" method, and, as uninitialized : it fails
... ?
As you probably are new to development, I suggest you adopt this habit very early : your code should check and report everything it does. A good program is easy to debug, as it says what's wrong
For instance, just after :
screen = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h, flags);
you may want to write something like :
if(!screen)
{
std::cout << "Failed to create window\n";
return -1;
}
or better :
if(!screen)
{
throw std::exception("Failed to create window\n");
}
And so on.
For instance, in your function update, you may want to have something like :
if(!screen)
{
throw std::exception("Unable to update the display as it is uninitialized\n");
}
I assume your application would not end without any comment... but that's a guess

SDL_Init(SDL_INIT_VIDEO)returns 1

Just wondering , anyone got that issue:
I'm using Visual Studio Community and after adding class and moving SDL_Init(SDL_INIT_VIDEO) from main function to Someclass.cpp my Window is not appearing anymore. SDL_Init returns 1.
I thought it's just my code related issue but I copied tutor code and that's not working as well in my environment.(his eclipse works as it should) It used to work properly when SDL_Init(SDL_INIT_VIDEO) was called from main.cpp.
I was trying to add additional dependencies in Project/Settings/Linker/Input/Additional Dependencies
but no success:( Maybe I was doing something wrong.
SDL Window still doesn't appear.
This is the function which initialize SDL video:
SDL_Window* Screen::Init(uint32_t w, uint32_t h, uint32_t mag){
if (SDL_Init(SDL_INIT_VIDEO))
{
std::cout << "Error SDL_Init Failed" << SDL_GetError() << std::endl;
return nullptr;
}
mWidth = w;
mHeight = h;
moptrWindow = SDL_CreateWindow("Arcade", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, mWidth * mag, mHeight * mag, 0);
if (moptrWindow)
{
mnoptrWindowSurface = SDL_GetWindowSurface(moptrWindow);
SDL_PixelFormat* pixelFormat = mnoptrWindowSurface->format;
Color::InitColorFormat(pixelFormat);
mClearColor = Color::Black();
mBackBuffer.Init(pixelFormat->format, mWidth, mHeight);
mBackBuffer.Clear(mClearColor);
}
return moptrWindow;
}
The main function from where Init is called:
int main(int argc, const char* argv[]){
Screen theScreen;
theScreen.Init(SCREEN_WIDTH, SCREEN_HEIGHT, MAGNIFICATION);
theScreen.Draw(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, Color::Yellow());
theScreen.SwapScreens();
SDL_Event sdlEvent;
bool running = true;
while (running)
{
while (SDL_PollEvent(&sdlEvent))
{
switch (sdlEvent.type)
{
case SDL_QUIT:
running = false;
break;
}
}
}
return 0;
}
Output is:
1
C:\Users\MyPC\projects\drawing-line\Debug\drawing-line.exe (process 13032) exited with code 0.
Press any key to close this window . . .
If anyone wants to try my code there is link to google drive:
that's whole project
Thank you.
Luke
Eventually I resolved the problem. I changed all settings to X64 and got rid of const in: int main(int argc,const char* argv[]). Now works as it should.Took me while:)

c++ sdl window freeze and issues with sdl

SDL just pisses me off, please help.
I'm trying just to show a window, this is the code :
#include <iostream>
#define SDL_MAIN_HANDLED
#include "SDL.h"
int main()
{
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Window *window = SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 600, 480, SDL_WINDOW_SHOWN);
if (window == NULL)
return 1;
SDL_Event event;
bool running = true;
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
}
}
}
SDL_Quit();
std::cout << "Hello :)" << std::endl;
return 0;
}
Now, the issue is that it says that the program now responding and I have a "loading" icon for the mouse. Second issue is that I cannot use SDL_INIT_EVERYTHING for some reason, it just gets stuck and nothing outputs when I try to output after init.
I tried multiple sdl files x86 , x64.
I have windows 10 64bit OS.
I really start to lose my sanity here , please help.
EDIT :
the window works perfectly fine with SDL_INIT_EVERYTHING but it takes the computer to load everything for 1 minute and 50 seconds. which is a lot of time.
But when I only init SDL_INIT_VIDEO , it's not responding.
Any solution ?
Okay, so I have downloaded an older version 2.0.5 instead of the new "stable" version and seems like it works. I guess the new version just have bugs that needs to be fixed.

SDL and SDL_image program doing nothing in Eclipse

I have been trying to make a PNG image appear on-screen to my SDL window. I am using the Eclipse CDT. SDL.h and SDL_image.h both seem to have been correctly linked, in that the functions pop up with colour on the compiler. When I run my code, however, literally nothing happens. There are no errors in the compiler, no comments, nothing. The window doesn't appear. I would really appreciate if anyone could help me out on the matter.
Also, SDL has worked previously on my computer before (without using SDL_image) - in which I ran a particle simulation that worked perfectly fine.
My code:
#include <iostream>
#include "SDL.h"
#include "SDL_image.h"
using namespace std;
SDL_Window *m_window; //Window upon which the game will be displayed.
SDL_Renderer *m_renderer; //Renderer used to draw the objects on the window.
SDL_Texture *playerTex;
int SCREEN_WIDTH = 600;
int SCREEN_HEIGHT = 600;
int main(int argc, char* args[]) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
cout << "Video init failed" << endl;
return 1;
}
//Creates the actual SDL-window and stores it in the m_window variable.
m_window = SDL_CreateWindow("Marko Beocanin SDD Project",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_FULLSCREEN);
//Error-checking method that determines if SDL could not create a window - returns false if unsuccessful.
if (m_window == NULL) {
cout << "Window Creation failed" << endl;
SDL_Quit();
IMG_Quit();
return 2;
}
//Creates an SDL-Renderer: a tool used to actually draw objects on the Window
m_renderer = SDL_CreateRenderer(m_window, -1, 0);
//Error-checking method that determines if SDL could not create a renderer - returns false if unsuccessful.
if (m_renderer == NULL) {
cout << "Renderer creation failed." << endl;
SDL_DestroyWindow(m_window);
SDL_Quit();
IMG_Quit();
return 3;
}
SDL_Surface *tmpSurface = IMG_Load("img.png");
playerTex = SDL_CreateTextureFromSurface(m_renderer, tmpSurface);
SDL_FreeSurface(tmpSurface);
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, playerTex, NULL, NULL);
SDL_RenderPresent(m_renderer);
SDL_Delay(2000);
SDL_DestroyWindow(m_window);
SDL_Quit();
IMG_Quit();
return 0;
}
The problem I had was a result of me using the wrong SDL_image library - I was using x64 instead of x86, which meant that it didn't throw an error per se, just didn't work properly!

SDL2 multiple windows focus

I have some problems with windows focus in SDL2.
I got two windows and listen to focus gain and lost events.
When I click on Window 2, the following events trigger:
"Window 1 lost focus"
"Window 2 gained focus."
When I click on Window 1, the following events trigger:
"Window 2 lost focus."
"Window 1 gained focus."
"Window 1 lost focus."
I can clearly tell the window has focus by the glowing effect my operating system draws around it.
Also, other SDL2 functions to get focus information give the same, wrong, answer when tested on Window 1.
I trimmed down the code to an almost-minimal test case:
#include <iostream>
#include <SDL2/SDL.h>
using namespace std;
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* w1=SDL_CreateWindow("Window 1",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
250,200,SDL_WINDOW_SHOWN);
SDL_Window* w2=SDL_CreateWindow("Window 2",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
200,250,SDL_WINDOW_SHOWN);
bool quit=false;
while(!quit){
SDL_Event e;
while(!quit && SDL_PollEvent(&e)){
switch(e.type){
case SDL_WINDOWEVENT :
{ // this block just scopes 'targetWindow' and 'title'
SDL_Window* targetWindow=SDL_GetWindowFromID(e.window.windowID);
const char* title=SDL_GetWindowTitle(targetWindow);
switch(e.window.event){
case SDL_WINDOWEVENT_FOCUS_GAINED :
// tell which window gained focus
cout << title << " gained focus!" << endl;
break;
case SDL_WINDOWEVENT_FOCUS_LOST :
// tell which window lost focus
cout << title << " lost focus!" << endl;
break;
}
}
break;
case SDL_QUIT :
quit=true;
break;
}
}
}
SDL_Quit();
return 0;
}
Is this a bug in SDL2 multi-windows support?
Does it depend on the underlying windowing system?
More importantly, is there a way to have correct focus information for multiple windows with SDL2?
I did a little more research on this and find out that the issue I described is a known bug as can be seen here.
There's a patch at the other end of the link but that's already included in the latest version of SDL.
Personally, I solved this by installing version 2.0.3 of the library.