[I also submitted this to the RFE section on sourceforge.net, but it
looks like that isn't really being monitored.]
Hello,
I felt the need to be able to write a GTK application for which the
main window is an epplet window. I tried several ways in which I could
mix the epplet events and the GTK event loop handler, but couldn't
come up with something that worked well.
To fix this, I have made some modifications to the epplets 0.7 API
code that allow one to run a single iteration of the main epplet loop
(Epplet_Loop) in a non-blocking mode. This means that I can call that
iteration from a GTK timer, and have it all work, more or less,
correctly.
To be able to deal with epplet timers in this setup, I also had to
change the way they worked. In fact, I think they work better now, and
I believe the code is actually easier to understand.
The changes should be backward compatible, i.e. no programs compiled
against 0.7 should need changes, or should display changes in
behaviour. There is a single new API function
(Epplet_Loop_Iteration(int block)), which takes a single argument
specifying whether the iteration should block or not.
I have tried to keep the code formatting as close to the original as
possible, although it is not my own coding style, so I might have
missed a space or indent here or there.
I will attach two (uni)diffs, one against api/epplet.c and one against
api/epplet.h.in, which reflect these changes.
Regards,
Martien
--
Martien Verbruggen |
IS Manager | The world is complex; sendmail.cf reflects
Trading Post Australia | this.
Tel: +61 2 9860 9139 |
--- epplets-0.7-orig/api/epplet.c 2003-04-07 11:02:18.000000000 +1000
+++ epplets-0.7/api/epplet.c 2004-04-18 20:10:40.000000000 +1000
@@ -122,7 +122,7 @@
void (*func) (void *data);
void *data;
double in;
- char just_added;
+ double when;
ETimer *next;
};
@@ -1470,7 +1470,6 @@
Epplet_timer(void (*func) (void *data), void *data, double in, char *name)
{
ETimer *et, *ptr, *pptr;
- double tally;
Epplet_remove_timer(name);
et = malloc(sizeof(ETimer));
@@ -1478,31 +1477,23 @@
et->func = func;
et->data = data;
et->name = malloc(strlen(name) + 1);
- et->just_added = 1;
- et->in = in;
+ et->when = Epplet_get_time() + in;
memcpy(et->name, name, strlen(name) + 1);
- tally = 0.0;
if (!q_first)
q_first = et;
else
{
pptr = NULL;
ptr = q_first;
- tally = 0.0;
while (ptr)
{
- tally += ptr->in;
- if (tally > in)
+ if (et->when < ptr->when)
{
- tally -= ptr->in;
et->next = ptr;
if (pptr)
pptr->next = et;
else
q_first = et;
- et->in -= tally;
- if (et->next)
- et->next->in -= et->in;
return;
}
pptr = ptr;
@@ -1512,7 +1503,6 @@
pptr->next = et;
else
q_first = et;
- et->in -= tally;
}
}
@@ -1532,8 +1522,6 @@
pptr->next = et->next;
else
q_first = et->next;
- if (et->next)
- et->next->in += et->in;
if (et->name)
free(et->name);
if (et)
@@ -1572,11 +1560,11 @@
return;
et = q_first;
q_first = q_first->next;
+
(*(et->func)) (et->data);
- if (et && et->name)
+ if (et->name)
free(et->name);
- if (et)
- free(et);
+ free(et);
}
double
@@ -1667,87 +1655,93 @@
}
void
-Epplet_Loop(void)
+Epplet_Loop_Iteration(int block)
{
- int xfd, fdsize, count;
- double t1 = 0.0, t2 = 0.0, pt;
+ XEvent *evs = NULL;
+ int evs_num = 0, i;
+
+ double t1, now = Epplet_get_time();
+ int count;
ETimer *et;
fd_set fdset;
- struct timeval tval;
- xfd = ConnectionNumber(disp);
- fdsize = xfd + 1;
- pt = Epplet_get_time();
- for (;;)
- {
- XEvent *evs = NULL;
- int evs_num = 0, i;
+ static int xfd, fdsize, initialised = 0;
- XFlush(disp);
- t1 = Epplet_get_time();
- t2 = t1 - pt;
- pt = t1;
- while (XPending(disp))
- {
- evs_num++;
- if (evs)
- evs = realloc(evs, sizeof(XEvent) * evs_num);
- else
- evs = malloc(sizeof(XEvent));
- XNextEvent(disp, &(evs[evs_num - 1]));
- }
- if (evs)
- {
- Epplet_prune_events(evs, evs_num);
- for (i = 0; i < evs_num; i++)
- {
- if (evs[i].type > 0)
- Epplet_handle_event(&(evs[i]));
- }
- free(evs);
- evs = NULL;
- evs_num = 0;
- }
- XFlush(disp);
- FD_ZERO(&fdset);
- FD_SET(xfd, &fdset);
- et = Epplet_get_first();
- count = 0;
- if (et)
- {
- if (et->just_added)
- {
- et->just_added = 0;
- t1 = et->in;
- }
- else
- {
- t1 = et->in - t2;
- if (t1 < 0.0)
- t1 = 0.0;
- et->in = t1;
- }
- tval.tv_sec = (long)t1;
- tval.tv_usec = (long)((t1 - ((double)tval.tv_sec)) * 1000000);
- if (tval.tv_sec < 0)
- tval.tv_sec = 0;
- if (tval.tv_usec <= 1000)
- tval.tv_usec = 1000;
- count = select(fdsize, &fdset, NULL, NULL, &tval);
+ if (!initialised)
+ {
+ xfd = ConnectionNumber(disp);
+ fdsize = xfd + 1;
+ initialised = 1;
+ }
+
+ XFlush(disp);
+ while (XPending(disp))
+ {
+ evs_num++;
+ if (evs)
+ evs = realloc(evs, sizeof(XEvent) * evs_num);
+ else
+ evs = malloc(sizeof(XEvent));
+ XNextEvent(disp, &(evs[evs_num - 1]));
+ }
+ if (evs)
+ {
+ Epplet_prune_events(evs, evs_num);
+ for (i = 0; i < evs_num; i++)
+ {
+ if (evs[i].type > 0)
+ Epplet_handle_event(&(evs[i]));
+ }
+ free(evs);
+ evs = NULL;
+ evs_num = 0;
+ }
+ XFlush(disp);
+
+ FD_ZERO(&fdset);
+ FD_SET(xfd, &fdset);
+ count = 0;
+
+ /* If there's a timer, see whether it needs executing */
+ et = Epplet_get_first();
+ while (et && et->when < now)
+ {
+ Epplet_handle_timer();
+ et = Epplet_get_first();
+ }
+
+ if (block)
+ {
+ /* If there are still any timers, we should block until the next
+ * one expires */
+ if (et)
+ {
+ struct timeval tval;
+ t1 = et->when - now;
+ tval.tv_sec = (long)t1;
+ tval.tv_usec = (long)((t1 - ((double)tval.tv_sec)) * 1000000);
+ if (tval.tv_sec < 0)
+ tval.tv_sec = 0;
+ if (tval.tv_usec <= 1000)
+ tval.tv_usec = 1000;
+ count = select(fdsize, &fdset, NULL, NULL, &tval);
}
else
count = select(fdsize, &fdset, NULL, NULL, NULL);
- if (count < 0)
- {
- if ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF))
- exit(1);
- }
- else
- {
- if ((et) && (count == 0))
- Epplet_handle_timer();
- }
- }
+ }
+
+ if (count < 0)
+ {
+ if ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF))
+ exit(1);
+ }
+}
+
+void
+Epplet_Loop(void)
+{
+ for (;;)
+ Epplet_Loop_Iteration(1);
}
static void
--- epplets-0.7-orig/api/epplet.h.in 2000-06-30 09:54:24.000000000 +1000
+++ epplets-0.7/api/epplet.h.in 2004-04-18 20:11:15.000000000 +1000
@@ -171,6 +171,7 @@
/* the epplet main loop - once you've set up and showed your epplet window */
/* call this */
void Epplet_Loop(void);
+void Epplet_Loop_Iteration(int block);
/* call the function func with data as its data param whenever an expose */
/* happens and needs to be handled */