Over the past year I've been trying to rewrite one of my projects from linux/X11 specific code to something more portable.
I first went with freeglut which seemed to work well, until I tried to compile it on other platforms (e.g. Windows). While in principle, all the libraries I was using had windows versions, it was just a nightmare trying to get them all istalled and properly linked.
Then I learned about SFML (SFML2). This single library seemed to have all the features my project required and looked like it would be much easier to compile against on Windows. All was going well until I tried to create a subwindow - unless I'm missing something SFML2 does not have the ability to create subwindows.
I'd want a subwindow as - basically - my primary SFML window is a large canvas. This canvas can be resized and moved/scrolled. I can do this with a single window, but it will be ugly as it will span off the user's screen. I'd like this large canvas window to be a child of a top-level window. So the canvas can be resized and scrolled within the top-level window, and the top-level window can be resized, maximized, whatever like any other window.
I was able to do this in my freeglut code by creating one glut top-level window then creating the main canvas window with glutCreateSubWindow.
As I've been working with SFML (which uses a opengl/glut backend as I understand) I assumed it'd be able to do something similar. But so far no such luck.
I know I can use platform specific code to create a top-level and sub-window and then use SFML to assign a view to the subwindow. I'd not love this approach, as I'd still need platform specific modules, but they'd be small, so I could write one for each target platform. However, I don't understand how this could even work. If I create one X11 module, and one Win32 module that create the windows then call SFML to assign the view, I don't know how to handle events: my main event loop is in the SFML module using sf::Window.waitEvent() - I would not be able to do this with X11/Win32 windows as they would need their own event loops.
So now I'm stuck - is SFML also a dead end for this project, or is there a way to create an SFML window as a subwindow and use an SFML event loop? The top-level window would not need anything special: any generic top-level window that would serve as a container would do.
If I understand correctly, you use the subwindow simply as a canvas, that is, as an off-screen buffer for drawing. I haven't used SFML myself, but looking at the documentation I think RenderTexture might be what you are looking for. It doesn't seem to support resizing after creation, but you can always create a new RenderTexture when you need to resize the canvas (unless you have to do it often, in which case it might get slow).
No, sorry, it is not an off-screen buffer. It is - essentially - the main window where everything happens. All the graphics are displayed to this window, the user interacts with this window. Currently I have a functional version with only this one window. I'd just like this to be contained in another simple window.
The canvas window needs to be able to be (potentially) larger than the screen and move around to "zoom in" on various parts of the window. I can do this with the single top-level window, but it is just a bit abnoxious as it actually takes up the user's whole screen if the image is larger than the screen. As a subwindow, this large window could be contained in a moderate sized normal window.
With freeglut my top level window did almost nothing. The freeglut subwindow was where all the drawing and interaction happened, but this subwindow could be moved around within the top-level window. That is the goal.
Sorry if I'm just making noise here, but after browsing through SFML docs some more, here's another suggestion. I think the View class in SFML offers the drawing portions of what you want. You set the target viewport to cover the whole main window and then alter the View's source rectangle to match the portion of the "canvas" you wish to display. SFML even takes care of the required scaling automatically. So instead of drawing to a separate (sub)window, you draw everything through the main window object and the attached View object takes care of displaying only the parts you want.
As for the input handling, just preprocess the input you receive to the main window (being the only window with SFML) by transforming window coordinates to canvas coordinates. Then shove the preprocessed input to your existing input handling.
Thanks, but I'm familiar with the view class, that is already being used. My issue is essentially that I need a view within a view. In SFML View and Window are separate but very related classes: so view withing view = window within window.
I could make an artificial subwindow as you describe by manually rerendering everything every time a fake subwindow was moved or resized, but this would negate all the benefits of using SFML/openGL. I want the texture sent to the graphics card as few times as possible - this 'fake window' approach could require transfers between the main memory and graphics memory of a new rendering dozens of times per second (or more).
EDIT: hold on, maybe this could work - I'll have to look into this. Although transorming all the coordinates myself for every interaction would be a bit of a pain.
Stuge, I just did some testing and you are right, a View will do exactly what I need.
It will require quite a bit of revision as my existing code works on the assumption that window size = "view" size and now I need to decouple these, but I've been tinkering with it and what I've implemented acheives my goal. Thanks.