[lazarus] Progress

Michael A. Hess mhess at miraclec.com
Thu Sep 2 16:47:24 EDT 1999

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:
> 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

*  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>

     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,
         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),
                             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,
         gtk_widget_show (window);
         gtk_main ();
     /* example-end */

Something more to think about. But again is it still worth the effort??

==== Programming my first best destiny! ====

Michael A. Hess      Miracle Concepts, Inc.
mhess at miraclec.com   http://www.miraclec.com

More information about the Lazarus mailing list