[XForms] client event sample application
Jeff
wd4nmq at comcast.net
Sat Apr 3 01:42:42 EST 2004
Below is an appliaction that uses the fl_register_client_callback() and
demonstrates why atoms are needed. As asked for by Angus I believe.
A quick explanation on why atoms are needed.
When a client callback is called, all it gets is a pointer to an XEvent
structure and all it knows is it is a ClientMessage. It has no idea how
the data is formatted. This is where an atom comes into play. An atom is
registered with the XInternAtom() call. This atom is then put into
effect for the whole X display, like 0:0. Now, any app or thread running
in display 0:0 can use that atom.
In my demo below I have a text widget that the time is displayed in. The
actual time is read from the system in a thread. The time is sent as
either a long, or as a pointer to a time struct. These alternate every
second.
Now, to demonstate how atoms are used I create two atoms, timeStructAtom
& longTimeAtom. if the time data is a long, longTimeAtom is used. If it
is a pointer to time struct, timeStructAtom is used. Now the client
callback can decide how the time is encoded and act appropiatly to
display it.
Remember, there can be only ONE user ClientMessage callback for an app.
So atoms are important in letting the callback know how the data is
formatted.
The code:
#include "forms.h"
#include <stdlib.h>
#include "timeEvent.h"
#include <time.h>
#include <pthread.h>
Atom longTimeAtom, timeStructAtom;
pthread_t getTimeThread;
FD_testEvent *fd_testEvent;
FD_testEvent *create_form_testEvent(void)
{
FL_OBJECT *obj;
FD_testEvent *fdui = (FD_testEvent *) fl_calloc(1, sizeof(*fdui));
fdui->testEvent = fl_bgn_form(FL_NO_BOX, 420, 250);
obj = fl_add_box(FL_UP_BOX,0,0,420,250,"");
fdui->timeText = obj = fl_add_text(FL_NORMAL_TEXT,30,90,350,60,"");
fl_set_object_boxtype(obj,FL_SHADOW_BOX);
fl_set_object_lsize(obj,FL_HUGE_SIZE);
fl_set_object_lalign(obj,FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
fl_end_form();
fdui->testEvent->fdui = fdui;
return fdui;
}
/*---------------------------------------*/
FL_CLIENT_CALLBACK clientCallback(FL_FORM *form, XEvent *xev){
char line[128];
// Use message_type to decide how time is encoded
if(xev->xclient.message_type == longTimeAtom){
fl_set_object_label(fd_testEvent->timeText,
ctime(&xev->xclient.data.l[0]));
}
else if(xev->xclient.message_type == timeStructAtom){
strftime(line,128, "%a %b %d %H:%M:%S %Y",xev->xclient.data.l[0]);
fl_set_object_label(fd_testEvent->timeText, line);
}
}
/*******************************************/
int timerThread(void *ptr){
time_t the_time;
struct tm *tm_ptr;
XEvent xev;
sleep(3); // long timeout first time
while(1){
the_time = time((time_t *)0);
if(the_time & 0x0001){
xev.xclient.type = ClientMessage;
xev.xclient.window = fl_get_winID(fd_testEvent->testEvent);
xev.xclient.message_type = longTimeAtom;
xev.xclient.format = 16;
xev.xclient.data.l[0] = the_time;
}
else {
tm_ptr = localtime(&the_time);
xev.xclient.type = ClientMessage;
xev.xclient.window = fl_get_winID(fd_testEvent->testEvent);
xev.xclient.message_type = timeStructAtom;
xev.xclient.format = 16;
xev.xclient.data.l[0] = (long)tm_ptr;
}
XSendEvent(fl_display,
fl_get_winID(fd_testEvent->testEvent),
False, 0l, &xev);
sleep(1);
}
}
/*************************************/
int main(int argc, char *argv[])
{
int rtn;
fl_initialize(&argc, argv, 0, 0, 0);
fd_testEvent = create_form_testEvent();
longTimeAtom = XInternAtom(fl_display, "Long Time", FALSE);
timeStructAtom = XInternAtom(fl_display, "Time Pointer", FALSE);
fl_register_client_callback(fd_testEvent->testEvent, clientCallback);
/* fill-in form initialization code */
/* show the first form */
fl_show_form(fd_testEvent->testEvent,FL_PLACE_CENTERFREE,
FL_FULLBORDER,"testEvent");
rtn = pthread_create(&getTimeThread,
NULL,
(void *) timerThread,
NULL);
fl_do_forms();
return 0;
}
// End of code
Now, since the code to update the time widget is running in the gui code
space, and not the thread actually getting the time. There are no
conflicts for the internal xforms code to write the form. You can use
fl_do_forms() instead of fl_check_forms() and have to have mutexes for
threads to be able to update a form. I believe this is much cleaner.
Well, it's 1:30 am local and I am hitting the sack.
Jeff
More information about the Xforms
mailing list