In my gui library, I'd like to allow widgets to start timers, put user events in an event queue, and put custom expose events in the associated display's event queue.

In order to allow widgets to start timers, widgets must have an ALLEGRO_EVENT_QUEUE* member in order to register the timer's event source to the queue.

In order to allow widgets to send user events, widgets must have an ALLEGRO_EVENT_SOURCE* member in order to use the function 'al_emit_user_event'.

In order to allow widgets to put custom expose events, widgets must have an ALLEGRO_DISPLAY* member (according to this thread).

Now my question is this: how to avoid having all these members in my widgets? is there a way in Allegro 5 to have a single pointer to <something> in a widget and do all the above? if so, what is this <something>? a queue? an event source?

I didn't like passing allegro events directly to my object based framework. Instead I have a bunch of methods that handle different events. The event objects themselves do take an ALLEGRO_EVENT to populate itself though.

is there a way in Allegro 5 to have a single pointer to <something> in a widget and do all the above? if so, what is this <something>? a queue? an event source?

No, I'm not really sure how you expect that it would work in C. Or maybe I don't even understand what you're asking.

I haven't done much with Allegro events in my GUI. I don't use them internally because I use my own function-based event system. However, externally, I will probably give the programmer an option to use Allegro events.

Regarding a display pointer, I don't associate widgets directly with displays. If I really needed to know what display a widget was on, I'd have to travel up the parent nodes until I got to the root object, and then check which display owned it by a display/root pair I maintain.

For example, on a mouse move event, I cycle through each root widget owned by the display. Each widget asks itself "what widget is at X,Y" recursively until it finds its top most widget. So I always know what the display is without explicitly storing it per widget.

But I haven't implemented any optimization. If I ever get to that point, I may rethink a few things.

Matthew, how does your GUI library handle redrawing? do you redraw the whole GUI at each frame update?

If I wanted to use your GUI not for a game, but for an application, I would not like to have my GUI being redrawn at every frame. So, in order to achieve this, I would have to manage expose events. But, in order to send expose events from widgets, I need to have a pointer to a display in each widget (or an association between a widget and a display, like the one you describe).

Now, normally, this isn't a problem. But, when I want to handle timers in widgets, each widget should also have a pointer to the event queue that will be associated with the timer.

Finally, if I want my widget to send events to an event queue, each widget must have a pointer to an event source.

Let me repeat the above in short form:

if I want my widgets to send expose events, each widget must have access to an ALLEGRO_DISPLAY pointer.

if I want my widgets to handle timer events, each widget must have access to an ALLEGRO_EVENT_QUEUE pointer, so as that the timer that is created by the widget is registered to the event queue.

if i want my widgets to send user events, each widget must have access to an ALLEGRO_EVENT_SOURCE pointer.

By the way, the above problem leads me to think that the Allegro 5 event system is not designed correctly. The core of the problem is al_emit_user_event. What is wrong with it is that user events can only be emitted on an event source. The right approach would be to put events in the event queue. If A5 was like that, I would only need this:

What if you want to send events to multiple queues? That's why Allegro is designed the way it is, so I wouldn't call it incorrect. Essentially, Allegro is providing the convenience layer to the owner of the event source, such that it simply has to emit an event into its source and not worry if anybody is listening.

However, I don't think it would be hard to add al_push_event(ALLEGRO_EVENT_QUEUE*queue, ALLEGRO_EVENT*event); to A5's internals as an alternative way to populate a queue.

I redraw the entire GUI double buffered, without optimization, on every frame. This is mostly because I'm too lazy to do anything else, as opposed to any master plan. I cannot imagine that my GUI would ever end up being useful for high speed, full screen games. It is primarily designed for tool building and not real time games, so I don't really care.

I have made use of multiple things listening to the same event source on Allegro, if that's what you mean. And with HTML/JS, I do it a lot.

Could you simply pass an event source to the widget? i.e., void Widget::setEventSource(ALLEGRO_EVENT_SOURCE*s); If it is 1:1 with an event queue, it's the same thing, from the widget's perspective. If you build your source like:

I don't think this is the best way to go about it. Why not make a global timer used by the entire GUI? Set it to the monitor's refresh rate and forget it. Have the user pass the delta time into a widget's update function after reading the timer events. The user will most likely create a timer at the refresh rate of the monitor anyway, and then they can just pass the delta time in.

That is so much simpler than making every widget own a timer, and event queue.

As for your expose events, it looks like Matthew's patch should take care of that for you. Wouldn't the display have to be using double buffering to make that work for you though? If it used page flipping, you would be forced to fully redraw everything every frame anyway. My A4 GUI uses a BITMAP buffer for each WidgetHandler, and it uses dirty rectangles, only updating the widgets that need to be redrawn. So it blits its buffer every time you call display, but doesn't necessarily redraw every widget.

My A4 GUI uses a BITMAP buffer for each WidgetHandler, and it uses dirty rectangles, only updating the widgets that need to be redrawn. So it blits its buffer every time you call display, but doesn't necessarily redraw every widget.

1) There is no need to use bitmaps in A4 when using a dirty rectangle system. I've done GUIs in A4 with dirty rectangles that simply told widgets to redraw the dirty rectangles.

2) I am not planning to use a dirty rectangle system, it's not required. All I want is to redraw a specific part of the GUI and not the whole GUI.

Here is how I decided to do it: A class GUI will hold the global context of a GUI, including display and queue. Then, the root widget will have to be initialized with this GUI class, like this:

1) Because Widgets shouldn't have update() functions. Remember, you spoke of clean and organized APIs in another thread.

If you want animated widgets, they should have an update function. Having a default base class update function that does nothing adds zero overhead. It is a perfectly clean and organized solution to have only the widgets that need delta time do something with it. If your user is too lazy / brain dead to use a timer and pass SECONDS_PER_TICK to a top level gui widget, that's really pathetic and they deserve for animations not to work.

axilmar said:

2) Because I wouldn't want to dispatch the timer event to every widget in a widget tree. I'd like to dispatch it to the widget that created the timer.

How do you plan to distinguish which widgets get which events? Isn't it better to let them decide whether they want to deal with an event?

axilmar said:

3) Because different widgets would have different timer periods, often incompatible between them.

Are you really going to need widgets that have timers faster than the refresh rate of the monitor?. I imagine widgets like that would be pretty rare and in that case then they should have their own timer built in. You would still need a way to detect widgets like this and have them check their inputs more often than the rest of the widgets.

axilmar said:

4) because I don't like the user of my library to not get blinking cursors if he/she doesn't handle the timer event in his/her event queue.

So instead of asking the user to do one tiny little thing, you would make your library more complicated and bloated by making all of your widgets have their own timers?

axilmar said:

1) There is no need to use bitmaps in A4 when using a dirty rectangle system. I've done GUIs in A4 with dirty rectangles that simply told widgets to redraw the dirty rectangles.

In A4, buffers are quite useful, and prevent the need for an entire panel of widgets to be redrawn at once. Buffers also allow the user to redraw the entire gui at once if part of the screen has been changed.

axilmar said:

2) I am not planning to use a dirty rectangle system, it's not required. All I want is to redraw a specific part of the GUI and not the whole GUI.

What are you going to do if A5 is using page flipping internally? The screen will get out of sync with what it is supposed to be displaying.

Animation can be achieved on a per widget basis. There is no need for a global system, because only one widget will be animated at a time.

Quote:

Having a default base class update function that does nothing adds zero overhead.

The update mechanism adds overhead. Having a timer, i.e. a thread, wake up 60 frames per second, i.e. every 16 milliseconds, when all I want is a blinking cursor every one second.

Quote:

It is a perfectly clean and organized solution to have only the widgets that need delta time do something with it.

It is not clean to have a function in the root class that only a few widgets will use.

Quote:

If your user is too lazy / brain dead to use a timer and pass SECONDS_PER_TICK to a top level gui widget, that's really pathetic and they deserve for animations not to work.

The user shouldn't have to initialize a timer in order for his GUI to work. It's better to automate the process.

Quote:

How do you plan to distinguish which widgets get which events? Isn't it better to let them decide whether they want to deal with an event?

Widgets that create timers will register themselves to their GUI object in order to receive timer events.

Quote:

Are you really going to need widgets that have timers faster than the refresh rate of the monitor?.

Not faster, slower. But when I need a blinking cursor with speed = 1000 milliseconds, 1000 is not divided accurately with 60.

Quote:

So instead of asking the user to do one tiny little thing, you would make your library more complicated and bloated by making all of your widgets have their own timers?

I am against making the user do anything except the absolutely necessary required to get his gui going. If that means making the library more complicated for me, then so be it. It will be easier for the user though.

Quote:

In A4, buffers are quite useful, and prevent the need for an entire panel of widgets to be redrawn at once.

Buffering is useless when widgets need to be redrawn. Why waste resources when the screen needs to be updated? drawing onto a buffer and then blitting the buffer to the screen spends resources that wouldn't be spent if the drawing happened directly to the destination bitmap (and then buffers were switched). And if you use memory bitmaps, you lose accelerated drawing.

Quote:

Buffers also allow the user to redraw the entire gui at once if part of the screen has been changed.

The same effect can be achieved by double buffering.

Quote:

What are you going to do if A5 is using page flipping internally? The screen will get out of sync with what it is supposed to be displaying.

Not at all. The event EXPOSE contains the area that is to be updated, and so I will redraw the appropriate widgets inside that area, as needed.

Buffering is useless when widgets need to be redrawn. Why waste resources when the screen needs to be updated? drawing onto a buffer and then blitting the buffer to the screen spends resources that wouldn't be spent if the drawing happened directly to the destination bitmap (and then buffers were switched). And if you use memory bitmaps, you lose accelerated drawing.

If you draw directly to the screen, you will have flickering images whenever an object needs to draw over itself or have it's background redrawn. You can use memory or video bitmaps if you like, I never said the user was forced to use one or another.

axilmar said:

Edgar said:

Buffers also allow the user to redraw the entire gui at once if part of the screen has been changed.

The same effect can be achieved by double buffering.

Why would you want to redraw every single widget when you could just blit a stored copy of the gui panel into place as necessary?

axilmar said:

Not at all. The event EXPOSE contains the area that is to be updated, and so I will redraw the appropriate widgets inside that area, as needed.

The EXPOSE event may tell you what part of the screen is dirty, but if A5 is using page flipping and you update one page and flip, that update is lost on the second page.

axilmar said:

The update mechanism adds overhead. Having a timer, i.e. a thread, wake up 60 frames per second, i.e. every 16 milliseconds, when all I want is a blinking cursor every one second.

Premature optimization anyone? The overhead added by an update function is completely negligible. If your timer is running at 60Hz, then you will never be more than 1/60 of a second behind the actual time you wanted. No human can even tell the difference between 60/60 and 61/60 of a second.

axilmar said:

It is not clean to have a function in the root class that only a few widgets will use.

Of course it is. Only the widgets that actually use the update function will ever redefine it. The rest of the widgets don't have to do a single thing with it.

I really just disagree with you on this. This all works perfectly fine in my GUI, and adding in 5-10 lines of timer code is not too much to ask a user to do if they want animations.

Animation can be achieved on a per widget basis. There is no need for a global system, because only one widget will be animated at a time.

Why make the limitation of one animation at a time? Sure you don't need a global animation system, but Qt manages it with Animation classes that you tie to various properties on a widget, and the Animation class handles the animation (which I assume registers a timer event for itself).

If you draw directly to the screen, you will have flickering images whenever an object needs to draw over itself or have it's background redrawn.

You also have flickering if you use per-widget bitmaps - the drawing operation then becomes the blitting of the widget bitmap to the screen.

Buffering widgets does not work like that (i.e. one bitmap per widget). It works with a background bitmap that all widgets are drawn onto, and then the final result is displayed, either via page flipping or blitting.

Quote:

Why would you want to redraw every single widget when you could just blit a stored copy of the gui panel into place as necessary?

Because bitmaps take a lot of memory, and you will usually have to redraw the bitmap anyway.

Quote:

The EXPOSE event may tell you what part of the screen is dirty, but if A5 is using page flipping and you update one page and flip, that update is lost on the second page.

Perhaps. I haven't seen it though, in my current demos. Which means that A5 doesn't use page flipping, it just blits the back buffer to the front buffer.

Quote:

Premature optimization anyone? The overhead added by an update function is completely negligible. If your timer is running at 60Hz, then you will never be more than 1/60 of a second behind the actual time you wanted. No human can even tell the difference between 60/60 and 61/60 of a second.

It's noticeable, because there are other delays too: the thread that implements the timer, the putting of event in the queue, the waking up of the thread etc. These may amount to more than 20 milliseconds, especially on Windows where the default timer accuracy is 10 milliseconds.

The main problem though is that a thread waking up every 16 milliseconds. It's a resource hog.

Quote:

Of course it is. Only the widgets that actually use the update function will ever redefine it. The rest of the widgets don't have to do a single thing with it.

But the whole widget tree will have to be notified every 16 milliseconds of the timer. Isn't that a performance issue?

Quote:

I really just disagree with you on this. This all works perfectly fine in my GUI, and adding in 5-10 lines of timer code is not too much to ask a user to do if they want animations.

Well, it may work for you, but if you try to do a simulation where the simulation state is updated every 100 milliseconds, and you have a thread waking up every 16 milliseconds, you will notice many hickups in the simulation thread.

I want to avoid any possible performance issues in my gui, since I'd like to use it in my simulations. Perhaps your needs are different, but even if they are, I don't see how saving up resources is a bad thing.

Because bitmaps take a lot of memory, and you will usually have to redraw the bitmap anyway.

Nope. Qt4 manages to speed up a lot of stuff using a back buffer for every widget. Turns out that much of the time, most widgets don't change much. And redrawing every complex widget every frame is a massive chunk of overhead. Primitives, especially ones with fancy features (Qt supports a wide range of Vector like drawing features in its primitive drawing api) are slower than you think they are. Even in Allegro 5 primitives are rather slow. Most of it is overhead in the graphics driver.

Using native windows for widgets also speeds things up, so it stopped doing that by default. They do use the platform's native drawing routines when possible to draw those widgets though, so themes tend to work.

If each window and each browser tab has one bitmap, we are talking about 30 bitmaps, which will consume 30 x 1650 x 1280 x 4 = 253440000 bytes, i.e. 241 MB.

Guess how much memory firefox and chrome use? many hundreds of MB. Even several GB if you let it get that far. I've seen both chrome and firefox use more than 2 GB.

append: though I think the default for Qt4 is to have one backbuffer for the top level window, and the widgets then render to a chunk of that. But each widget has the option of having its own back buffer IIRC.

You cannot do all graphical effects without a buffer. My GUI is a mess regarding this right now, but my goal is to support both buffered (as it does now) and unbuffered (sub-bitmaps or transformations) widgets at the programmer's own discretion.

In case you want an example of that "Painter" stuff, I implemented a simple Painter/PaintEngine setup in my Canva5 library. Its rather simple and doesn't do any caching (yet). But adding a cached version of objects would likely speed up the rendering of simple objects significantly (especially if the pixmaps were cached in atlases). The overhead of calling things like al_draw_circle hundreds of times is enormous.

You also have flickering if you use per-widget bitmaps - the drawing operation then becomes the blitting of the widget bitmap to the screen.

Buffering widgets does not work like that (i.e. one bitmap per widget). It works with a background bitmap that all widgets are drawn onto, and then the final result is displayed, either via page flipping or blitting.

That's the kind of buffering I was talking about - my WidgetHandler (gui / panel / window) class has two bitmaps, one background bitmap and one buffer bitmap. The background is redrawn as necessary and then the necessary widgets are drawn, but almost never all of them are redrawn at once. Having a buffer allows the user to change as much of the back buffer as he wants to without having to make every widget redraw itself all over again. Why redraw more than once when you don't have to?

Because bitmaps take a lot of memory, and you will usually have to redraw the bitmap anyway....If each window and each browser tab has one bitmap, we are talking about 30 bitmaps, which will consume 30 x 1650 x 1280 x 4 = 253440000 bytes, i.e. 241 MB.

And with 2GB being the standard normal amount of memory in a system these days, that's still only about 12% of the systems memory, which isn't that much.

But the whole widget tree will have to be notified every 16 milliseconds of the timer. Isn't that a performance issue?

1,000 widgets * 60 updates per second = 60,000 function calls per second. That's not all that much for today's processors to handle. And 1,000 widgets is kind of ridiculous anyway, more like one or two hundred. Don't optimize until you identify a bottleneck.