A simple alternative is that often you just want to call yourself later. That is, register a timer which when it expires, will call the given function which you give when you register the timer. It can be a one-shot or a repeating timer.
In my conception of the event queue, each event has a timestamp indicating when it has to be dispatched. So an event can be inserted in the queue before already present events.
> b) (which is related) Since a function call results > from an event, you can't generate an event whose > callback needs the end of > the event-generating-computation (i.e. it's not > asynchronous). > > I'd rather like to finish a computation which generates > an event before processing it. If you generate the event and put it in the queue, it will be processed later when the code gets around to checking the queue, right?
Yes. The code could be a scheduler (provided by the library) or user code.
> c) Also, say you want to code "When the left mouse button > is pressed (elsewhere than above my two main widgets), > make the first widget be blue and the second one be red.". > (Call this the blue-red exemple for later reuse.) > You'll need to register a callback on the background widget. > This callback needs to access (to be aware of) the two > other widgets. I don't like this. Whereas in an immediate mode UI, the main "do" function is both finding out that the button is pressed, and drawing the blue and red widgets directly right?
I guess so.
An alternative way to get this behavior with callbacks would be to make it possible for every widget to register interest in any kind of event, whether or not it would seem relevant to that widget. The callback can have an extra parameter to indicate the relevance. So a normal button registers only for a click event on himself, and your special button registers for a click event anywhere, and is given a "true" when the click is on him, and a "false" if it's somewhere else, along with coordinates etc. Or maybe your special button does two registrations of two different callbacks so that the parameter is not necessary...
The first part of your description sticks to my idea. Hwever, when you say 'the widget registers interest', I would say 'you register a callback that will only cares of one widget'. So to implement the button, I would make a handler for 'left-mouse-button-pressed which insert a new event, 'that-button-clicked. This step could be hidden for the user of the GUI.
> "My" Idea. > > I call it mine but I don't know .. maybe it's as old > as the world ? > > - The callback mechanism is exposed and made not mandatory. > - The widgets are aware of events, not the contrary > (see c) above). > - The event facility can be used for application-generated > events. > - The ol'callback way is still available. > > > How. > > An event-queue keeps the not-yet-processed events. > (For some application, it might be useful to timestamp > events so they are dispatched later or even keep the > already-processed events to be able to reverse time.) That's probably a really good idea. I think in general the trend is that as memory gets cheaper (RAM and disk both, and I believe they will be the same thing some day when nonvolatile RAM is cheap enough), you can find reasons to keep data around, timestamp it, take diffs, even build a sort of version control system for some classes of data, rather than assume that only the latest, most current data is relevant and letting new stuff overwrite old stuff. Especially, any text which the user enters himself ought to be considered sacred and never garbage-collected unless the user asks for it to be deleted. The book "The Humane Interface" makes this point. I was thinking a few years ago that a computer's disk ought to be structured as a giant log, where the data the user creates is appended to the log, and then data structures which the software creates to organize that data never duplicate it - they just point to it. The user enters a stream of data, and the computer makes sense of it over time. You would have built-in version control - edits are actually a special kind of diff that is appended to the log, so you will have the new version and the old version at the same time. Like CVS or subversion but implemented more efficiently. That is what early versions of the Xanadu project were about...but there is more than one way to implement it, and I can't make up my mind which is the best one (and neither could the Xanadu guys, which is why it never got done). Anyway I'm not sure that mouse events have the same kind of perennial lasting importance that text does, but in graphical documents, like diagrams, a persistent history would be nice, with unlimited undo and the ability to compare different versions. I want to build something like that when I get the GUI stuff done.
Interesting point. Although it was not clear, I was thinking of some functions to get events but also query the existence of a event. We could add the possibility to keep scheduled(processed) events. But in fact, I think it's appplication specific and I don't see if it would be really interesting; maybe would you prefer your own event data structure.
> For some event, the current state is kept. Exemple: > You might not want to have code run each time the > <enter> key is pressed but only want to be able to > query its state; is it pressed ? In the embedded system I described above I have a bitmask which keeps the state of every button. How else will I detect that it was just pressed, or just released, in order to generate an event? But in a PC keyboard the microcontroller would have to do something similar, and then it sends scan codes across the serial link to the PC. So you have to re-create the state of the enter key when an event occurs which indicates the state changed.
I'm not sure I understand this paragraph. Usually you receive different event for key-pressed and key-released. In my paragraph, I said you can both keep the timestamped event *and* the current state related to the event. If you poll not enough (not a sufficiently high rate) the current state, you can miss events (key-pressed then key-released: the state is 'released' and you didn't see the two events). But you might not care of events but only state, so the API should provide both.
> The base API let you test the existence of an event. > The test can be blocking or not. It can removes the > event from the queue or not. (The api has to be > extended so an event can be removed automatically > when every interested widget has already received it.) Are you sure you would want to have events removed from the queue, if you are depending on them to be there so that applications which started up after those events can still process them?
Sure, I'm not :) ... do you have an example in mind (not me) ?
> (This last point let you write the blue-red program: > the two widgets are aware of the events.) > > At this point, we have access to events. But how (when) > the code accessing the events is run ? How the gui > event-polling is done ? > > Here again we gain some flexibility. You can write > yourself a loop that calls one API function to > pump gui events then calls the event-testing-related > API functions. Testing the existence of an event is a search, isn't it? So you could have potentially hundreds of widgets all doing the same search over and over again to comb through the whole event queue and find out what is of interest to them? or at least combing through the "tail" of the event queue (and keeping track where they left off, so at the next polling cycle they know where to start). This is why registering a callback is a nice concept - when the event occurs, the main event handler can immediately build a list of callbacks that need to be notified, and then call them.
I've done no math but I believe that if you build a Callback abstraction on top of the low level part of the api you will not have that much events to search for.
On a multi-processor system the callbacks could even be simultaneous. If the red button expressed interest in receiving all mouse clicks then he will be notified at once (practically instantaneously) when the mouse is clicked, maybe even at the same time the blue button also gets notified.
I don't think so. GUI (user) event processing is unithreaded for me : a simple gui button has to see the press then the release of the mouse button; those two events have to be processed by the same thread. You can run multiple threads if those events are not related or you'll have to keep trak of shared information about those events.
> Or you can use an API function set > to let you register functions to be called regularly > (independently of events) and then launch an API- > provided main loop. Or register functions to > be called only for some specific events. > > Yep, we approached the well-known callback mechanism. Yeah maybe we're thinking pretty much the same. > To make it really feels like that, we can provide a > function which makes the widget generate an event What does that mean, the widget generating an event? Usually the user generates an event by clicking or moving or typing.
(Read above, I provide an example in this answer.)
> *and* register a callback for that specific event. > > By 'specific event', I mean an event has some kind > of name. When you register a function, you have to > say for which event names you want it to respond. > So the function I talked about in the previous > paragraph can generate a unique name so only *that* > widget and *that* callback are tied. Is a "name" really just a generated ID, or is it some kind of concatenation of an event ID, a widget ID and a callback?
Just a event type or kind. For example, 'key-pressed or 'mouse-button-released. So (this answer your question below too), a callback and a gui element can be related by a unique event name. No other callback would receive that event since the event name is generated when registering the callback for it and making the gui element send an event with that name. (I think Scheme has a gensym function for that.)
Would you say that every widget has to create its own callbacks
yes
or you'd have a globally unique, generated widget ID which is passed as a parameter to the callbacks, so that the callbacks can service multiple widgets?
yes too but the event is passed to callback that are registered for that/those event name(s).
(This is an ancient Java AWT thing - is it OK sometimes to have one button handler for several buttons, or do you have to create new ones for each? If you share the handler, then you have to have some if's inside to decide which button was pressed. Worse yet, the callback included only the string that labeled the button, so the if's would be doing string comparisons. But before anonymous inner classes were added to the language, it was hard to write separate handlers for every button. Now both ways are still possible, as far as I know.)
Sorry for responding so late but I knew I would have some time to answer correctly. Thanks for the discussion, thu _______________________________________________ Chicken-users mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/chicken-users
