Open GoogleCodeExporter opened 9 years ago
Hi, im a developer of openanno (www.openanno.org) and we use the fife engine,
which
uses guichan.
We have the same issues with dropdown boxes, i just want to confirm this but
cant
give a more detailed bug description, all i know is that an excaption is thrown
and
that the logic function by this does not do anything anymore.
Original comment by kristoff...@googlemail.com
on 12 Aug 2008 at 11:01
I need to be able to reproduce the problem to fix it. What is the exception
thrown?
Can you use a debugger to see where the problem occurs?
Original comment by olof.nae...@gmail.com
on 18 Aug 2008 at 1:20
the problem occurs in handleModalMouseInputFocus();
when the dropdown box is clicked
i don't know why this happened
apparently is a null pointer exception
Original comment by thenetce...@gmail.com
on 19 Aug 2008 at 12:59
I have a similar problem. I am using guichan 8.1 .
To reproduce create a TabbedArea with two Tabs: Tab1 and Tab2. In each tab
place a
dropdown, DD1 and DD2 populated with some items.
Click Tab2
Click DD2 and select an item from the list
Click Tab1
Click DD1
At this point an exception is thrown from Tab2's isModalMouseInputFocused()
complaining that there is no focus handler. There is no focus handler because
we
set the focus handler to NULL when Tab2 was removed from the TabbedArea after
clicking Tab1. A pointer to Tab2 seems to be still lingering in the
mWidgetWithMouseQueue after the widget had been removed from the widget
hierarchy.
Original comment by esm...@gmail.com
on 3 Sep 2008 at 6:14
In guichan-0.8.1/src/gui.cpp
problem occurs here
void Gui::handleModalMouseInputFocus()
{
// Check if modal mouse input focus has been gained by a widget.
if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
!= mFocusHandler->getModalMouseInputFocused())
&& (mFocusHandler->getLastWidgetWithModalMouseInputFocus() == NULL))
{
handleModalFocusGained();
mFocusHandler->setLastWidgetWithModalMouseInputFocus(mFocusHandler->getModalMous
eInputFocused());
}
// Check if modal mouse input focus has been released.
else if ((mFocusHandler->getLastWidgetWithModalMouseInputFocus()
!= mFocusHandler->getModalMouseInputFocused())
&& (mFocusHandler->getLastWidgetWithModalMouseInputFocus() != NULL))
{
handleModalFocusReleased();
mFocusHandler->setLastWidgetWithModalMouseInputFocus(NULL);
}
}
Original comment by thenetce...@gmail.com
on 3 Sep 2008 at 11:56
I can't recreate it with the latest Guichan SVN version. I fixed a possible
segfault
concerning modal mouse input some time ago, perhaps it took care of the problem?
Note, I always work with the latest SVN version. If you have a bug you should
try the
SVN version as things might have been taken care of.
Original comment by olof.nae...@gmail.com
on 3 Sep 2008 at 1:41
I have had the same over the weekend, SVN version, and after some debugging I
think
I know where it comes from.
Here's what I did: I have two containers which serve as top level widgets, one
for
each screen. My gameloop can switch screens by calling
gui->setTop(new_toplevel);
Now, each of these containers has widgets as children, but top2 has a dropdown
somewhere as child. Now I start with top1, all is fine, then gui->setTop(top2)
is
called, I can see the dropdown, but when I click it, I get the exception. It
complains about a widget not having a focus handler, and I really wondered...
and
then the debugger told me that it's top1 that complains here!!!
Why is that? Simple, there's a double bookkeeping hidden in gcn::Gui. On the
one
hand you have mTop (and its children), but for focus handling you use
mWidgetWithMouseQueue, which may contain widgets that are not children of the
current top level widget. Voila!
Several solutions, as I see it, though I don't know exactly how this is
intended to
work. The simplest is to ask for existing focus handler in line 939, which
would
then read
if (Widget::widgetExists(widget) && widget->_getFocusHandler())
That works for my example, but I guess that that would only be a workaround,
not a
real solution.
It might be a better solution to get rid of the extra bookkeeping and traverse
the
widgets starting with the current top level widget instead of using
mWidgetWithMouseQueue.
Or you would have to make sure that the current widget hierarchy is in sync
with the
widgets in mWidgetWithMouseQueue.
Hopefully this helps to nail down this problem and solve it!
Original comment by tobias.s...@gmx.net
on 15 Sep 2008 at 12:00
I'm actually thinking about removing the top widget and let the Gui already
contain a
top widget that is a Container. That way your problem shouldn't occur. Instead
of
Removing the top container you would instead remove a container from the top.
This solution also makes it possible for widgets to add widgets to the top at
runtime, such as the drop down adding it's dropped down part to the top or a
menu
adding it's display part to the top.
Original comment by olof.nae...@gmail.com
on 15 Sep 2008 at 9:51
Hm. Sounds good at first glance. How do you make sure that there's only one top
widget at a time? Now, when I setTop(p) the existing top widget is removed and
p is
set. There shouldn't be more than one top widget, even in case that something
adds a
(temporary) additional widget 'on top' of all others.
Also I'm not completely sure if that really solves the problem here. When I
remove a
widget from the container, what happens to the focus handler of that widget? If
it
remains, then why is the focus handler reset to 0 in setTop(0)? If it doesn't
remain, the problem would persist...
Why is to necessary to have an extra deque of widgets mWidgetWithMouseQueue?
Original comment by tobias.s...@gmx.net
on 16 Sep 2008 at 6:10
The real issue here is that making Guichan work with dynamic behaviour, like
removing
things and deleting things runtime, is very difficult. At first Guichan was
designed
for more or less static GUIs, but over time we have enhanced it to be more
flexible.
The mWidgetWithMouseQueue is a typical example of something at least I have
overlooked.
mWidgetWithMouseQueue is necessary when dealing with focus. When you hover a
widget
there might be several widgets under the mouse that should receive a focus
gained
event, or more importantly several widgets should receive a focus lost event as
soon
as the mouse exits the widget, thus they need to be remembered.
Consider a container with a button at coordinate (0, 0). When the mouse enters
the
button area from left to right at the top of the button area both the container
under
the button and the button has the mouse. This is all tracked by Guichan using
the
mWidgetWithMouseQueue.
By design Guichan does most of the advanced stuff in the Gui class so end users
don't
have to worry about it when making widgets. Deleting a widget is all fine as
the Gui
class will be notified whenever a widget is deleted. Removing a widget from a
container on the other hand is another matter. Somehow the Gui class needs to be
notified upon these events to update it's internal state.
A solution might be to let every widget hold a reference to the Gui they belong
to
and notify the Gui upon changes, just like every widget holds a reference to the
Gui's focus handler.
Original comment by olof.nae...@gmail.com
on 16 Sep 2008 at 10:56
I'm also thinking about merging Widget and BasicContainer. If every widget is
treated
like container making container widgets of your own will be much easier as all
notifications to the Gui class could be handled by Widget.
Original comment by olof.nae...@gmail.com
on 16 Sep 2008 at 11:03
ad 10) another reference from the widget to gui? Why not keep
mWidgetWithMouseQueue
in sync with the current widget hierarchy in setTop()? Or traverse the widget
hierarchy instead of using mWidgetWithMouseQueue?
ad 11) it might make creating custom containers easier (i haven't had any big
problems with my custom containers), but it feels wrong nevertheless. Because
in
general a widget IS NOT a container, and people are also making custom widgets
that
are not containers (at least I am).
I appreciate that gui does all the hard work, which is one of the great
advantages
of using guichan. I also appreciate the flexibility guichan gives me, so I
really
would like to see a good solution here that supports all the dynamic uses
people
have. Currently I can live with the additional check for the widget having a
focus
listener, even if that's not a final solution. For that, I would try to get rid
of
double bookkeeping, and probably try to get rid of mWidgetWithMouseQueue
altogether.
Original comment by tobias.s...@gmx.net
on 16 Sep 2008 at 11:33
For comparison with Qt, the QWidget can contain child widgets and as such is a
container. Of course many widgets don't actually have child widgets, but that
really
doesn't matter.
However, note that QWidget does not have a container interface or anything.
There is
no QWidget::addWidget/removeWidget. Widget A is the child of widget B if B is
set as
the parent of widget A (and this also defines ownership). You can do this
either in
the contructor or using QWidget::setParent(). This is part of what makes Qt
really
easy to use.
Original comment by b.lindeijer
on 16 Sep 2008 at 12:38
"Why not keep mWidgetWithMouseQueue
in sync with the current widget hierarchy in setTop()?"
Of course, that's what we want to do, but the question is how? The Gui class
needs to
be informed whenever a widget is disconnected from the Gui, and it can be if
Widget
informs the Gui via a Gui reference in Widget.
"a widget IS NOT a container"
Actually, Guichan uses the composite design pattern
(http://en.wikipedia.org/wiki/Composite_pattern). Therefore a widget should have
container methods. Why that is is quite simple, it makes everything so easy to
always
be able to treat a Widget as a container. Now, the ability to contain other
widgets
doesn't necessary have to mean a widget contains other widgets.
Björn, the QT way seems interesting, but I have a question. How is the
container
informed that it is not any longer an owner of a widget? To me it seems
important
that a container is informed. Also, how is the widget tree traversed? In
Guichan a
container draws its children by iterating over its children list, but how is
this
done in QT where it doesn't seem to be a two way relation between a container
and a
widget, but rather a one way relation between widget and a container.
Original comment by olof.nae...@gmail.com
on 16 Sep 2008 at 1:20
"The Gui class needs to
be informed whenever a widget is disconnected from the Gui, and it can be if
Widget
informs the Gui via a Gui reference in Widget."
I see, you're already thinking in more general terms. For my use case, I'm
thinking
about setTop(), and that replaces the complete widget hierarchy by another one.
So
in a more general situation, things get even more complicated...
I still don't really udnerstand what mWidgetWithMouseQueue is doing. Could it
be
possible, instead of iterating that deque when needed, to traverse the current
widget hierarchy instead? That way, the widget hierarchy would be seen as it is
in
that moment, so only widgets that are active below the current top level widget
are
traversed (and only they can react on events and stuff).
Original comment by tobias.s...@gmx.net
on 16 Sep 2008 at 1:47
"Could it be possible, instead of iterating that deque when needed"
Perhaps, if the last mouse position was remembered it might be possible. The
whole
thing is quite complicated and there are a lot of cases to consider, like when a
widget is removed from the Gui when having the mouse and after a while added to
the
Gui again, it might still think it has the mouse.
Another good thing with having a Gui reference is that we can force a widget
only to
reside in one GUI and in one container in the GUI by checking the Gui reference
and
the parent reference.
Original comment by olof.nae...@gmail.com
on 16 Sep 2008 at 4:21
About the children in Qt: The parent is notified using events
(QEvent::ChildAdded,
QEvent::ChildRemoved) in QObject::childEvent. The actual list of children is
maintained internally and is available via QObject::children(), and you can
search it
using QObject::findChild/findChildren to find children of a specific type or
with a
specific name. All this stuff is in QObject and not in QWidget, since the
ownership
isn't only about widgets.
Original comment by b.lindeijer
on 19 Sep 2008 at 11:59
I've now removed mWidgetWithMouseQueue and changed Gui so the widgets with the
mouse
and the last widgets with the mouse is computed at runtime with the help of the
mouse
position and the last known mouse position.
The new implementation is a lot cleaner than the old one and it will hopefully
solve
some issues with dynamic behaviour, although I am aware of other places that
needs
work (such as adding and removing widgets at runtime from a container).
Original comment by olof.nae...@gmail.com
on 19 Sep 2008 at 3:40
Original comment by olof.nae...@gmail.com
on 19 Sep 2008 at 3:40
Hi, i am a guy of unknown-horizons.org and made a complete backtrace of this
bug,
maybe it's helpfull:
...
terminate called after throwing an instance of 'gcn::Exception'
Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7f9be79196e0 (LWP 20356)]
0x00007f9be6b48095 in raise () from /lib/libc.so.6
(gdb) backtrace
#0 0x00007f9be6b48095 in raise () from /lib/libc.so.6
#1 0x00007f9be6b49af0 in abort () from /lib/libc.so.6
#2 0x00007f9be38640e4 in __gnu_cxx::__verbose_terminate_handler ()
from /usr/lib/libstdc++.so.6
#3 0x00007f9be3862076 in ?? () from /usr/lib/libstdc++.so.6
#4 0x00007f9be38620a3 in std::terminate () from /usr/lib/libstdc++.so.6
#5 0x00007f9be386218a in __cxa_throw () from /usr/lib/libstdc++.so.6
#6 0x00007f9be43ce4f4 in gcn::Widget::isModalMouseInputFocused (
this=<value optimized out>) at widget.cpp:617
#7 0x00007f9be43c6bae in gcn::Gui::distributeMouseEvent (this=0x1052fc0,
source=0x8171170, type=7, button=1, x=593, y=280, force=true,
toSourceOnly=true) at gui.cpp:687
#8 0x00007f9be43c5448 in gcn::Gui::handleModalFocusGained (this=0x1052fc0)
at gui.cpp:939
#9 0x00007f9be43c49d5 in gcn::Gui::handleModalMouseInputFocus (this=0x1052fc0)
at gui.cpp:891
#10 0x00007f9be43c6157 in gcn::Gui::logic (this=0x1052fc0) at gui.cpp:139
#11 0x00007f9be5e13c40 in FIFE::GUIManager::turn (this=0x1052c20)
at engine/core/gui/guimanager.cpp:223
#12 0x00007f9be5dda3f3 in FIFE::Engine::pump (this=0xe84ca0)
at engine/core/controller/engine.cpp:298
#13 0x00007f9be5fa718e in _wrap_Engine_pump (args=0x4572c10)
at engine/swigwrappers/python/fife_wrap.cxx:24383
---Type <return> to continue, or q <return> to quit---
#14 0x0000000000417e33 in PyObject_Call ()
#15 0x0000000000487073 in PyEval_EvalFrameEx ()
#16 0x000000000048a406 in PyEval_EvalCodeEx ()
#17 0x0000000000488075 in PyEval_EvalFrameEx ()
#18 0x0000000000488c07 in PyEval_EvalFrameEx ()
#19 0x000000000048a406 in PyEval_EvalCodeEx ()
#20 0x0000000000488075 in PyEval_EvalFrameEx ()
#21 0x000000000048a406 in PyEval_EvalCodeEx ()
#22 0x0000000000488075 in PyEval_EvalFrameEx ()
#23 0x000000000048a406 in PyEval_EvalCodeEx ()
#24 0x00000000004d5223 in ?? ()
#25 0x0000000000417e33 in PyObject_Call ()
#26 0x0000000000487073 in PyEval_EvalFrameEx ()
#27 0x000000000048a406 in PyEval_EvalCodeEx ()
#28 0x0000000000488075 in PyEval_EvalFrameEx ()
#29 0x000000000048a406 in PyEval_EvalCodeEx ()
#30 0x0000000000488075 in PyEval_EvalFrameEx ()
#31 0x0000000000488c07 in PyEval_EvalFrameEx ()
#32 0x000000000048a406 in PyEval_EvalCodeEx ()
#33 0x00000000004d528a in ?? ()
#34 0x0000000000417e33 in PyObject_Call ()
#35 0x000000000041e66f in ?? ()
#36 0x00000000004191aa in ?? ()
---Type <return> to continue, or q <return> to quit---
#37 0x000000000041b090 in PyObject_CallMethod ()
#38 0x00007f9be5ebe6ca in SwigDirector_ActionListener::action (this=0x11eebd0,
actionEvent=@0x7fffef936c40)
at engine/swigwrappers/python/fife_wrap.cxx:7239
#39 0x00007f9be43ccf4e in gcn::Widget::distributeActionEvent (this=0x11ee150)
at widget.cpp:713
#40 0x00007f9be43cf901 in gcn::Button::mouseReleased (this=0x11ee150,
mouseEvent=@0x7fffef936d10) at button.cpp:238
#41 0x00007f9be43c6f29 in gcn::Gui::distributeMouseEvent (this=0x1052fc0,
source=0x597d710, type=<value optimized out>,
button=<value optimized out>, x=672, y=339, force=false,
toSourceOnly=false) at gui.cpp:746
#42 0x00007f9be43c4c74 in gcn::Gui::handleMouseReleased (this=0x1052fc0,
mouseInput=@0x7fffef936e30) at gui.cpp:600
#43 0x00007f9be43c7314 in gcn::Gui::handleMouseInput (this=0x1052fc0)
at gui.cpp:234
#44 0x00007f9be43c617b in gcn::Gui::logic (this=0x1052fc0) at gui.cpp:146
#45 0x00007f9be5e13c40 in FIFE::GUIManager::turn (this=0x1052c20)
at engine/core/gui/guimanager.cpp:223
#46 0x00007f9be5dda3f3 in FIFE::Engine::pump (this=0xe84ca0)
at engine/core/controller/engine.cpp:298
#47 0x00007f9be5fa718e in _wrap_Engine_pump (args=0x14a48d0)
at engine/swigwrappers/python/fife_wrap.cxx:24383
---Type <return> to continue, or q <return> to quit---
#48 0x0000000000417e33 in PyObject_Call ()
#49 0x0000000000487073 in PyEval_EvalFrameEx ()
#50 0x000000000048a406 in PyEval_EvalCodeEx ()
#51 0x0000000000488075 in PyEval_EvalFrameEx ()
#52 0x0000000000488c07 in PyEval_EvalFrameEx ()
#53 0x000000000048a406 in PyEval_EvalCodeEx ()
#54 0x0000000000488075 in PyEval_EvalFrameEx ()
#55 0x000000000048a406 in PyEval_EvalCodeEx ()
#56 0x0000000000488075 in PyEval_EvalFrameEx ()
#57 0x000000000048a406 in PyEval_EvalCodeEx ()
#58 0x00000000004d5223 in ?? ()
#59 0x0000000000417e33 in PyObject_Call ()
#60 0x0000000000487073 in PyEval_EvalFrameEx ()
#61 0x000000000048a406 in PyEval_EvalCodeEx ()
#62 0x0000000000488075 in PyEval_EvalFrameEx ()
#63 0x000000000048a406 in PyEval_EvalCodeEx ()
#64 0x0000000000488075 in PyEval_EvalFrameEx ()
#65 0x0000000000488c07 in PyEval_EvalFrameEx ()
#66 0x000000000048a406 in PyEval_EvalCodeEx ()
#67 0x00000000004d528a in ?? ()
#68 0x0000000000417e33 in PyObject_Call ()
#69 0x000000000041e66f in ?? ()
#70 0x00000000004191aa in ?? ()
---Type <return> to continue, or q <return> to quit---
#71 0x000000000041b090 in PyObject_CallMethod ()
#72 0x00007f9be5ebe6ca in SwigDirector_ActionListener::action (this=0x1205230,
actionEvent=@0x7fffef938d80)
at engine/swigwrappers/python/fife_wrap.cxx:7239
#73 0x00007f9be43ccf4e in gcn::Widget::distributeActionEvent (this=0x12047b0)
at widget.cpp:713
#74 0x00007f9be43cf901 in gcn::Button::mouseReleased (this=0x12047b0,
mouseEvent=@0x7fffef938e50) at button.cpp:238
#75 0x00007f9be43c6f29 in gcn::Gui::distributeMouseEvent (this=0x1052fc0,
source=0x1a91260, type=<value optimized out>,
button=<value optimized out>, x=399, y=232, force=false,
toSourceOnly=false) at gui.cpp:746
#76 0x00007f9be43c4c74 in gcn::Gui::handleMouseReleased (this=0x1052fc0,
mouseInput=@0x7fffef938f70) at gui.cpp:600
#77 0x00007f9be43c7314 in gcn::Gui::handleMouseInput (this=0x1052fc0)
at gui.cpp:234
#78 0x00007f9be43c617b in gcn::Gui::logic (this=0x1052fc0) at gui.cpp:146
#79 0x00007f9be5e13c40 in FIFE::GUIManager::turn (this=0x1052c20)
at engine/core/gui/guimanager.cpp:223
#80 0x00007f9be5dda3f3 in FIFE::Engine::pump (this=0xe84ca0)
at engine/core/controller/engine.cpp:298
#81 0x00007f9be5fa718e in _wrap_Engine_pump (args=0xe3f190)
at engine/swigwrappers/python/fife_wrap.cxx:24383
---Type <return> to continue, or q <return> to quit---
#82 0x0000000000417e33 in PyObject_Call ()
#83 0x0000000000487073 in PyEval_EvalFrameEx ()
#84 0x000000000048a406 in PyEval_EvalCodeEx ()
#85 0x0000000000488075 in PyEval_EvalFrameEx ()
#86 0x0000000000488c07 in PyEval_EvalFrameEx ()
#87 0x0000000000488c07 in PyEval_EvalFrameEx ()
#88 0x0000000000488c07 in PyEval_EvalFrameEx ()
#89 0x000000000048a406 in PyEval_EvalCodeEx ()
#90 0x000000000048a522 in PyEval_EvalCode ()
#91 0x00000000004abe2e in PyRun_FileExFlags ()
#92 0x00000000004ac0c9 in PyRun_SimpleFileExFlags ()
#93 0x00000000004145ad in Py_Main ()
#94 0x00007f9be6b341c4 in __libc_start_main () from /lib/libc.so.6
#95 0x0000000000413b29 in _start ()
(gdb)
Original comment by geto...@googlemail.com
on 27 Mar 2009 at 7:47
Let me clarify: The issue is that in FIFE synchronous execution of dialogs is
handled
via recursion of the main loop. The Gui logic function isn't robust enough for
that.
A fix is pending where events won't get called directly from inside event
handlers
but deferred by one frame.
That should close this issue.
Original comment by klaus.bl...@web.de
on 27 Mar 2009 at 10:43
Original issue reported on code.google.com by
thenetce...@gmail.com
on 24 Jul 2008 at 10:49