New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Views not scaling correctly on resize on Mac OS X #474

Closed
Voidious opened this Issue Oct 6, 2013 · 15 comments

Comments

Projects
None yet
3 participants
@Voidious

Voidious commented Oct 6, 2013

It looks like c0f3587 solves one problem but creates (or exposes) another for me.

Before that, I see what Manuel was seeing in #468 - many frames of resizing, sometimes ending up at the right size / sometimes not, but the aspect ratio remains correct. My onResize code is similar to his. (I don't see any problem on Linux/GTK (Ubuntu), in 2.1 or at head - all my resizing still works fine.)

With c0f3587, the window resizes immediately/correctly on OS X, but the views don't get updated correctly. I have content spilling over the sides or the top and it's the wrong aspect ratio. One of the dimensions is always scaled correctly, the other incorrectly, as though the height XOR width were stale in the viewport calculations. (No idea if that's plausible, just trying to be clear what's going on.) When I make tiny resizes, I can get the views to scale correctly (or too close to tell).

I just spent some time troubleshooting it and trying to make sure I'm not doing something wrong. One of my viewports is set as:

    stageView_.setViewport(sf::FloatRect(dockViewportWidth, 0.f,
                                        stageViewportWidth, 1.f));

It should be impossible for that to overflow vertically, right? (Dock is a fixed width column on the left, stage takes up the rest of the width and 100% height.)

Also worth noting that the resizing was OK for me in SFML 2.0 and the RC's before it. Not sure what commit(s) between 2.0 and 2.1 changed things.

I'm on 10.8 on a mid-2009 MacBook Pro. Happy to do more investigations or post some code. This is where I update the views: https://github.com/Voidious/BerryBots/blob/master/gfxmanager.cpp#L466

And lastly, since this is my first post here, I of course have to add that SFML is amazing and many thanks to all of you for your hard work. :-)

@ghost ghost assigned mantognini Oct 7, 2013

@mantognini

This comment has been minimized.

Show comment
Hide comment
@mantognini

mantognini Oct 7, 2013

Member

Can you produce a SSCCE? That would help a lot for testing / debugging. Thanks.

Member

mantognini commented Oct 7, 2013

Can you produce a SSCCE? That would help a lot for testing / debugging. Thanks.

@Voidious

This comment has been minimized.

Show comment
Hide comment
@Voidious

Voidious Oct 8, 2013

Sure thing. Here's the code:

#include <algorithm>
#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>

int VIEW_WIDTH = 500;
int VIEW_HEIGHT = 500;

int main(int argc, char *argv[]) {
  sf::RenderWindow *window;

  window = new sf::RenderWindow(sf::VideoMode(VIEW_WIDTH, VIEW_HEIGHT),
      "SFML #474", sf::Style::Default, sf::ContextSettings(0, 0, 16, 2, 0));
  window->setVerticalSyncEnabled(true);

  // Apparently these lines are redundant, behaves the same either way.
//  sf::View view;
//  view.reset(sf::FloatRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT));
//  view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
//  window->setView(view);

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(VIEW_WIDTH - 16, VIEW_HEIGHT - 16));
  rect.setPosition(8, 8);
  rect.setFillColor(sf::Color::Black);
  rect.setOutlineThickness(4);
  rect.setOutlineColor(sf::Color::White);

  while (true) {
    window->clear();
    window->draw(rect);
    window->display();

    sf::Event event;
    while (window->pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window->close();
        exit(0);
      }
      if (event.type == sf::Event::Resized) {
        unsigned int oldWindowWidth = window->getSize().x;
        unsigned int oldWindowHeight = window->getSize().y;
        double widthScale = ((double) oldWindowWidth) / VIEW_WIDTH;
        double heightScale = ((double) oldWindowHeight) / VIEW_HEIGHT;
        double scale = std::min(widthScale, heightScale);

        unsigned int windowWidth = (int) (scale * VIEW_WIDTH + 0.5);
        unsigned int windowHeight = (int) (scale * VIEW_HEIGHT + 0.5);
        window->setSize(sf::Vector2u(windowWidth, windowHeight));
      }
    }
  }

  return 0;
}

On my Mac, that resizes correctly in SFML 2.0. In 2.1 or at the commit just before c0f3587, it wigs out and appears to get stuck in a re-resizing loop. At c0f3587 and at head, it resizes the window itself correctly, but with one of the dimensions slightly overspilling.

Guessing you know how to compile an SFML app :-), but for completeness, here's my build process. Sorry it's kind of convoluted, I wanted to do this from command line and forgot those built-in dylib paths on Mac are kind of a pain.

g++ sfml474.cpp -I/home/yada/SFML-master/include \
-L./sfml-lib -lsfml-graphics -lsfml-window -lsfml-system -o sfml474
./sfml474

After copying SFML/build/lib to ./sfml-lib:

cd ~/SFML-master/build
cp -a lib ~/sfmlbug/sfml-lib

And fixing the dylib paths.

#!/bin/bash

SFML_LIBNAMES="libsfml-graphics libsfml-system libsfml-window"

for TARGET in ${SFML_LIBNAMES} ; do
  LIBFILE=sfml-lib/${TARGET}.2.1.dylib
  TARGETID=`otool -DX ${LIBFILE}`
  install_name_tool -id ${LIBFILE} ${LIBFILE}
  for TARGET2 in ${SFML_LIBNAMES} ; do
    LIBFILE2=sfml-lib/${TARGET2}.2.1.dylib
    install_name_tool -change ${TARGETID} ${LIBFILE} ${LIBFILE2}
  done
done

Voidious commented Oct 8, 2013

Sure thing. Here's the code:

#include <algorithm>
#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>

int VIEW_WIDTH = 500;
int VIEW_HEIGHT = 500;

int main(int argc, char *argv[]) {
  sf::RenderWindow *window;

  window = new sf::RenderWindow(sf::VideoMode(VIEW_WIDTH, VIEW_HEIGHT),
      "SFML #474", sf::Style::Default, sf::ContextSettings(0, 0, 16, 2, 0));
  window->setVerticalSyncEnabled(true);

  // Apparently these lines are redundant, behaves the same either way.
//  sf::View view;
//  view.reset(sf::FloatRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT));
//  view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
//  window->setView(view);

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(VIEW_WIDTH - 16, VIEW_HEIGHT - 16));
  rect.setPosition(8, 8);
  rect.setFillColor(sf::Color::Black);
  rect.setOutlineThickness(4);
  rect.setOutlineColor(sf::Color::White);

  while (true) {
    window->clear();
    window->draw(rect);
    window->display();

    sf::Event event;
    while (window->pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window->close();
        exit(0);
      }
      if (event.type == sf::Event::Resized) {
        unsigned int oldWindowWidth = window->getSize().x;
        unsigned int oldWindowHeight = window->getSize().y;
        double widthScale = ((double) oldWindowWidth) / VIEW_WIDTH;
        double heightScale = ((double) oldWindowHeight) / VIEW_HEIGHT;
        double scale = std::min(widthScale, heightScale);

        unsigned int windowWidth = (int) (scale * VIEW_WIDTH + 0.5);
        unsigned int windowHeight = (int) (scale * VIEW_HEIGHT + 0.5);
        window->setSize(sf::Vector2u(windowWidth, windowHeight));
      }
    }
  }

  return 0;
}

On my Mac, that resizes correctly in SFML 2.0. In 2.1 or at the commit just before c0f3587, it wigs out and appears to get stuck in a re-resizing loop. At c0f3587 and at head, it resizes the window itself correctly, but with one of the dimensions slightly overspilling.

Guessing you know how to compile an SFML app :-), but for completeness, here's my build process. Sorry it's kind of convoluted, I wanted to do this from command line and forgot those built-in dylib paths on Mac are kind of a pain.

g++ sfml474.cpp -I/home/yada/SFML-master/include \
-L./sfml-lib -lsfml-graphics -lsfml-window -lsfml-system -o sfml474
./sfml474

After copying SFML/build/lib to ./sfml-lib:

cd ~/SFML-master/build
cp -a lib ~/sfmlbug/sfml-lib

And fixing the dylib paths.

#!/bin/bash

SFML_LIBNAMES="libsfml-graphics libsfml-system libsfml-window"

for TARGET in ${SFML_LIBNAMES} ; do
  LIBFILE=sfml-lib/${TARGET}.2.1.dylib
  TARGETID=`otool -DX ${LIBFILE}`
  install_name_tool -id ${LIBFILE} ${LIBFILE}
  for TARGET2 in ${SFML_LIBNAMES} ; do
    LIBFILE2=sfml-lib/${TARGET2}.2.1.dylib
    install_name_tool -change ${TARGETID} ${LIBFILE} ${LIBFILE2}
  done
done
@mantognini

This comment has been minimized.

Show comment
Hide comment
@mantognini

mantognini Oct 8, 2013

Member

Thanks @Voidious. I've digged into it and I don't think it's directly related to #468. Prior to the #468's fix, the code above create an infinite loop. It simply didn't work at all.

Here, the problem is that the window's size cached in sf::Window is not correctly updated when sf::Window::setSize() is called.

Below is a code that will print 500 instead of 499. Tested on Mac and Linux. I guess Windows is also concerned by this issue.

int main() {
    sf::Window window(sf::VideoMode(500, 500), "setsize");
    window.setSize(sf::Vector2u(499, 499));
    std::cout << window.getSize().y << std::endl;
    return 0;
}

The thing is, sf::Window cache is not updated immediately – and might not be if the implementation doesn't fire a resize event (e.g. Mac).

@LaurentGomila I need your help to define:

  1. should sf::Window::setSize update the size cache?
  2. should sf::Window::setSize implementation fire a resize event?

For 1., the following patch fix (quick copy and past of filterEvent) this issue #474 too (or, at least, Voidious' code) and the size printed in the code above would be 499 as expected. (Disclaimer: not tested on Linux/Windows)

 void Window::setSize(const Vector2u size)
 {
-    if (m_impl)
+    if (m_impl) {
         m_impl->setSize(size);
+
+        // Cache the new size
+        m_size.x = size.x;
+        m_size.y = size.y;
+
+        // Notify the derived class
+        onResize();
+    }
 }

For 2., the best way I've found, without introducing an infinite loop in the user code, is this: in the Mac impl I can check if the size was different than before and fire an event only then. But since it won't fire an event every time it's not extremely consistent. Do we care?

The event could also be fired directly from sf::Window::setSize.

Member

mantognini commented Oct 8, 2013

Thanks @Voidious. I've digged into it and I don't think it's directly related to #468. Prior to the #468's fix, the code above create an infinite loop. It simply didn't work at all.

Here, the problem is that the window's size cached in sf::Window is not correctly updated when sf::Window::setSize() is called.

Below is a code that will print 500 instead of 499. Tested on Mac and Linux. I guess Windows is also concerned by this issue.

int main() {
    sf::Window window(sf::VideoMode(500, 500), "setsize");
    window.setSize(sf::Vector2u(499, 499));
    std::cout << window.getSize().y << std::endl;
    return 0;
}

The thing is, sf::Window cache is not updated immediately – and might not be if the implementation doesn't fire a resize event (e.g. Mac).

@LaurentGomila I need your help to define:

  1. should sf::Window::setSize update the size cache?
  2. should sf::Window::setSize implementation fire a resize event?

For 1., the following patch fix (quick copy and past of filterEvent) this issue #474 too (or, at least, Voidious' code) and the size printed in the code above would be 499 as expected. (Disclaimer: not tested on Linux/Windows)

 void Window::setSize(const Vector2u size)
 {
-    if (m_impl)
+    if (m_impl) {
         m_impl->setSize(size);
+
+        // Cache the new size
+        m_size.x = size.x;
+        m_size.y = size.y;
+
+        // Notify the derived class
+        onResize();
+    }
 }

For 2., the best way I've found, without introducing an infinite loop in the user code, is this: in the Mac impl I can check if the size was different than before and fire an event only then. But since it won't fire an event every time it's not extremely consistent. Do we care?

The event could also be fired directly from sf::Window::setSize.

@LaurentGomila

This comment has been minimized.

Show comment
Hide comment
@LaurentGomila

LaurentGomila Oct 8, 2013

Member

should sf::Window::setSize update the size cache?

It's clearly not consistent to wait for the OS generated event (when there's one), so yes.

should sf::Window::setSize implementation fire a resize event?

On Windows it does. Not tested yet on Linux.

Member

LaurentGomila commented Oct 8, 2013

should sf::Window::setSize update the size cache?

It's clearly not consistent to wait for the OS generated event (when there's one), so yes.

should sf::Window::setSize implementation fire a resize event?

On Windows it does. Not tested yet on Linux.

@Voidious

This comment has been minimized.

Show comment
Hide comment
@Voidious

Voidious Oct 9, 2013

Great, thanks for the quick turnaround! This fixes the resize scaling on my machine, with the test program above and my actual app.

Unfortunately I still found a quirk with it, or at least a behavioral difference vs 2.0. If you set the height and width to a size that's too large for your screen, you will get a window of a size capped by your screen dimensions, most likely in the wrong aspect ratio. I guess this doesn't trigger a resize event. Confirmed in SFML 2.0 the window resizes right away to the right aspect ratio.

Should I open another issue?

Or do I need to deal with this myself now (e.g., manually resize on first frame)?

Here's the slightly tweaked sample program I used. Had to enable the view stuff, and of course bigger sizes. (Not sure if the overspilling content when I didn't set the view is also an issue... I'm never not using views in my app.)

#include <algorithm>
#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>

int VIEW_WIDTH = 1500;
int VIEW_HEIGHT = 1500;

int main(int argc, char *argv[]) {
  sf::RenderWindow *window;

  window = new sf::RenderWindow(sf::VideoMode(VIEW_WIDTH, VIEW_HEIGHT),
      "SFML #474", sf::Style::Default, sf::ContextSettings(0, 0, 16, 2, 0));
  window->setVerticalSyncEnabled(true);

  sf::View view;
  view.reset(sf::FloatRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT));
  view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
  window->setView(view);

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(VIEW_WIDTH - 40, VIEW_HEIGHT - 40));
  rect.setPosition(20, 20);
  rect.setFillColor(sf::Color::Black);
  rect.setOutlineThickness(4);
  rect.setOutlineColor(sf::Color::White);

  while (true) {
    window->clear();
    window->draw(rect);
    window->display();

    sf::Event event;
    while (window->pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window->close();
        exit(0);
      }
      if (event.type == sf::Event::Resized) {
        unsigned int oldWindowWidth = window->getSize().x;
        unsigned int oldWindowHeight = window->getSize().y;
        double widthScale = ((double) oldWindowWidth) / VIEW_WIDTH;
        double heightScale = ((double) oldWindowHeight) / VIEW_HEIGHT;
        double scale = std::min(widthScale, heightScale);

        unsigned int windowWidth = (int) (scale * VIEW_WIDTH + 0.5);
        unsigned int windowHeight = (int) (scale * VIEW_HEIGHT + 0.5);
        window->setSize(sf::Vector2u(windowWidth, windowHeight));
      }
    }
  }

  return 0;
}

Voidious commented Oct 9, 2013

Great, thanks for the quick turnaround! This fixes the resize scaling on my machine, with the test program above and my actual app.

Unfortunately I still found a quirk with it, or at least a behavioral difference vs 2.0. If you set the height and width to a size that's too large for your screen, you will get a window of a size capped by your screen dimensions, most likely in the wrong aspect ratio. I guess this doesn't trigger a resize event. Confirmed in SFML 2.0 the window resizes right away to the right aspect ratio.

Should I open another issue?

Or do I need to deal with this myself now (e.g., manually resize on first frame)?

Here's the slightly tweaked sample program I used. Had to enable the view stuff, and of course bigger sizes. (Not sure if the overspilling content when I didn't set the view is also an issue... I'm never not using views in my app.)

#include <algorithm>
#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>

int VIEW_WIDTH = 1500;
int VIEW_HEIGHT = 1500;

int main(int argc, char *argv[]) {
  sf::RenderWindow *window;

  window = new sf::RenderWindow(sf::VideoMode(VIEW_WIDTH, VIEW_HEIGHT),
      "SFML #474", sf::Style::Default, sf::ContextSettings(0, 0, 16, 2, 0));
  window->setVerticalSyncEnabled(true);

  sf::View view;
  view.reset(sf::FloatRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT));
  view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
  window->setView(view);

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(VIEW_WIDTH - 40, VIEW_HEIGHT - 40));
  rect.setPosition(20, 20);
  rect.setFillColor(sf::Color::Black);
  rect.setOutlineThickness(4);
  rect.setOutlineColor(sf::Color::White);

  while (true) {
    window->clear();
    window->draw(rect);
    window->display();

    sf::Event event;
    while (window->pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window->close();
        exit(0);
      }
      if (event.type == sf::Event::Resized) {
        unsigned int oldWindowWidth = window->getSize().x;
        unsigned int oldWindowHeight = window->getSize().y;
        double widthScale = ((double) oldWindowWidth) / VIEW_WIDTH;
        double heightScale = ((double) oldWindowHeight) / VIEW_HEIGHT;
        double scale = std::min(widthScale, heightScale);

        unsigned int windowWidth = (int) (scale * VIEW_WIDTH + 0.5);
        unsigned int windowHeight = (int) (scale * VIEW_HEIGHT + 0.5);
        window->setSize(sf::Vector2u(windowWidth, windowHeight));
      }
    }
  }

  return 0;
}
@Voidious

This comment has been minimized.

Show comment
Hide comment
@Voidious

Voidious Oct 9, 2013

Ok, manually resizing isn't a workaround because window->getSize() is returning the size of the window I requested, not the one I have. So I guess there's definitely still a problem here.

Voidious commented Oct 9, 2013

Ok, manually resizing isn't a workaround because window->getSize() is returning the size of the window I requested, not the one I have. So I guess there's definitely still a problem here.

@mantognini

This comment has been minimized.

Show comment
Hide comment
@mantognini

mantognini Oct 9, 2013

Member

Ok, so there are two ways to set a window's size: a) by creating the window, b) with setSize().

The following code will print 1002 on my machine. So a) is fine. (NB: No event is fired on Mac).

int main()
{
    sf::Window win{{1500, 1500}, "#474"};
    std::cout << win.getSize().y << std::endl;
    return 0;
}

Regarding b), the issue is related to the above one. A fix could be something like:

 void Window::setSize(const Vector2u& size)
 {
     if (m_impl)
     {
         m_impl->setSize(size);

         // Cache the new size
-        m_size.x = size.x;
-        m_size.y = size.y;
+        m_size = m_impl->getSize();

         // Notify the derived class
         onResize();
     }
 }

This will make sure the window render everything (but might be distorted).

However, the user won't receive a resize event and, unless checking getSize(), won't know the window is distorted.

If I send a resize event in the Mac impl, then codes like the following one end up in an infinite loop.

int main()
{
    auto desktop = sf::VideoMode::getDesktopMode();
    sf::RenderWindow window{desktop, "#474"};
    window.setSize({desktop.width, desktop.height}); // <- start infinite loop
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::Resized)
                window.setSize({desktop.width, desktop.height}); // with that
        }
        window.clear();
        window.display();
    }
}

I'm asking myself if it's up to SFML to prevent such situations (and therefore not firing a resize event from setSize() and its implementation) or if the user has to be aware of them and make sure they don't happen...

What happen on Windows with this last code?

Member

mantognini commented Oct 9, 2013

Ok, so there are two ways to set a window's size: a) by creating the window, b) with setSize().

The following code will print 1002 on my machine. So a) is fine. (NB: No event is fired on Mac).

int main()
{
    sf::Window win{{1500, 1500}, "#474"};
    std::cout << win.getSize().y << std::endl;
    return 0;
}

Regarding b), the issue is related to the above one. A fix could be something like:

 void Window::setSize(const Vector2u& size)
 {
     if (m_impl)
     {
         m_impl->setSize(size);

         // Cache the new size
-        m_size.x = size.x;
-        m_size.y = size.y;
+        m_size = m_impl->getSize();

         // Notify the derived class
         onResize();
     }
 }

This will make sure the window render everything (but might be distorted).

However, the user won't receive a resize event and, unless checking getSize(), won't know the window is distorted.

If I send a resize event in the Mac impl, then codes like the following one end up in an infinite loop.

int main()
{
    auto desktop = sf::VideoMode::getDesktopMode();
    sf::RenderWindow window{desktop, "#474"};
    window.setSize({desktop.width, desktop.height}); // <- start infinite loop
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::Resized)
                window.setSize({desktop.width, desktop.height}); // with that
        }
        window.clear();
        window.display();
    }
}

I'm asking myself if it's up to SFML to prevent such situations (and therefore not firing a resize event from setSize() and its implementation) or if the user has to be aware of them and make sure they don't happen...

What happen on Windows with this last code?

@LaurentGomila

This comment has been minimized.

Show comment
Hide comment
@LaurentGomila

LaurentGomila Oct 9, 2013

Member

Can't you force the window to be created with the requested size? That's what I do on Windows to avoid problems, and that would be the easiest solution here too.

Member

LaurentGomila commented Oct 9, 2013

Can't you force the window to be created with the requested size? That's what I do on Windows to avoid problems, and that would be the easiest solution here too.

@mantognini

This comment has been minimized.

Show comment
Hide comment
@mantognini

mantognini Oct 9, 2013

Member

Indeed there is a way. And thus no need of

-        m_size.x = size.x;
-        m_size.y = size.y;
+        m_size = m_impl->getSize();
Member

mantognini commented Oct 9, 2013

Indeed there is a way. And thus no need of

-        m_size.x = size.x;
-        m_size.y = size.y;
+        m_size = m_impl->getSize();
@LaurentGomila

This comment has been minimized.

Show comment
Hide comment
@LaurentGomila

LaurentGomila Oct 9, 2013

Member

Great :)

So is everything ok now?

Member

LaurentGomila commented Oct 9, 2013

Great :)

So is everything ok now?

@mantognini

This comment has been minimized.

Show comment
Hide comment
@mantognini

mantognini Oct 9, 2013

Member

As far as I know, yes. :-)

@Voidious can you confirm it?

Member

mantognini commented Oct 9, 2013

As far as I know, yes. :-)

@Voidious can you confirm it?

@Voidious

This comment has been minimized.

Show comment
Hide comment
@Voidious

Voidious Oct 9, 2013

Not quite... :-)

When I create a window too big for the screen, manually resizing works. That probably already worked and I was wrong above - my apologies.

If I create a smaller window, then setSize() it too big for the screen, it gives me the requested width but still caps the height, and getSize().y is wrong - returns the size I requested, not the capped window height. So I can't detect this and manually resize to fix the aspect ratio.

#include <iostream>
#include <algorithm>
#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>

int VIEW_WIDTH = 1500;
int VIEW_HEIGHT = 1500;

int main(int argc, char *argv[]) {
  sf::RenderWindow *window;

  window = new sf::RenderWindow(sf::VideoMode(50, 50),
      "SFML #474", sf::Style::Default, sf::ContextSettings(0, 0, 16, 2, 0));
  window->setSize(sf::Vector2u(VIEW_WIDTH, VIEW_HEIGHT));
  window->setVerticalSyncEnabled(true);

  sf::View view;
  view.reset(sf::FloatRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT));
  view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
  window->setView(view);

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(VIEW_WIDTH - 40, VIEW_HEIGHT - 40));
  rect.setPosition(20, 20);
  rect.setFillColor(sf::Color::Black);
  rect.setOutlineThickness(4);
  rect.setOutlineColor(sf::Color::White);

  std::cout << window->getSize().x << ", " << window->getSize().y << std::endl;

  while (true) {
    std::cout << window->getSize().x << ", " << window->getSize().y << std::endl;
    window->clear();
    window->draw(rect);
    window->display();

    sf::Event event;
    while (window->pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window->close();
        exit(0);
      }
      if (event.type == sf::Event::Resized) {
        unsigned int oldWindowWidth = window->getSize().x;
        unsigned int oldWindowHeight = window->getSize().y;
        double widthScale = ((double) oldWindowWidth) / VIEW_WIDTH;
        double heightScale = ((double) oldWindowHeight) / VIEW_HEIGHT;
        double scale = std::min(widthScale, heightScale);

        unsigned int windowWidth = (int) (scale * VIEW_WIDTH + 0.5);
        unsigned int windowHeight = (int) (scale * VIEW_HEIGHT + 0.5);
        window->setSize(sf::Vector2u(windowWidth, windowHeight));
      }
    }
  }

  return 0;
}

Giving me the size I asked for seems like the right behavior, but it will leave me needing to figure out the dock height to emulate what OS X was doing for me before.

Voidious commented Oct 9, 2013

Not quite... :-)

When I create a window too big for the screen, manually resizing works. That probably already worked and I was wrong above - my apologies.

If I create a smaller window, then setSize() it too big for the screen, it gives me the requested width but still caps the height, and getSize().y is wrong - returns the size I requested, not the capped window height. So I can't detect this and manually resize to fix the aspect ratio.

#include <iostream>
#include <algorithm>
#include <SFML/Graphics.hpp>
#include <SFML/System/Vector2.hpp>

int VIEW_WIDTH = 1500;
int VIEW_HEIGHT = 1500;

int main(int argc, char *argv[]) {
  sf::RenderWindow *window;

  window = new sf::RenderWindow(sf::VideoMode(50, 50),
      "SFML #474", sf::Style::Default, sf::ContextSettings(0, 0, 16, 2, 0));
  window->setSize(sf::Vector2u(VIEW_WIDTH, VIEW_HEIGHT));
  window->setVerticalSyncEnabled(true);

  sf::View view;
  view.reset(sf::FloatRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT));
  view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
  window->setView(view);

  sf::RectangleShape rect;
  rect.setSize(sf::Vector2f(VIEW_WIDTH - 40, VIEW_HEIGHT - 40));
  rect.setPosition(20, 20);
  rect.setFillColor(sf::Color::Black);
  rect.setOutlineThickness(4);
  rect.setOutlineColor(sf::Color::White);

  std::cout << window->getSize().x << ", " << window->getSize().y << std::endl;

  while (true) {
    std::cout << window->getSize().x << ", " << window->getSize().y << std::endl;
    window->clear();
    window->draw(rect);
    window->display();

    sf::Event event;
    while (window->pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window->close();
        exit(0);
      }
      if (event.type == sf::Event::Resized) {
        unsigned int oldWindowWidth = window->getSize().x;
        unsigned int oldWindowHeight = window->getSize().y;
        double widthScale = ((double) oldWindowWidth) / VIEW_WIDTH;
        double heightScale = ((double) oldWindowHeight) / VIEW_HEIGHT;
        double scale = std::min(widthScale, heightScale);

        unsigned int windowWidth = (int) (scale * VIEW_WIDTH + 0.5);
        unsigned int windowHeight = (int) (scale * VIEW_HEIGHT + 0.5);
        window->setSize(sf::Vector2u(windowWidth, windowHeight));
      }
    }
  }

  return 0;
}

Giving me the size I asked for seems like the right behavior, but it will leave me needing to figure out the dock height to emulate what OS X was doing for me before.

@Voidious

This comment has been minimized.

Show comment
Hide comment
@Voidious

Voidious Oct 9, 2013

I'm asking myself if it's up to SFML to prevent such situations (and therefore not firing a resize event from setSize() and its implementation) or if the user has to be aware of them and make sure they don't happen...

For what it's worth, I have a guard in my code to prevent handling more than one resize per frame. Can't remember if it was Mac or Linux (or both) that caused me to add that while working with SFML 2.0 RC's.

Voidious commented Oct 9, 2013

I'm asking myself if it's up to SFML to prevent such situations (and therefore not firing a resize event from setSize() and its implementation) or if the user has to be aware of them and make sure they don't happen...

For what it's worth, I have a guard in my code to prevent handling more than one resize per frame. Can't remember if it was Mac or Linux (or both) that caused me to add that while working with SFML 2.0 RC's.

@mantognini

This comment has been minimized.

Show comment
Hide comment
@mantognini

mantognini Oct 10, 2013

Member

Huumm... there are indeed a few things to be improved.. :-/

For example, moving a window bigger than the screen will resize it down to the screen size without generating an event. No idea why.

I reopen this issue but since those are really vicious corner cases don't expect a fix soon.

Member

mantognini commented Oct 10, 2013

Huumm... there are indeed a few things to be improved.. :-/

For example, moving a window bigger than the screen will resize it down to the screen size without generating an event. No idea why.

I reopen this issue but since those are really vicious corner cases don't expect a fix soon.

@mantognini mantognini reopened this Oct 10, 2013

@Voidious

This comment has been minimized.

Show comment
Hide comment
@Voidious

Voidious Oct 10, 2013

Thanks for looking into it. I'll probably just drop to 2.0 on OS X until this is resolved. Maybe I can try and tinker a bit myself once I get the next version of my app out the door, but OS X windowing isn't exactly my forte. :-)

Voidious commented Oct 10, 2013

Thanks for looking into it. I'll probably just drop to 2.0 on OS X until this is resolved. Maybe I can try and tinker a bit myself once I get the next version of my app out the door, but OS X windowing isn't exactly my forte. :-)

@mantognini mantognini modified the milestones: 2.2, 2.x Apr 23, 2014

@mantognini mantognini added the resolved label Apr 23, 2014

jcowgill added a commit to jcowgill/SFML that referenced this issue Sep 22, 2014

Fixed window size not correctly updated when changed through Window::…
…setSize (SFML#474)

Modifed by James Cowgill to prevent ABI breakage.

(cherry picked from commit fe12270)

jcowgill added a commit to jcowgill/SFML that referenced this issue Sep 22, 2014

jcowgill added a commit to jcowgill/SFML that referenced this issue Sep 22, 2014

Improved resizing windows on OS X (close SFML#474)
sf::Window::setSize will fire a resize event if the view could not be created at the requested size.
(cherry picked from commit efe4354)

Conflicts:
	src/SFML/Window/OSX/SFWindowController.mm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment