[XForms] Client Message handler success.

Jeff wd4nmq at comcast.net
Mon Mar 15 00:50:45 EST 2004


Angus and Jean-marc,

(Lets try this using my registered email account :-), Sorry)

I have the code working to allow for a user supplied callback to handle 
ClientMessage XEvents.

It was actually very little code to change. Just tracing the code to 
find where to put it was a royal pain .

I quick synopsis.

XClient messages are used as an XEvent message that has user defined 
data. Refer to XLib documents for the CLient message data structure. 
Now, the present xforms seems to use client messages for forms to 
destroy other forms and use the WM_PROTOCOLS and WM_DELETE_WINDOW X 
atoms to specify that action. And of course, you can use user defined 
atoms. If the message_type is not these, the client message is passed to 
any other forms in the forms list.

Now, I do not understand why if the client message is not WM_PROTOCOLS, 
etc, it is  passed on. The whole purpose of XSendEvent with 
ClientMessage is to  send it to a SPECIFIC window, or form in xforms 
terminology.

So here is what I did. I added a member to the FL_FORMS structure to 
hold a function pointer. So only two lines were added to forms.h

line 649:
typedef void (*FL_CLIENT_CALLBACK)(void *);

line 703:
FL_CLIENT_CALLBACK client_callback;

in objects.c added at line 105
form->client_callback = 0;

And in forms.c

removed line 1657
 fl_handle_form(form, FL_OTHER, 0, xev);
and replaced it with:
     if(form->client_callback){
   if(!form->client_callback(xev))
      fl_handle_form(form, FL_OTHER, 0, xev);
     }
     else
   fl_handle_form(form, FL_OTHER, 0, xev);

What this does is test to see if a client callback has been set, if not, 
it goes through fl_handle_form just like before. Also the client 
callback returns a TRUE if it did consume the event and a FLASE if it 
did not. If a FALSE is returned, fl_handle_form() is called as in 
original code.

So, in the users code  you need only  assign a  function pointer to  
(your form name)->client_callback  to get  ClientMessage's sent to you 
code. A quick snippet:
// user's ClientMessage handler:
int clientCallback(XEvent *xev){
   // test message type for atom defining data structure
   // and handle it.
   return 1;
}

// This code is in initialization before do_forms();

  fd_testEvent->testEvent->client_callback = clientCallback;

One thing I did notice as I traced through the code starting at 
fl_handle_form with FL_OTHER as the event was I could not find any other 
code in that chain that tested for FL_OTHER event. I think that it is a 
dead event starting at fl_handle_form. But, just to make sure I left the 
chain in if the client message is not consumed by user code.

This is just a prelimenary annoucement. I am doing more testing and once 
I believe it is stable and introduces no bugs, I will do  difff and pass 
the patch to you. I hope to make it into the next release, which I also 
hope is coming soon, as I want to use this on an amatuer radio 
application I wrote. And, if I use it others need to be able to get the 
same xforms version from savannah. Any idea on when the next release 
will happen?

As I have stated before, this will allow worker threads to be able to 
send ClientMessage XEvents to the gui thread containing user defined 
atoms to display data, set indicators, etc WITHOUT having to 
create/lock/unlock mutexes in a big while loop. Since the message is on 
the xforms gui event queue, it is handles just like a mouse click or key 
pressed event. Creatly simplifing code.

Please feel free to ask questions or make comments.

Jeff
wd4nmq at comcast.net



More information about the Xforms mailing list