I changed some of my position in mid response to this email. Read the whole thing to follow my train of thought.
Jeff Wormsley wrote 16 lines
The only reason I am asking is that if there is a Before as well as an
After, then Interfaces could by default set the Before callback to
tell GTK to handle the event, but if the LCL event were overriden, it
could in turn override the Before event. So, to use a GTK button as
normal, there would be no difference from current code. But, if you
wanted to, say, keep someone from clicking on it, you would set the
callback that came before the click to something other than the
default, then handle the event yourself, and return to GTK whether to
keep going or not. In essence, you have then overridden the event,
just as you would have in windows if you intercepted the WindProc and
acted on a WM_MOUSECLICK (or whatever that message is). In Windows,
you either pass the message on to the parent handler for normal
handling, or throw it away. In GTK, you either return False to the
Before event for normal handling, or return True to tell GTK the event
has already been handled.
Again were back to the problem of the API independence. If the LCL was written just for GTK we wouldn't be using the InterfaceObject code and the GTK routines and calls and callbacks could be an integral part of the LCL classes. Then we could more easily do what you are asking about. The problem is with our callback dispatching. It currently works as follows.
* The GTK callback routine is called. This is found in the gtkint.pp set of files.
* This callback routine establishes which LCL component to Dispatch the message to by the data variable that is passed into the callback routine from GTK.
* The callback routine calls the low level RTL code for the Dispatch to and FPC Object.
Now this is where I was seeing a problem. How to return the information to GTK telling to ignore the event. I suppose you could pass a record to the Dispatch which would include a variable as a flag that the LCL eventhandler could set indicating whether to pass a result that it did or did not handle it. Hmmmmmmm.
I'm beginning to change my mind here. We just might be able to do what you are talking about after all. If we can inclose every component inside the GTKEventBox so that we are always assured that every component is capable of receiving any trapped event and we include a return state variable with every {DoEvent}, this just might work.
It will still depend on how the GTK deals with default handlers of the various events within the GTK library. It might not always be possible to override every event. We will have to examine some of the internals of the GTK widgets to be sure this will work. Hmmmm.
This will require us to backup and redo alot of what has already been built for the LCL. Really it will only require changes in the gtkint.pp files but it will be some heavy changes. It will also require some changes to how the TNotify routines are written for every class. But it might be worth it. Hmmmmmm.
I am including some more information from the GTK tutorial with regards to the GTKEventBox. It is an example showing how to add buttonClick to a Label Widget which doesn't naturally have one. So if the EventBox does support all events we could indeed over ride any control to include or ignore events it previously used. Hmmmmm.
We still have to look if it is an easy matter to override the various widget class methods for things like draw normally written in "C". Then we have to see if we can maintain this separation via the gtkint.pp code. I still think that this might be getting to complex to maintain independence. It might make more sense to make an LCL that is just written for use by GTK. I'm still not sure of the whole concept.
-------------------
10.1 The EventBox
Some GTK widgets don't have associated X windows, so they just draw on their parents. Because of this, they cannot receive events and if they are incorrectly sized, they don't clip so you can get messy overwriting, etc. If you require more from these widgets, the EventBox is for you.
At first glance, the EventBox widget might appear to be totally useless. It draws nothing on the screen and responds to no events. However, it does serve a function - it provides an X window for its child widget. This is important as many GTK widgets do not have an associated X window. Not having an X window saves memory and improves performance, but also has some drawbacks. A widget without an X window cannot receive events, and does not perform any clipping on its contents. Although the name EventBox emphasizes the event-handling function, the widget can also be used for clipping. (and more, see the example below).
To create a new EventBox widget, use:
GtkWidget *gtk_event_box_new( void );
A child widget can then be added to this EventBox:
gtk_container_add( GTK_CONTAINER(event_box), child_widget );
The following example demonstrates both uses of an EventBox - a label is created that is clipped to a small box, and set up so that a mouse-click on the label causes the program to exit. Resizing the window reveals varying amounts of the label.
/* example-start eventbox eventbox.c */
#include <gtk/gtk.h>
int
main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *event_box;
GtkWidget *label;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Event Box");
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (gtk_exit), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
/* Create an EventBox and add it to our toplevel window */
event_box = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER(window), event_box);
gtk_widget_show (event_box);
/* Create a long label */
label = gtk_label_new ("Click here to quit, quit, quit, quit,
quit");
gtk_container_add (GTK_CONTAINER (event_box), label);
gtk_widget_show (label);
/* Clip it short. */
gtk_widget_set_usize (label, 110, 20);
/* And bind an action to it */
gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
gtk_signal_connect (GTK_OBJECT(event_box),
"button_press_event",
GTK_SIGNAL_FUNC (gtk_exit), NULL);
/* Yet one more thing you need an X window for ... */
gtk_widget_realize (event_box);
gdk_window_set_cursor (event_box->window,
gdk_cursor_new(GDK_HAND1));
gtk_widget_show (window);
gtk_main ();
return(0);
}
/* example-end */
Something more to think about. But again is it still worth the effort??