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.
Related
This is my code:
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, const char * argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *_window;
_window = SDL_CreateWindow("Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 500, SDL_WINDOW_RESIZABLE);
SDL_Delay(20000);
SDL_DestroyWindow(_window);
SDL_Quit();
return 0;
}
Im working in Xcode. I've downloaded SDL2 and imported the library to the projects build phases. I've tested that the SDL2 works correctly.
The problem is that window never shows up. I just get a "spinning-mac-wheel" and then the program quits after the delay. I've made sure that the window is not hidden behind somewhere.
Ideas?
You have to give the system a chance to have it's event loop run.
easiest is to poll for events yourself:
SDL_Event e;
bool quit = false;
while (!quit){
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT){
quit = true;
}
if (e.type == SDL_KEYDOWN){
quit = true;
}
if (e.type == SDL_MOUSEBUTTONDOWN){
quit = true;
}
}
}
instead of the wait loop
--- Addendum
Since this answer is still helping people maybe it's nice if I also add a bit more info on why this works instead of just posting the solution.
When on the Mac (same for Windows actually) a program starts, it starts with just the 'main thread'. This is the thread which is used to set up UI stuff. The 'main thead' differs from other threads in that it comes with an event handling system. This system catches events like mouse moves, key presses, button clicks and then queues these and lets your code respond to it. All the UI things on Mac (and Windows) rely on this event pump being there and running. This is the reason why if you do anything UI related in your code you need to make sure you are not on a different thread.
Now, in your code you initialise the window and the UI, but then you do a SDL_Delay. This just blocks the thread and halts it for 20 seconds so nothing is done. And since you do that on the main thread, even the handling of the queue with the events is blocked. So on the Mac that shows as the spinning macwheel.
So the solution I posted actually keeps on polling for events and handles them. This way you are effectively also 'idling', but the moment events are posted (like mouse clicks and keys) the thread will wake up again and stuff will be processed.
You have to load a bitmap image, or display something on the window, for Xcode to start displaying the window.
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main() {
SDL_Window * window = nullptr;
SDL_Surface * window_surface = nullptr;
SDL_Surface * image_surface = nullptr;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
window_surface = SDL_GetWindowSurface(window);
image_surface = SDL_LoadBMP("image.bmp");
SDL_BlitSurface(image_surface, NULL, window_surface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(5000);
SDL_DestroyWindow(window);
SDL_FreeSurface(image_surface);
SDL_Quit();
}
You need to initialize SDL with SDL_Init(SDL_INIT_VIDEO) before creating the window.
Please remove the sdl_delay() and replace it with the below mentioned code. I don't have any reason for it but I tried on my own and it works
bool isquit = false;
SDL_Event event;
while (!isquit) {
if (SDL_PollEvent( & event)) {
if (event.type == SDL_QUIT) {
isquit = true;
}
}
}
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.
I just started learning sfml and whenever I run the following code and try to move the window it crashes:
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(1920 , 1080), "Window", Style::Close | Style::Titlebar | Style::Resize);
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
switch(event.type)
{
case event.Closed:
window.close();
break;
case event.Resized:
std::cout << "New Window Width:" << event.size.width <<std::endl;
std::cout << "New Window Height:"<< event.size.height<<std::endl<<std::endl;
break;
}
}
window.display();
}
return 0;
}
When I remove window.display() from the code I can move the window without crashing it.
I am using Codeblocks 16.01 and SFML 2.4.2
Any ideas on why that happens?
Hellow, did you try to clear the window before displaying it like this:
window.clear();
And if it doesn't work, try to draw something before display nothing like a sf::Sprite for example.
Another thing that may causes that, is the size of your window. Because your not in full-screen mode so a size of 1920x1080 is too big because a external frame will be created by the os and may be it draws out the screen... but that would be really strange...
PS: prefer to use sf::Event::Closed for your switch/case
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, ¤t);
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;
}
This is my code:
#include <iostream>
#include <SDL2/SDL.h>
int main(int argc, const char * argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *_window;
_window = SDL_CreateWindow("Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 500, SDL_WINDOW_RESIZABLE);
SDL_Delay(20000);
SDL_DestroyWindow(_window);
SDL_Quit();
return 0;
}
Im working in Xcode. I've downloaded SDL2 and imported the library to the projects build phases. I've tested that the SDL2 works correctly.
The problem is that window never shows up. I just get a "spinning-mac-wheel" and then the program quits after the delay. I've made sure that the window is not hidden behind somewhere.
Ideas?
You have to give the system a chance to have it's event loop run.
easiest is to poll for events yourself:
SDL_Event e;
bool quit = false;
while (!quit){
while (SDL_PollEvent(&e)){
if (e.type == SDL_QUIT){
quit = true;
}
if (e.type == SDL_KEYDOWN){
quit = true;
}
if (e.type == SDL_MOUSEBUTTONDOWN){
quit = true;
}
}
}
instead of the wait loop
--- Addendum
Since this answer is still helping people maybe it's nice if I also add a bit more info on why this works instead of just posting the solution.
When on the Mac (same for Windows actually) a program starts, it starts with just the 'main thread'. This is the thread which is used to set up UI stuff. The 'main thead' differs from other threads in that it comes with an event handling system. This system catches events like mouse moves, key presses, button clicks and then queues these and lets your code respond to it. All the UI things on Mac (and Windows) rely on this event pump being there and running. This is the reason why if you do anything UI related in your code you need to make sure you are not on a different thread.
Now, in your code you initialise the window and the UI, but then you do a SDL_Delay. This just blocks the thread and halts it for 20 seconds so nothing is done. And since you do that on the main thread, even the handling of the queue with the events is blocked. So on the Mac that shows as the spinning macwheel.
So the solution I posted actually keeps on polling for events and handles them. This way you are effectively also 'idling', but the moment events are posted (like mouse clicks and keys) the thread will wake up again and stuff will be processed.
You have to load a bitmap image, or display something on the window, for Xcode to start displaying the window.
#include <SDL2/SDL.h>
#include <iostream>
using namespace std;
int main() {
SDL_Window * window = nullptr;
SDL_Surface * window_surface = nullptr;
SDL_Surface * image_surface = nullptr;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
window_surface = SDL_GetWindowSurface(window);
image_surface = SDL_LoadBMP("image.bmp");
SDL_BlitSurface(image_surface, NULL, window_surface, NULL);
SDL_UpdateWindowSurface(window);
SDL_Delay(5000);
SDL_DestroyWindow(window);
SDL_FreeSurface(image_surface);
SDL_Quit();
}
You need to initialize SDL with SDL_Init(SDL_INIT_VIDEO) before creating the window.
Please remove the sdl_delay() and replace it with the below mentioned code. I don't have any reason for it but I tried on my own and it works
bool isquit = false;
SDL_Event event;
while (!isquit) {
if (SDL_PollEvent( & event)) {
if (event.type == SDL_QUIT) {
isquit = true;
}
}
}