SFML community forums

Bindings - other languages => Java => Topic started by: pdinklag on October 11, 2012, 11:07:23 am

Title: RenderCanvas on X11 and Cocoa
Post by: pdinklag on October 11, 2012, 11:07:23 am
A short while ago, I started the "render-canvas" branch in which I'm adding the "RenderCanvas" - a Java control that makes it possible to have an SFML RenderWindow inside a Java AWT UI.

On Windows, it seems to work perfectly fine now. There was a conflict between AWT and SFML in that both registered their own window function. The solution I came up with was to create my own window function that passes all events to both AWT and SFML.

Now, I am trying to get things running under Linux / X11, where I'm facing a similar problem: AWT seems to "eat" all the input events and SFML doesn't get any. The problem is that I know barely anything about X11 programming and how applications register themselves as "input listeners".

Both SFML and AWT seem to create a so-called "input context" using XOpenIM and XCreateIC. AWT does this before SFML, naturally. I have no idea how this works, but this is the only thing I see at the moment that could cause conflicts.

Both SFML and AWT also perform "XMapWindow" and "XFlush", but since both run in the same environment I think the display remains the same and this doesn't cause any issues.

Finally, both SFML and SWT do something concerning a "WM_DELETE_WINDOW". I assume that's some kind of callback and hope it won't cause any issues.

Well, I could need some help here pointing me in a direction to look.

I also assume that similar problems will occur on Mac OS X / Cocoa. I hope that Hiura can have a look at this at some point as well. Just checkout the "render-canvas" branch, compile it all (C++ sources too) and run "jsfml-test.sh swing". You will probably have to fix the build.xml because the "jawt" library needs to be linked.
Title: Re: RenderCanvas on X11 and Cocoa
Post by: Laurent on October 11, 2012, 02:13:53 pm
Quote
On Windows, it seems to work perfectly fine now. There was a conflict between AWT and SFML in that both registered their own window function. The solution I came up with was to create my own window function that passes all events to both AWT and SFML.
You don't have to do that. On Windows, when you register your event callback, it is inserted in the chain of other existing callbacks (if you do things right), so you don't have to care about other potential systems that use an event callback on the window. Just look at how SFML does ;)

Same advice for Linux: look at SFML sources. I wrote it a long time ago so I can't tell you what to do exactly.
Title: Re: RenderCanvas on X11 and Cocoa
Post by: pdinklag on October 11, 2012, 02:17:49 pm
Quote from: Laurent
You don't have to do that. On Windows, when you register your event callback, it is inserted in the chain of other existing callbacks (if you do things right), so you don't have to care about other potential systems that use an event callback on the window. Just look at how SFML does
Both SFML and AWT wrote the "GWLP_WNDPROC" and "GWLP_USERDATA" fields and both expect their respective data in it. That failed, I had to fix it.

And I'm assuming something similar to break input events being passed to SFML on Linux. AWT receives them, SFML doesn't. To me, that sounds like a broken chain. The SFML source is relatively simple, it's the AWT sources that are complicated as hell. That's why I asked, maybe somebody has an idea right away. If not, I'll have to dig through that mess that is AWT's C code. :)
Title: Re: RenderCanvas on X11 and Cocoa
Post by: Laurent on October 11, 2012, 02:22:36 pm
Quote
Both SFML and AWT wrote the "GWLP_WNDPROC" and "GWLP_USERDATA" fields and both expect their respective data in it. That failed, I had to fix it.
GWLP_USERDATA is a window property and there's only one, so yes you have to find a workaround.

But when you set GWLP_WNDPROC, you get the previous one and can call it back in your own event callback so that the chain is not broken. That's how you're supposed to handle it.

This is what I have in SFML, in the event calllback:
if (window->m_callback)
    return CallWindowProc(reinterpret_cast<WNDPROC>(window->m_callback), handle, message, wParam, lParam);

Quote
And I'm assuming something similar to break input events being passed to SFML on Linux
As I said I don't remember how things work on Linux, so you have to look at the source code (of SFML). I can have a look if you're really stuck.
Title: Re: RenderCanvas on X11 and Cocoa
Post by: pdinklag on October 12, 2012, 07:15:46 am
Well, for now, I am using a workaround. But I'm not sure if I should present that as "the solution".

Firstly, some events are actually received by SFML. I don't know the reason, but SFML gets the MOUSE_MOVED, MOUSE_ENTER and MOUSE_LEFT events just fine. Resizing events also work out of the box.

For some reason, when I move the mouse, SFML also gets a JOYSTICK_MOVED event. Any idea what this is about? It might have to do with a VM setting, I'm not using a real Linux machine atm.

Anyway, since AWT receives the events, I can register the respective event listeners on the canvas and simulate SFML events:

This works perfectly and is completely hidden away from the user, but it seems like a really ugly mix of SFML and AWT event reception to me. Any opinions on that?

EDIT:
Thinking about it, I could simulate *all* SFML events from AWT events on all operating system. That way, all the problems would be ruled out and it'd be consistent.

I suppose I would still have to poll events from the RenderWindow to make sure that the buffer doesn't fill up? Or isn't that a problem?
Title: Re: RenderCanvas on X11 and Cocoa
Post by: Laurent on October 12, 2012, 08:00:01 am
Quote
I suppose I would still have to poll events from the RenderWindow to make sure that the buffer doesn't fill up? Or isn't that a problem?
I'm not sure. If you don't call pollEvent, SFML doesn't trigger internal event processing, but AWT probably does it and my event callback gets called anyway. That's for Windows at least, on Linux there's no registered event callback so nothing can happen automatically, and I have no idea about OS X.

But when integrating SFML into another GUI toolkit, SFML events shouldn't be used in my opinion. If you have an AWT interface, with AWT events everywhere, it feels strange to use SFML events just for that specific canvas, which is an AWT component too.
Title: Re: RenderCanvas on X11 and Cocoa
Post by: pdinklag on October 12, 2012, 08:10:35 am
Good point.

Well, that's the question, should I even put any effort in translating AWT events to (J)SFML events?

IMO, it would be strange for users if they can work with the JSFML event types when they use a single window, but suddenly have to deal with AWT event listeners when they integrate the window into an AWT GUI.

So right now, I am listening on AWT events, translate them to JSFML events and add them to a queue. When you call pollEvent, it will poll from that queue instead of the SFML one. The translation seems to be very reliable, although I will have to put some effort into making the key repeat disabling work. AWT does not have such a feature.
Title: Re: RenderCanvas on X11 and Cocoa
Post by: Laurent on October 12, 2012, 08:43:15 am
Since you can use AWT events, yes it can be worth the effort. It's a different problem for SFML itself, where I can't write code on top of a specific GUI toolkit.
Title: Re: RenderCanvas on X11 and Cocoa
Post by: pdinklag on January 03, 2013, 08:46:46 pm
There are some issues that remain before the RenderCanvas can be merged into the master branch.

In the render-canvas branch, the JSFML binary depends on the Java AWT binaries. However, those might not be available everywhere. For instance, you can install a headless JRE on a Linux machine and end up without the AWT binaries.

I am not quite sure how to proceed here. SFML is a multimedia library, and a headless environment practically does not need that. However, you might want to use some of the SFML classes for server code, e.g. Vector2f for synchronized entity positions, to name an example.

A very easy fix would be a separate lightweight JSFML package called "jsfml-headless" for those environments. It would only contain data classes like Vector2f, Time, etc.  Those are all implemented in pure Java anyway, so that package would not even require any of the complicated binary loading and take a few kilobytes at max. It would be similar to SFML's "system" binary, JSFML is not as strictly modularized.

Other than that, there has been zero progress for Mac OS X yet and I did not do any testing yet concerning browser applets. I'd love to include this feature in the first release, but these have to be resolved first. The binding is finally shaping up now and I will spend more time on this branch in the near future.