Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Incorrect window mouse coords generated after window resize event.  (Read 7629 times)

0 Members and 1 Guest are viewing this topic.

Thrusty

  • Newbie
  • *
  • Posts: 16
    • View Profile
I'm experiencing a problem with window mouse coords when resizing the window. Everything works fine until the window is re-sized, at which point the coords being generated appear to be based on the original window size, not the new one*. I do not change the standard view when resizing, I just update everything accordingly, including the UI elements within the window.

*Actually what really seems to be happening is that the new window size coords are converted back to the view from the old window size, such that when the Mousemoved event is passed into my UI elements, they get a messed up coord.

I hope I'm explaining this problem well.

Please help. Thanks.


#include <sstream>

#include <TGUI/TGUI.hpp>

#include "../rgm_system/system.h"
#include "../rgm_ui/ui.h"
#include "../rgm_ui/ui_window.h"

void menuDisplaySettingsResetElements(int y, int x, Sys::System& rS)
{
    tgui::Window& window = *rS.win;

    tgui::Label* label1 = window.addLabel();
    label1->setText("Fullscreen Enabled");
    label1->setTextSize(18);
    label1->setTextColor(sf::Color::Black);
    label1->setPosition(x, y+24*1);

    tgui::Checkbox* checkbox1 = window.addCheckbox("display_settings_fullscreen_mode");
    checkbox1->load("TGUI/objects/Checkbox/Black");
    checkbox1->setText("");
    checkbox1->setPosition(x+250-36, y+24*1);
    checkbox1->setSize(24.0, 24.0);

    tgui::Label* label2 = window.addLabel();
    label2->setText("Scale to Fit");
    label2->setTextSize(18);
    label2->setTextColor(sf::Color::Black);
    label2->setPosition(x, y+24*3);

    tgui::Checkbox* checkbox2 = window.addCheckbox("display_settings_scale_to_fit");
    checkbox2->load("TGUI/objects/Checkbox/Black");
    checkbox2->setText("");
    checkbox2->setPosition(x+250-36, y+24*3);
    checkbox2->setSize(24.0, 24.0);

    tgui::Label* label3 = window.addLabel();
    label3->setText("Tile Smoothing");
    label3->setTextSize(18);
    label3->setTextColor(sf::Color::Black);
    label3->setPosition(x, y+24*5);

    tgui::Checkbox* checkbox3 = window.addCheckbox("display_settings_tile_smoothing");
    checkbox3->load("TGUI/objects/Checkbox/Black");
    checkbox3->setText("");
    checkbox3->setPosition(x+250-36, y+24*5);
    checkbox3->setSize(24.0, 24.0);

    tgui::Label* label4 = window.addLabel();
    label4->setText("Framerate Limit");
    label4->setTextSize(18);
    label4->setTextColor(sf::Color::Black);
    label4->setPosition(x, y+24*7);

    tgui::EditBox* editBox1 = window.addEditBox();
    editBox1->load("TGUI/objects/EditBox/Black");
    editBox1->setTextSize(18);
    editBox1->setBorders(6, 4, 6, 4);
    editBox1->setPosition(x+250-112, y+24*7);
    editBox1->setText("60");
    editBox1->setSize(100, 24);

    tgui::Label* label5 = window.addLabel();
    label5->setText("Fullscreen Mode");
    label5->setTextSize(18);
    label5->setTextColor(sf::Color::Black);
    label5->setPosition(x+250, y+24*1);

    tgui::Label* label6 = window.addLabel();
    label6->setText("Window Height");
    label6->setTextSize(18);
    label6->setTextColor(sf::Color::Black);
    label6->setPosition(x, y+24*9);

    tgui::EditBox* editBox2 = window.addEditBox();
    editBox2->load("TGUI/objects/EditBox/Black");
    editBox2->setTextSize(18);
    editBox2->setBorders(6, 4, 6, 4);
    editBox2->setPosition(x+250-12-100, y+24*9);
    editBox2->setText("600");
    editBox2->setSize(100, 24);

    tgui::Label* label7 = window.addLabel();
    label7->setText("Window Width");
    label7->setTextSize(18);
    label7->setTextColor(sf::Color::Black);
    label7->setPosition(x+250, y+24*9);

    tgui::EditBox* editBox3 = window.addEditBox();
    editBox3->load("TGUI/objects/EditBox/Black");
    editBox3->setTextSize(18);
    editBox3->setBorders(6, 4, 6, 4);
    editBox3->setPosition(x+500-12-100, y+24*9);
    editBox3->setText("1024");
    editBox3->setSize(100, 24);



    tgui::Listbox* listbox = window.addListbox();
    listbox->load(125, 144, "TGUI/objects/Scrollbar/Black", 20);
    listbox->setBorders(2, 2, 2, 2);
    listbox->setPosition(x+500-12-125, y+24*1);

    std::vector<sf::VideoMode> modes = sf::VideoMode::getFullscreenModes();

    for (auto it : modes)
    {
        if (it.bitsPerPixel == 32 && it.width >= 854 && it.height >= 480)
        {
            std::stringstream ss;

            ss << it.width << " x " << it.height;

            listbox->addItem(ss.str());
        }
    }

    listbox->changeColors(rS.guiInst.barDDdivideColour,
                          sf::Color::White,
                          rS.guiInst.barHighlightColour,
                          sf::Color::White);



    tgui::Button* button1 = window.addButton();
    button1->load("TGUI/objects/Button/Black");
    button1->setTextSize(18);
    button1->setText("OK");
    button1->setSize(100.0, 24.0);
    button1->setPosition(x, y+24*12);

    tgui::Button* button2 = window.addButton();
    button2->load("TGUI/objects/Button/Black");
    button2->setTextSize(18);
    button2->setText("Cancel");
    button2->setSize(100.0, 24.0);
    button2->setPosition(x+106, y+24*12);
}

void Sys::menuDisplaySettings(System& rS)
{
    sf::Event event;

    Sys::SubWindow w(350, 500, rS);
    w.setPositionAuto();
    w.setTitle("Display Settings");
    w.enableVertDiv();

    menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);

    int windowHeight = 600;
    int windowWidth = 1024;
    int fsHeight = 600;
    int fsWidth = 1024;
    int fullscreen = 0;
    int scaleToFit = 0;
    int smoothTiles = 0;
    int frameRateLimit = 60;

    for ( ; ; )
    {
        int resize = 0;
        int width = 0;
        int height = 0;

        while (rS.win->pollEvent(event))
        {
            rS.win->handleEvent(event);

            if (event.type == sf::Event::Closed) return;

            if (event.type == sf::Event::Resized)
            {
                resize = 1;
                width = event.size.width;
                height = event.size.height;
            }
        }

        if (resize)
        {
            rS.win->removeAllObjects();

            rS.win->create(sf::VideoMode(width, height, 32), "SFML Window");

            rS.winPixelWidth = width;
            rS.winPixelHeight = height;

            w.setPositionAuto();

            menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);
        }

        rS.win->clear();
        rS.displayTiles();
        rS.displayUI();
        w.displayWindow();
        rS.win->drawGUI();
        rS.win->display();
    }
}
« Last Edit: December 01, 2012, 11:50:55 pm by Thrusty »

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Incorrect window mouse coords generated after window resize event.
« Reply #1 on: December 01, 2012, 05:09:02 pm »
1. Wrap code in [ code=cpp ][ /code ] tags.
2. Provide minimal examples, not full code.
3. sf::RenderWindow has convertCoords that takes sf::Vector2i containing pixel coords and returns sf::Vector2f with real coordinates.
Back to C++ gamedev with SFML in May 2023

Thrusty

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Incorrect window mouse coords generated after window resize event.
« Reply #2 on: December 02, 2012, 01:04:06 am »
So I managed to solve the problem with a dodgy hack:

        while (rS.win->pollEvent(event))
        {
            if (event.type == sf::Event::MouseMoved)
            {
                sf::Vector2i position_i = sf::Mouse::getPosition(*rS.win);
                sf::Vector2f position_f = rS.win->convertCoords(position_i);

                sf::Event etmp;
                etmp.type = sf::Event::MouseMoved;
                etmp.mouseMove.x = position_f.x;
                etmp.mouseMove.y = position_f.y;

                rS.win->handleEvent(etmp);
            }

            if (event.type == sf::Event::MouseButtonPressed || event.type == sf::Event::MouseButtonReleased)
            {
                rS.win->handleEvent(event);
            }

            if (event.type == sf::Event::Closed) return;

            if (event.type == sf::Event::Resized)
            {
                resize = 1;
                width = event.size.width;
                height = event.size.height;
            }
        }
 

I wish there were a way to do this without creating my own event instantiation and passing it into the UI elements, though.

texus

  • Sr. Member
  • ****
  • Posts: 499
    • View Profile
    • TGUI
    • Email
Re: Incorrect window mouse coords generated after window resize event.
« Reply #3 on: December 02, 2012, 01:13:42 pm »
If you think there is a bug in tgui then you should make a minimal code, because I can't reproduce the problems you describe. Providing the full code will also help, but then it will take a bit longer to find the problem.

I am surprised that the last code works because you aren't sending the resized events to tgui. Also only converting the coords on mouse move and not on mouse press looks a bit strange to me.
In fact, convertCoords is called inside the handleEvent function (tgui v0.4 still does it differently but with the same effect).

In your first code you are calling window.create when you receive a resized event.
Doesn't this get you into an infinite loop because a resize event is triggered when creating the window?
At least it does on my linux machine.

If you just want the objects to remain at the same size after resizing the window, then you should just change the view, not recreate the whole window.
TGUI: C++ SFML GUI

Thrusty

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Incorrect window mouse coords generated after window resize event.
« Reply #4 on: December 02, 2012, 03:57:22 pm »
This is the code I had before using the hack:

    for ( ; ; )
    {
        int resize = 0;
        int width = 0;
        int height = 0;

        while (rS.win->pollEvent(event))
        {
            rS.win->handleEvent(event);

            if (event.type == sf::Event::Closed) return;

            if (event.type == sf::Event::Resized)
            {
                resize = 1;
                width = event.size.width;
                height = event.size.height;
            }
        }

        if (resize)
        {
            rS.win->removeAllObjects();

            rS.win->create(sf::VideoMode(width, height, 32), "SFML Window");

            rS.winPixelWidth = width;
            rS.winPixelHeight = height;

            w.setPositionAuto();

            menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);
        }

        rS.win->clear();
        rS.displayTiles();
        rS.displayUI();
        w.displayWindow();
        rS.win->drawGUI();
        rS.win->display();
    }

The event was passed into tgui regardless of what type it was. Why were you getting an infinite lop on linux, anyway? That doesn't happen on my system. We need to investigate this.

tgui must keep a record of the last mouse position after a mousemove event, since I didn't need to convert the button press events, only the mousemove events.
« Last Edit: December 02, 2012, 03:59:17 pm by Thrusty »

texus

  • Sr. Member
  • ****
  • Posts: 499
    • View Profile
    • TGUI
    • Email
Re: Incorrect window mouse coords generated after window resize event.
« Reply #5 on: December 02, 2012, 04:07:21 pm »
It's not really an infinite loop, because the program keeps continuing, but it will constantly send Resized events.
Your code is almost the same as the code below.

Even with your code, if you would add the cout line, you should see that the line keeps printing.

sf::Event event;
while (window.pollEvent(event))
{
    window.handleEvent(event);

    if (event.type == sf::Event::Closed) return 0;

    if (event.type == sf::Event::Resized)
    {
        window.create(sf::VideoMode(event.size.width, height = event.size.height, 32), "SFML Window");
        std::cout << "Resized" << std::endl;
    }
}
TGUI: C++ SFML GUI

Thrusty

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Incorrect window mouse coords generated after window resize event.
« Reply #6 on: December 02, 2012, 04:24:14 pm »
So here's my new updated code:

The line with the "//" at the beginning is the line that causes the coordinate problem when I reactivate that bit of code. Why would not telling tgui about the re-size event, solve the problem? Well at least appear to.

void Sys::menuDisplaySettings(System& rS)
{
    sf::Event event;
    Sys::SubWindow w(350, 500, rS);
    w.setPositionAuto();
    w.setTitle("Display Settings");
    w.enableVertDiv();
    menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);

    for (;;)
    {
        int resize = 0;
        int width = 0;
        int height = 0;

        while (rS.win->pollEvent(event))
        {
            if (event.type == sf::Event::MouseMoved)
            {
                sf::Vector2i position_i = sf::Mouse::getPosition(*rS.win);
                sf::Vector2f position_f = rS.win->convertCoords(position_i);

                sf::Event etmp;
                etmp.type = sf::Event::MouseMoved;
                etmp.mouseMove.x = position_f.x;
                etmp.mouseMove.y = position_f.y;

                rS.win->handleEvent(etmp);
            }

            else if (event.type == sf::Event::MouseButtonPressed || event.type == sf::Event::MouseButtonReleased)
            {
                rS.win->handleEvent(event);
            }

            else if (event.type == sf::Event::Closed) return;

            else if (event.type == sf::Event::Resized)
            {
                if (event.size.width != width && event.size.height != height)
                {
                    resize = 1;
                    width = event.size.width;
                    height = event.size.height;

                    // rS.win->handleEvent(event);
                }
            }
        }

        if (resize)
        {
            rS.win->removeAllObjects();
            rS.win->create(sf::VideoMode(width, height, 32), "SFML Window");
            rS.winPixelWidth = width;
            rS.winPixelHeight = height;
            w.setPositionAuto();
            menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);
        }

        rS.win->clear();
        rS.displayTiles();
        rS.displayUI();
        w.displayWindow();
        rS.win->drawGUI();
        rS.win->display();
    }
}
« Last Edit: December 02, 2012, 04:28:56 pm by Thrusty »

texus

  • Sr. Member
  • ****
  • Posts: 499
    • View Profile
    • TGUI
    • Email
Re: Incorrect window mouse coords generated after window resize event.
« Reply #7 on: December 02, 2012, 04:48:21 pm »
The window scale is calculated and stored when a resize event is received.
When not telling tgui the scale will always be (1, 1).

If you would pass the resize then tgui will think the window changed its size and the images are now stretched.
Right after that you recreate the window so the window has the correct size and isn't stretched. But tgui doesn't know about it. You could try passing a Resized event to tgui after recreating the window, maybe that helps.

The above could be a reason, but it is not supposed to happen.
On linux a resize event is triggered when recreating the window, so the internal scale should be reset.
Apparently this doesn't happen on windows.

But I think you should focus on the window first instead of on the mouse events.
Not only does the window flicker the whole time (because its keeps destroying and recreating it), but it also won't react to any events. This will probably happen on more linux systems than just mine.

Is there any reason why you can't just change the view?
Can't you change
rS.win->create(sf::VideoMode(width, height, 32), "SFML Window");
to
rS.win->setView(sf::View(sf::FloatRect(0, 0, width, height)));
?

Also could you try adding the cout line there, to see if the resize events keep coming on windows too?
TGUI: C++ SFML GUI

Thrusty

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Incorrect window mouse coords generated after window resize event.
« Reply #8 on: December 02, 2012, 05:52:44 pm »
Re-size events are only generated while the user is holding down the mouse button and dragging the window to re-size it. Once he releases the button, cout no longer generates any re-size messages.

            else if (event.type == sf::Event::Resized)
            {
                ++counter;
                std::cout << "Resizes: " << counter << "\n";
                if (event.size.width != width && event.size.height != height)
                {
                    resize = 1;
                    width = event.size.width;
                    height = event.size.height;

                    // rS.win->handleEvent(event);
                }
            }

Does the resize event really need to be given to tgui *after* the view has been changed?

texus

  • Sr. Member
  • ****
  • Posts: 499
    • View Profile
    • TGUI
    • Email
Re: Incorrect window mouse coords generated after window resize event.
« Reply #9 on: December 02, 2012, 06:09:44 pm »
Quote
Does the resize event really need to be given to tgui *after* the view has been changed?
The resized event should only be passed to tgui when the window changes its size. You can change the view as much as you want, it shouldn't make a difference.

You could add the following lines after the create call. That should make sure that the internal scaling is always 1 (as long as the view has the same size as the window).
sf::Event event;
event.type = sf::Event::Resized;
event.size.width = width;
event.size.height = height;
rS.Win->handleEvent(event);

Still, the code won't work on linux (and I can't test it) because here the resize events just keep coming.
TGUI: C++ SFML GUI

Thrusty

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Incorrect window mouse coords generated after window resize event.
« Reply #10 on: December 02, 2012, 06:14:12 pm »
Very well. I'm now sending the re-size event after recreating the window. I don't seem to need a view change either. Though I'll test that out on linux, at some point.

void Sys::menuDisplaySettings(System& rS)
{
    sf::Event event;
    Sys::SubWindow w(350, 500, rS);
    w.setPositionAuto();
    w.setTitle("Display Settings");
    w.enableVertDiv();
    menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);
    int counter = 0;

    for (;;)
    {
        int resize = 0;
        int width = 0;
        int height = 0;

        while (rS.win->pollEvent(event))
        {
            if (event.type == sf::Event::MouseMoved ||
                event.type == sf::Event::MouseButtonPressed ||
                event.type == sf::Event::MouseButtonReleased)
            {
                rS.win->handleEvent(event);
            }

            else if (event.type == sf::Event::Closed) return;

            else if (event.type == sf::Event::Resized)
            {
                if (event.size.width != width || event.size.height != height)
                {
                    resize = 1;
                    width = event.size.width;
                    height = event.size.height;
                }
            }
        }

        if (resize)
        {
            rS.win->removeAllObjects();
            rS.win->create(sf::VideoMode(width, height, 32), "SFML Window");
            //rS.win->setView(sf::View(sf::FloatRect(0, 0, width, height)));

            rS.win->handleEvent(event);

            rS.winPixelWidth = width;
            rS.winPixelHeight = height;
            w.setPositionAuto();
            menuDisplaySettingsResetElements(w.yBegin+30, w.xBegin+6, rS);
        }

        rS.win->clear();
        rS.displayTiles();
        rS.displayUI();
        w.displayWindow();
        rS.win->drawGUI();
        rS.win->display();
    }
}

For the linux release, I'll have to disallow manual window resizing, and let the user specify a window size in the window settings menu.

texus

  • Sr. Member
  • ****
  • Posts: 499
    • View Profile
    • TGUI
    • Email
Re: Incorrect window mouse coords generated after window resize event.
« Reply #11 on: December 02, 2012, 06:42:07 pm »
I just noticed something. When comparing the code from v0.4 and v0.5, I saw that the code has changed more than I thought. The resized event is no longer used inside tgui v0.5, which means that you probably don't even have to do anything extra after recreating the window.

So this bug should already be solved in the latest version. I just can't test it to be sure because it seems like it only affected windows. I guess I should really get that virtualbox running again.

But as long as you stay with v0.4 you will just have to pass the resized event manually after recreating the window.
TGUI: C++ SFML GUI

 

anything