SDL2 Toggle fullscreen: Window position gets reset - c++

I'm attempting to toggle fullscreen in SDL2 and so far it works. However when the mode returns to windowed mode, the position gets reset to 0, 0. I tried storing the last position of the window before the window goes fullscreen but after it returns to windowed, the positon gets reset to 0,0 still.
I'm outputting the last position and it seems correct, yet it still gets reset to 0,0 when returning to windowed. Do I need to listen for an event or something?
void ToggleFullscreen(SDL_Window* window) {
Uint32 flag = SDL_WINDOW_FULLSCREEN;
bool isFullscreen = SDL_GetWindowFlags(window) & flag;
if(!isFullscreen){
SDL_GetWindowPosition(window, &lastWindowX, &lastWindowY);
}
SDL_SetWindowFullscreen(window, isFullscreen ? 0 : flag);
if(isFullscreen){
cout << "set window to: " << lastWindowX << " " << lastWindowY << endl;
SDL_SetWindowPosition(window, lastWindowX, lastWindowY);
}
}

Looking at one of my projects that has a function to set either windowed, fullscreen or fullscreen desktop I found these two lines:
// Fixes problem when Game::changeResolution is called in fullscreen or fullscreen desktop and then return to windowed.
SDL_SetWindowSize(m_pWindow, m_width, m_height);
SDL_SetWindowPosition(m_pWindow, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED);
With the SDL_SetWindowSize done first, everything works fine. Then I commented out the SDL_SetWindowSize line and ran again. When returning from SDL_WINDOW_FULLSCREEN_DESKTOP, it reset it's position to (0,0).
Although when returning to windowed from SDL_WINDOW_FULLSCREEN, it was placed okay. Try adding that line and see if it fixes the problem for you. Also try adding in SDL_Delay(2000); between calls.

Related

SDL mouse position with multiple sdl windows

With these lines I managed to get the mouse coordinates only inside my sdl window. This code is inside the "draw" function.
SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1", SDL_HINT_OVERRIDE);
SDL_GetMouseState(&mxx, &myy);
//other code
SDL_GL_SwapWindow(window);
Now I draw two windows: there is a way to obtain mouse position only when it is inside the first window? (when the mouse inside the second window consider it as out of border of the first window and coordinates are not updated)
void draw(){
//common part
if (windowId == 0) {
//draw something in the first window
}
else {
//draw other things in the second window
}
SDL_GL_SwapWindow(window);
}
This is my draw function this structure, called in the main like this after creating 2 SDL windows object
window1.draw()
window2.draw()

How to watch any window movements with xlib?

How do I track move event for all the windows?
Like if user moves window "Pluma" my daemon would receive window name and new coordinates.
if(XCheckMaskEvent(display, -1, &event))
{
if(event.type == ConfigureNotify)
{
moved += event.xmotion.x + event.xmotion.y;
//qDebug << moved;
}
}
I tried tracking it like this, but it does not work...
You need t select SubstructureNotify mask on the root window first:
XSelectInput(display, XDefaultRootWindow(display), SubstructureNotifyMask );
This way you are telling X server "I'm interested in root window childrens move/resize/delete/create events"

GLFW camera and mouse control

So basically am learning OpenGL and the GLFW libraries from the tutorial on page: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-6-keyboard-and-mouse/
My problems is with this less lesson showing the control of camera movement with mouse.
Basicaly it makes the application to get "FPS" like camera, with disabled cursor being moved on center of screen with each frame. But the camera gets crazy when we lose focus on the window and then it regains. For example if we click on the window to regain focus away from the middle of view, the camera will be moved by big amount. I tried to fix this issue with adding window focus callback:
void window_focus_callback(GLFWwindow* window, int focused){
if (focused)
{
//center mouse on screen
int width, height;
glfwGetWindowSize(window, &width, &height);
glfwSetCursorPos(window, 1024 / 2, 768 / 2);
windowFocused = true;
}
else
{
windowFocused = false;
}
And in the main application loop:
if(windowFocused) computeMatricesFromInputs();
But for some reason this solution doesnt work.
Is there any way to fix this issue using glfw?
Question is a bit old, but I recently suffered a similar issue. So just sharing, more solutions exist.
I use GLFW_CURSOR_DISABLED. In this mode the mouse position is not (yet) updated when you receive the 'on' focus event, so call to GetCursorPos delivers the previous value. The new cursor position arrives in the MouseMove callback AFTER the 'on' focus event.
I solved it by keeping track of the regain of focus and use this int he OnMouseMove callback to either dispatch a MouseInit (to snap the cursor) or a regular MouseMove.
This way I can ALT+TAB out of my window and return with the cursor somewhere else without nasty jumps/rotations of the camera.
void InputManagerGLFW::Callback_OnMouseMove(
GLFWwindow* window,
double xpos, //
double ypos) //
{
if (!mFocusRegained)
{
mMouseBuffer.Move(xpos, ypos);
}
else
{
mFocusRegained = false;
mMouseBuffer.Init(xpos, ypos);
}
}
void InputManagerGLFW::Callback_OnFocus(
GLFWwindow* window,
int focused)
{
if (focused)
{
// The window gained input focus
// Note: the mouse position is not yet updated
// the new position is provided by the mousemove callback AFTER this callback
Log::Info("focus");
// use flag to indicate the OnMouseMove that we just regained focus,
// so the first mouse move must be handled differently
mFocusRegained = true;
// this will NOT work!!!
// double x,y;
// glfwGetCursorPos(window,&x,&y);
// mMouseBuffer.Init(x,y);
}
else
{
// The window lost input focus
Log::Info("focus lost");
}
}

GLFW non-responsive fullscreen window

I am having some issues with GLFW's window creation. I am wanting to have a program capable of toggling between windowed and fullscreen mode. To do this in GLFW 2.7.8 one must first destroy the active window, then create a new one. I read that version 3.0 has support for multiple windows, but it is still in development.
I have provided my own function to handle keyboard input. Using the initial 400 by 400 window, the program functions as expected; it will enter fullscreen on f or F, will exit when the escape key is pressed, and will complain when anything else is pressed.
However, when fullscreen mode is entered, the window becomes unresponsive with regards to my provided keyboard function. It will continue to run through the loop in main() and will respond to something like the glfwGetKey(GLFW_KEY_ESC) test. Regardless of if I have the mouse cursor enabled or not, the cursor does not appear.
Again, the fullscreen window is created and the KeyboardCallback function returns back into the main loop. I wish to understand why the fullscreen window is not working with my keyboard function, and why it is not displaying properly.
I am not drawing anything to the window, as I am trying to get some experience with various window abstraction libraries specifically. Drawing a simple triangle did nothing to solve he problem, and the fullscreen window remains black.
My code is as follows:
#include <stdio.h>
#include <stdlib.h>
// glfw32 - 2.7.8
#include <GL\glfw.h>
#pragma comment (lib, "GLFW.lib")
#pragma comment (lib, "opengl32.lib")
using namespace std;
// constants and globals
const int WINDOW_WIDTH=400, WINDOW_HEIGHT=400;
static bool fullscreen=false;
// function declarations
void GLFWCALL KeyboardCallback(int key, int action);
void FatalError(const char* msg) {
fprintf(stderr, "ERROR: Failure in \"%s\"\n", msg);
exit(1);
}
int main() {
// ititialize GLFW
glfwInit();
glfwEnable(GLFW_MOUSE_CURSOR);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
// initial window, 400x400 with 32-bit depth buffer in windowed mode
glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0,0,0,0, 32, 0, GLFW_WINDOW);
glfwSetWindowTitle("Simple Title");
glfwSetWindowPos(0, 0);
// set custom keyboard callback
glfwSetKeyCallback(KeyboardCallback);
while (true) { // loop until exit
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers();
// debug
//printf("Looping...\n");
if ( glfwGetKey(GLFW_KEY_ESC) ) {break;}
}
glfwTerminate();
printf("\nHave a nice day\n");
return 0;
}
void GLFWCALL KeyboardCallback(int key, int action) {
//printf("In keyboard function\n");
if (action) { // if key DOWN,
switch(key) { // do something...
case 'f':
case 'F': {
fullscreen = !fullscreen;
printf("Toggle Fullscreen: %s\n", (fullscreen ? "On" : "Off"));
glfwCloseWindow();
if (! glfwOpenWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 0,0,0,0, 32, 0,
fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW)) {
FatalError("toggle fullscreen");
}
glfwSetWindowTitle("New Title");
break;
}
case GLFW_KEY_ESC: {
printf("\nGoodbye cruel world...\n");
glfwTerminate();
exit(0);
}
default: {
printf("Key not implemented: %c\n", key);
break;
}
}
}
printf("Exiting keyboard function\n");
}
I tried James' approach from here but to no effect. Are there GLFW flags I am forgetting to set?
EDIT------- 5/20
I had a thought. Perhaps my callback was being unregistered when the window is destroyed. Turns out that re-registering my function when the new window is created made the window responsive.
While this solves my original problem, I now face a new one. I cannot render to the new window properly. I can insert glClear( GL_COLOR_BUFFER_BIT ); into my main loop, which will successfully set a background colour for the new window. For some reason it does not interact with my arrays and buffers to draw the image.
Code with attempted drawing
EDIT------- 5/21
I converted my code to GLFW 3.0.0. The window management is much cleaner (albeit more complex) and I do not have the rendering issue. Probably because I explicitly have to state the current context to use.
I would still like to solve the rendering issue, both out of curiosity and for if/when I return to 2.7.
Right now the event queue of GLFW is not pumped. You must either set the GLFW_AUTO_POLL_EVENTS option so that glfwSwapBuffers pumps the event queue, or you call glfwPollEvents at the start of a main event loop iteration.

How to update text in a loop?

I'm basically a beginner in C++ but was looking into how to update a string that is in a while loop?
Currently every iteration of the loop it writes the text on top of the previous still its basically a blur of white colour.
This is my loop that im testing with:
while(!quit){
while( SDL_PollEvent( &event ) ){
switch(event.type){
case SDL_QUIT: quit = true; break;
case SDL_MOUSEMOTION: handle_mouse_position();
}
}
SDL_Rect offset;
offset.x = 400;
offset.y = 290;
std::stringstream s;
s << "Mouse xpos: " << mouseX << " Mouse ypos: " << mouseY;
font_surface = TTF_RenderText_Solid(font,s.str().c_str(),font_color);
SDL_BlitSurface(font_surface, NULL, screen, &offset);
//Update the screen
if( SDL_Flip( screen ) == -1 ) {
return 1;
}
}
Is there some way to clear the previous text output and update it each loop so that it will display mouse position clearly?
You are not clearing the screen between redraws, so it just paints over the already painted text (or anything), and it becomes "blur of white" as you say.
For example, try fillrect on the screen every frame.
Extra note: it seems you are not freeing the font_surface --> memory leak.
You can do that redrawing everything each time, or if your background is a solid color, paint a rectangle and draw the text above it.
The second one is more efficient. But if you have a complex scenario it is better to work with layers. First you render the bottom layer, then the second, and so on... By layers I mean, you can have a background() which draws the background and foreground() which, obviously, draws the foreground. So what you will have is something like:
while (main_loop) {
background();
foreground();
}
So you can easily handle more complex scenarios.