Does SDL_SetWindowSize trigger a window event? - c++

In SDL2 when you resize the window by dragging the corners during runtime, a window resized event is triggered and can be used like this:
SDL_Event e;
int width, height;
SDL_PollEvent(&e);
if(e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_RESIZED)
{
width = e.window.data1;
height = e.window.data2;
}
If I resize a window manually like this:
SDL_SetWindowSize(window, myWidth, myHeight);
(documentation)
Will this trigger a window event like above?

Yes, just like SDL_SetWindowFullscreen (). SDL_SetWindowSize () triggers window events. Technically, I think it just resizes the window, which is treated as if the user manually resized it.

Using SDL_WINDOWEVENT_RESIZED, the answer is no. But an SDL_WINDOWEVENT_SIZE_CHANGED event is triggered.

Related

Allegro get current window size

In Allegro, I can set the Window to be resizeable by running
al_set_new_display_flags(ALLEGRO_RESIZABLE);
before
display = al_create_display(800, 600);
however, if I resize the window, how will I know how big the window is that I resize?
use al_get_window_constraints(ALLEGRO_DISPLAY *display,
int *min_w, int *min_h, int *max_w, int *max_h).
Source
If you want to respond dynamically as the window is resized, you should listen for ALLEGRO_EVENT_DISPLAY_RESIZE. Note that you'll have to register your display as a source for your event queue first:
al_register_event_source(event_queue, al_get_display_event_source(display));

Animation issue on X11 window

I'm struggling to get X11 redrawing events right in a cross platform C++ application.
Everything works great on Windows (I just issue some InvalidateRect calls when I need the window to redraw), but on Linux I keep having redrawing stuttering (probably when I send too many redraw events as follows)
event.type = Expose;
event.xexpose.window = window;
XSendEvent(display, window, False, ExposureMask, &event);
the same happens when I resize the window.
This is the code I'm using
void Window::redraw() { // Called by any control which needs redrawing
XEvent event;
memset(&event, 0, sizeof(event));
event.type = Expose;
event.xexpose.display = display;
XSendEvent(display, window, False, ExposureMask, &event);
}
void Window::resize(int width, int height) {
this->Width = width;
this->Height = height;
}
bool Window::wndProc(XEvent *evt) {
switch (evt->type) {
case Expose: {
if (evt->xexpose.count == 0) { // handle last one only
if (Width != Bitmap.width() || Height != Bitmap.height())
Bitmap.resize(Width, Height);
Renderer.drawOnBitmap(Bitmap);
this->paint();
}
return true;
} break;
case ConfigureNotify: {
this->resize(evt->xconfigure.width, evt->xconfigure.height);
redraw();
return true;
} break;
}
}
void Window::paint() {
XImage image;
sk_bzero(&image, sizeof(image));
// .. boilerplate to initialize XImage...
XInitImage(&image);
XPutImage(display, window, fGc, &image,
0, 0,
0, 0,
Width, Height);
}
I tried several approaches to solve this issue including:
Having a 200 ms delay between every redraw event sending (stuttering still happening.. resize still issues a LOT of events)
Having a secondary thread issuing a redraw call every 50ms (this saturates X11's buffer immediately and crashes the whole thing)
Unfortunately I have animated controls which call redraw() anytime they need another redrawing of part of the window (I handle painting regions of the window separately).
How can I solve stuttering during resizing and too many redrawing events while ensuring my animated controls remain smooth?

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");
}
}

How can you efficiently create an allegro 5 title menu?

I'm working on my first game in Allegro 5, I've got the title menu rendering as such, however I want to add clickable text in the menu. How would I make it so that, when you hover over the text you can click it? I'm thinking having a for statement checking the pixels would be very bad for performance, here's what I have so far:
#include <allegro5\allegro.h>
#include <allegro5\allegro_image.h>
#include <allegro5\allegro_primitives.h>
const int width = 1280;
const int height = 720;
int main(void)
{
al_init();
al_init_primitives_addon();
al_init_image_addon();
ALLEGRO_DISPLAY *display = al_create_display(width, height);
ALLEGRO_BITMAP *title = al_load_bitmap("titlemenu.bmp");
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_bitmap(title, 0, 0, 0);
al_flip_display();
al_rest(3.0);
al_destroy_display(display);
return 0;
}
I'm using codeblocks on windows XP SP3
To do it "properly," you'd need to use some sort of GUI library. But you can easily create a clickable section of the screen by hardcoding some rectangle's coordinates.
First you'll need to set up your event handling:
ALLEGRO_EVENT_QUEUE *queue;
queue = al_create_event_queue();
al_install_keyboard();
al_register_event_source(queue, al_get_keyboard_event_source());
Without getting into the specifics of event handling (it's an entire topic of its own), here's the relevant bit:
int selection = 0;
while (!selection)
{
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if (event.type == ALLEGRO_EVENT_KEY_UP)
{
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
selection = MYGAME_QUIT;
}
else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
{
if (event.mouse.x >= MYGAME_MENU_X1 && event.mouse.x < MYGAME_MENU_X2 &&
event.mouse.y >= MYGAME_MENU_Y1 && event.mouse.y < MYGAME_MENU_Y2)
{
selection = MYGAME_OPTION1;
}
}
}
There are many ways to improve upon this example... This is just to get you started.
You should carefully read through the documentation regarding event handling and examine the bundled examples and check out the wiki for more information.
PS: Use forward slashes when using file paths, as they are cross platform:
#include <allegro5/allegro.h>
The above isn't true;
You can add the keyboard to your game and then you have 2 options for collision detection, pixel perfect and bounding box, both covered in the allegro 5 wiki. The tick here to create the best menu IMO is to create a loop and timer for the menu, then list the keyboard, mouse, and timer events seperatley. Next make some if statements so the mouse or keyboard event only triggers when you actually click it, this is needed so you can scroll through a menu with both mouse and keypad, or you could just make it so the mouse wont affect the screen until after you click, but former looks better, at least IMO.