Thread: [UFO-devel] Events and layered panes
Status: Beta
Brought to you by:
schmidtjf
From: Andreas B. <b_...@gm...> - 2005-11-30 23:00:55
Attachments:
events.diff
|
Hi attached is a patch that I have sent before, I believe (or at least mentioned). It implements layered pane compatible event handling. Umm, well, this patch has been used in Boson for quite some time, here the comment in my README about this patch: - Patch to uabstractcontext.hpp, uabstractcontext.cpp and uwidget.cpp to improve events for our needs: Instead of delivering a mouse event to root->getVisibleWidgetAt(), we implement a getVisibleWidgetsDFS() function, that starts at the root and finds all currently visible widgets (at the relevant point) using a depth first search and returns them in a stack. We then dispatch it to every widget on the stack until one widget consumes the event (in that case we stop then). This especially fixes layered panes: previously an event was delivered to the topmost layer only and to the layered pane itself, if the widget was not interested in that event. Now the event is first delivered to the topmost layer, then to the layers below it, then to the layered pane. This patch makes pretty much the difference between "libufo is usable" and "libufo is unusable" for us: it is extremely important that a click on a button is dispatched to the button and clicks on everything else is delivered to the stuff below that. (yeah, that was the simple version) I have been maintaining this patch for 2 or 3 libufo updates already and it starts to go on my nerves. I know that my (non-trivial) patches are not very liked here, so is there any chance this every makes it to official cvs? If not I'll investigate whether it is possible to subclass ufo::UAbstractContext instead and achieve the same in our extension library, so that I don't have to re-apply the patches every time (well - at least not all of them. The ufo::UWidget::dispatchEvent() part cannot be done outside of libufo). CU Andi |
From: Andreas B. <b_...@gm...> - 2005-11-30 23:37:42
|
The e->unreference() in ufo::UWidget::dispatchEvent() should of course be AFTER the #endif, not before. CU Andi |
From: Johannes S. <sch...@us...> - 2005-12-01 15:37:13
|
Am Donnerstag 01 Dezember 2005 00:01 schrieb Andreas Beckermann: > Hi > attached is a patch that I have sent before, I believe (or at least > mentioned). Sorry, there are probably several patches which are lost in email flood. I've been very busy last weeks doing some uni stuff. > It implements layered pane compatible event handling. > Umm, well, this patch has been used in Boson for quite some time, here the > comment in my README about this patch: > > - Patch to uabstractcontext.hpp, uabstractcontext.cpp and uwidget.cpp > to improve events for our needs: > Instead of delivering a mouse event to root->getVisibleWidgetAt(), we > implement a getVisibleWidgetsDFS() function, that starts at the root and > finds > all currently visible widgets (at the relevant point) using a depth first > search > and returns them in a stack. > We then dispatch it to every widget on the stack until one widget > consumes the event (in that case we stop then). > This especially fixes layered panes: previously an event was delivered to > the > topmost layer only and to the layered pane itself, if the widget was not > interested in that event. Now the event is first delivered to the topmost > layer, then to the layers below it, then to the layered pane. > > > This patch makes pretty much the difference between "libufo is usable" and > "libufo is unusable" for us: it is extremely important that a click on a > button is dispatched to the button and clicks on everything else is > delivered to the stuff below that. (yeah, that was the simple version) Just a side note: Keep the GUI stuff clearly separated from your game engine stuff or you will end up in an unmaintainable, monolithic source tree. If the event haven't been processed by the GUI, send it to your game engine. To your problem: I thought of adding a separate event dispatcher (which can be added to the display), which chooses to which widget(s) the event is sent. Anyway, this may take some time, as I am really busy these days. cu, Johannes |
From: Andreas B. <b_...@gm...> - 2005-12-01 17:46:41
|
On Thursday 01 December 2005 15:23, Johannes Schmidt wrote: > Am Donnerstag 01 Dezember 2005 00:01 schrieb Andreas Beckermann: [...] > Just a side note: > Keep the GUI stuff clearly separated from your game engine stuff or you > will end up in an unmaintainable, monolithic source tree. > If the event haven't been processed by the GUI, send it to your game > engine. Is there _any_ relation to the patch or are you just trying to be the teacher? ;-) > To your problem: I don't have a problem, the attached patch fixed pretty much everything a long time ago for me. > I thought of adding a separate event dispatcher (which can be added to the > display), which chooses to which widget(s) the event is sent. > Anyway, this may take some time, as I am really busy these days. May I read this as a "this patch won't ever make it into official cvs" ? > cu, > Johannes CU Andi |
From: Johannes S. <sch...@us...> - 2005-12-13 17:58:37
|
Am Donnerstag 01 Dezember 2005 18:40 schrieb Andreas Beckermann: [...] > > Just a side note: > > Keep the GUI stuff clearly separated from your game engine stuff or you > > will end up in an unmaintainable, monolithic source tree. > > If the event haven't been processed by the GUI, send it to your game > > engine. > > Is there _any_ relation to the patch or are you just trying to be the > teacher? ;-) The relation is that you definitely have one of the most complex GUI designs I've ever seen. There are easier methods which do not depend on the event dispatching method. You are using several nested layered panes, big widget hierarchies and so on. Layered panes were designed to handle popups and internal frames. And all I can see on the screen shots are a command frame and some text buffers. Now if neither the command frame nor the text frame or other GUI elements processed the event, it should be processed by the game engine. Or you could register event listeners at the internal frame, which is used to display the command frame, and redispatch it to your game widget if none of the buttons did process the event (otherwise it won't bubble up). Both are independent of the way how event dispatching is done and there are surely more solutions to do that. [...] > > I thought of adding a separate event dispatcher (which can be added to > > the display), which chooses to which widget(s) the event is sent. > > Anyway, this may take some time, as I am really busy these days. > > May I read this as a "this patch won't ever make it into official cvs" ? Yes. Probably it is best to override UXContext instead of patching UAbstractContext. Regards, Johannes |
From: Andreas B. <b_...@gm...> - 2005-12-13 19:45:16
|
On Tuesday 13 December 2005 18:58, Johannes Schmidt wrote: > Am Donnerstag 01 Dezember 2005 18:40 schrieb Andreas Beckermann: > [...] > > > > Just a side note: > > > Keep the GUI stuff clearly separated from your game engine stuff or you > > > will end up in an unmaintainable, monolithic source tree. > > > If the event haven't been processed by the GUI, send it to your game > > > engine. > > > > Is there _any_ relation to the patch or are you just trying to be the > > teacher? ;-) > > The relation is that you definitely have one of the most complex GUI > designs I've ever seen. I have? I disagree... The only "complex" part is that we want transparency (and even translucency in the future) and yeah, that's exactly what I need the patch for, that we are talking about. Oh and of course: without transparency libufo would be totally pointless to me, I could achieve the same with Qt/KDE (much easier even - no need for a GL solution). > There are easier methods which do not depend on the > event dispatching method. > You are using several nested layered panes, big widget hierarchies and so > on. Layered panes were designed to handle popups and internal frames. Yeah, I can see that from the code. libufo is clearly not designed to be used in an environment that uses transparency a lot. This was somewhat surprising to me, as I have always thought that is the main reason for why someone would use OpenGL for a GUI at all. And that's also what the patch is for: it make libufo support more than only simple popups and internal frames. > And all I can see on the screen shots are a command frame and > some text buffers. Oh wow, I can see much more. I can see a minimap (often only the boson logo, as the minimap is not available to the player - but it's the same widget) and the game area itself. Both are BoUfoWidget objects (the wrapper around ufo::UWidget in boson). > Now if neither the command frame nor the text frame or other GUI elements > processed the event, it should be processed by the game engine. There are many more. Firs of all the most visible layered pane contains the * chat widget * pause label * what you call the command frame (which contains the actual command frame, the minimap and a few debug widgets) These should be separate widgets in the same layered pane, as they all must overlap. This layered pane is embedded into a "main" layered pane, which is used by the actual game GUI. Besides the above mentioned widget (the layered pane) it contains * the canvas widget (reponsible for rendering the actual game world, i.e. ground + units) * placement preview widget * tooltip label * cursor widget * selectionrect widget * several debugging widgets Most, but not all of them can receive events. And it is very (!!!) important that they receive them in the correct order. For example if the canvas widget receives a click on the map before another widget, it'll eat the event. This is not intended, if the mouse is currently on a button in the commandframe. Also widgets can overlap (that is intended and in most cases very important!) and so it can happen that a button is on top of a different button (this is not intended, but unavoidable .. at least by code design). And here the priorities must be correct, too - if widget A is on top of B, then A must receive all events before B does. But if A doesn't want the events, then B must receive them, before the game GUI does. > Or you could register event listeners at the internal frame, which is used > to display the command frame, It isn't, it's a widget. I don't know if the same would be possible with widgets (and not only frames) - but the point is I don't want to. The libufo event listeners are not very powerful and not really nice to use. In addition I simply don't trust them, as they are pretty much unused in libufo. AFAICS only menu/popups use them at all and even they do that for extremely simple tasks only. So I'd have to figure out how to use them correctly myself, and even then would risk to find bugs. I don't want to debug yet another piece of code in libufo - especially since it's very hard to debug libufo (not because of the code itself - the code itself is pretty good. But rather because of the issues I mentioned long ago, e.g. *.hpp heades and especially distinction of src/ and include/ directories which force me to have several editor sessions opened all the time, only to perform simple tasks. Most libufo debugging sessions take much longer than simply rewriting all of the relevant code). And last but not least: the patch works. It works very well, even in my "complex" GUI design (which I consider a "normal" GUI design from a game POV). So why not include a patch that supports both, simple and complex designs instead of the simple ones only? > and redispatch it to your game widget if none > of the buttons did process the event (otherwise it won't bubble up). > > Both are independent of the way how event dispatching is done and > there are surely more solutions to do that. This sounds pretty much like "do the correct event dispatching yourself". Why doesn't the library do that? I thought that's the main point of a widget toolkit? > [...] > > > > I thought of adding a separate event dispatcher (which can be added to > > > the display), which chooses to which widget(s) the event is sent. > > > Anyway, this may take some time, as I am really busy these days. > > > > May I read this as a "this patch won't ever make it into official cvs" ? > > Yes. > Probably it is best to override UXContext instead of patching > UAbstractContext. Honestly: not a surprise to me. Not a single non-trivial patch I sent in got ever applied. And even the trivial ones usually got rewritten. I didn't really expect it to change anytime soon. > Regards, > Johannes CU Andi |