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

Author Topic: Using SFML as a child window without access to Event Loop  (Read 9358 times)

0 Members and 5 Guests are viewing this topic.

burn.it.all.down

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Using SFML as a child window without access to Event Loop
« on: September 10, 2021, 11:49:09 pm »
First, let me just say that I really enjoy SFML and really hope that there are no issues with my design intent.

The Scenario:

The VST3 framework controls the parent window and the event loop so you cannot use pollEvent.

So I've been writing test code that allows me to create a native Win32 child window and then wrap the HWND in a sf::WindowHandle and then pass that to sf::RenderWindow, which works great.

For events, I've been forwarding messages from my Win32 wndProc callback to my SFML wrapper that the sf::RenderWindow can process draw on WM_PAINT, close on WM_CLOSE/WM_QUIT and then perform a few mouse and keyboard events.

Everything seems to work fine so far.

The Problem:

The conversion from the WinApi events to sf::Event is handled privately via WindowImplWin32. So I have two questions:

1. Is there actually a public-facing interface from SFML that enables native event conversion to sf::Event?
2. Are there known any issues or undefined behavior that can occur if I continue down this path?

Thanks!




burn.it.all.down

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: Using SFML as a child window without access to Event Loop
« Reply #1 on: September 17, 2021, 05:51:28 am »
For those interested, I've managed to get SFML working pretty well whenever there's not direct access to an event loop AND whenever you have to create a native Win32 child window first that SFML then consumes. Some gotchas:

1. SFML takes over whatever data you've stored in SetWindowsLongPtr GWLP_USERDATA with its own sf::priv::WindowImplWin32, which you don't have public access to.

2. SFML doesn't trigger any events on WM_TIMER, so you'll need to SetTimer() with your own callback in order to create your own event loop. You'll need to map the child HWND used with SetTimer to your class due to issue 1.

3. Don't create the win32 child window using CW_USEDEFAULT for width and height because it'll return 0, which makes SFML scale things oddly. Know your starting window size in advance, if possible, by getting it from another API or using GetWindowRect. Somebody with more SFML experience may know how to scale properly once your original size is set to zero and then you call sf::Window::setSize( { >0, >0 } ).

4. Don't mistakenly call sf::Window::create() AFTER other adjustments, such as setSize, setActive because you haven't actually created anything yet and you'll bang your head

5. You must call SetFocus( getSystemHandle() ) directly on timer callback or else keyboard events won't be available. The sf::priv::WindowImplWin32::requestFocus() calls SetForegroundWindow() when on the same process thread or flashes a window notification but there's nothing in the API that calls SetFocus on your behalf

There was a lot of trial and error and I still had to perform quite a bit of native API wrapping. Originally, I was hoping to be able to have SFML create a child window automatically for me by giving it a parent window handle. Maybe I'm the only dope who wants this use case though.
« Last Edit: September 17, 2021, 03:35:11 pm by burn.it.all.down »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Using SFML as a child window without access to Event Loop
« Reply #2 on: October 10, 2021, 06:37:45 pm »
Does the reverse not work, of calling .create with the HWND after you've created the child window yourself?

You could also try to connect with j.keller51, who's also written some VST using SFML.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

burn.it.all.down

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: Using SFML as a child window without access to Event Loop
« Reply #3 on: October 20, 2021, 07:43:03 am »
Thanks for the contact.

Does the reverse not work, of calling .create with the HWND after you've created the child window yourself?

That is what I'm currently doing. It works if I create the native child window myself, call create( childHWND ), and then process the SFML loop via the SetTimer callback. Another way is to also have SFML create a new window using sf::Style::None, call SetWindowLongPtr to update the dwstyle, call SetPosition to enact the update, and then call SetParent to attach it.

The problem with the sf::Style::None option is that SFML sets dwstyle to WS_POPUP, which cannot be used with WS_CHILD but it does get around other dwstyle issues on initial SFML window creation.

Regardless of which route you take, you're left making quite a few OS-specific calls. There's probably very little demand to add a cross-platform feature for something like createAsChildTo( parentSystemHandle ) but that would be ideal for folks who are looking for plugin solutions.


 

anything