diff options
author | Owen Taylor <otaylor@src.gnome.org> | 1998-02-03 23:31:21 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1998-02-03 23:31:21 +0000 |
commit | 23a13fd4a57cf3c6742fda7ee768a8433e1bbe39 (patch) | |
tree | 8a1b5dbeae8311826a0393fe87eca6b42cb37db8 /docs/widget_system.txt | |
parent | 64ca527ecbcbbf715551b59a7248ef3b225894ce (diff) | |
download | gtk+-23a13fd4a57cf3c6742fda7ee768a8433e1bbe39.tar.gz |
Renamed widget_states.txt to widget_system.txt, and
made some further revisions.
Diffstat (limited to 'docs/widget_system.txt')
-rw-r--r-- | docs/widget_system.txt | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/docs/widget_system.txt b/docs/widget_system.txt new file mode 100644 index 0000000000..6607aa2768 --- /dev/null +++ b/docs/widget_system.txt @@ -0,0 +1,379 @@ +This file contains some notes as to how the widget system does +and should work. It consists of three parts: + + I) A description of the meaning of the various flags + + II) A list of invariants about the states of the widgets. + (Throughout this document, we refer to the states of the + widgets by referring to the flags for gtkwidget) + + III) Some notes about the ways that a widget changes states + + IV) A list of responsibilities of various widget signals when + the states change. + +Any action necessary to maintain the invariants in II which is not +explicitly mentioned in IV), is the responsibility of the core GTK +code, which is roughly defined as: + + gtkobject.c + gtkwidget.c + gtkcontainer.c + gtkmain.c + gtksignal.c + +Section II is mostly of interest to those maintaining GTK, the +other sections may also be interesting to people writing +new widgets. + + Owen Taylor <owt1@cornell.edu> + 98/02/03 + +I. Flags +-------- + +GTK_REALIZED: + set by gtk_widget_realize, unset by gtk_widget_unrealize + relies on ((widget->parent && widget->parent->window) + || GTK_WIDGET_TOPLEVEL (widget); + means: widget has an associated GdkWindow (XWindow) + +GTK_MAPPED: + set by gtk_widget_map, unset by gtk_widget_unmap + may only be set if GTK_WIDGET_REALIZED(widget) + means: gdk_window_show() has been called on the widgets window(s). + +GTK_VISIBLE: + set by gtk_widget_show + implies that a widget will be GTK_MAPPED as soon as it's + parent is GTK_MAPPED. +!GTK_VISIBLE: + set by gtk_widget_hide + implies that a widget is not onscreen, therefore !GTK_MAPPED + +GTK_REDRAW_PENDING: + relies on GTK_WIDGET_MAPPED(widget) + [this is not really enforced throughout the code, but should + be. it only requires a few checks for GTK_WIDGET_MAPPED and + minor changes to gtk_widget_unmap, we can then remove the check + in gtk_widget_real_destroy] + means: there is an idle handler waiting for the widget, that + will cause a full redraw (gtk_widget_draw(widget, NULL)) + +GTK_RESIZE_PENDING: + first, this is only valid for GtkContainers. + [some of the code should move to gtkcontainer.c therefore] + relies on GTK_WIDGET_REALIZED(widget) + [this is not really enforced throughout the code, but should + be. it only requires a few checks for GTK_WIDGET_RELIZED and + minor changes to gtk_widget_unrealize, we can then remove the check + in gtk_widget_real_destroy] + means: there is an idle handler waiting for the container to + resize it. + +GTK_RESIZE_NEEDED: + relies on GTK_WIDGET_REALIZED(widget) + [puhhh, this isn't rely enforced either..., bla bla ...remove check + in gtk_widget_real_destroy] + means: a widget has been added to the resize_widgets list of + its _toplevel_ container (keep this in mind for GtkViewport). + remark: this flag is also used internaly by gtkwindow.c. + +GTK_LEAVE_PENDING: + a widget is flagged as such if there is a leave_notify event + pending for it. it receives this event regardless of a grab or + its current sensitivity. + [this should be made relying on GTK_REALIZED] + +GTK_HAS_GRAB: + set by gtk_grab_add, unset by gtk_grab_remove + means: widget is in the grab_widgets stack. + +GTK_WIDGET_DRAWABLE: + a widget is flagged as GTK_WIDGET_VISIBLE and GTK_WIDGET_MAPPED + means: it _makes sense_ to draw in a widgets window. + + + +II. Invariants: +--------------- + +This section describes various constraints on the states of +the widget: + +In the following + + A => B means if A is true, than B is true + A <=> B means A is true, if and only if B is true + (equivalent to A => B and B <= A) + + +1) GTK_WIDGET_DESTROYED (widget) => !GTK_WIDGET_REALIZED (widget) + => !GTK_WIDGET_VISIBLE (widget) +[ The latter is not currently in place, but it should be ] + +2) GTK_WIDGET_MAPPED (widget) => GTK_WIDGET_REALIZED (widget) + +3) if GTK_WIDGET_TOPLEVEL (widget): + GTK_WIDGET_VISIBLE (widget) <=> GTK_WIDGET_MAPPED (widget) + +4) if !GTK_WIDGET_TOPLEVEL (widget): + widget->parent && GTK_WIDGET_REALIZED (widget->parent) <=> + GTK_WIDGET_REALIZED (widget) + +5) if !GTK_WIDGET_TOPLEVEL (widget): + + GTK_WIDGET_MAPPED (widget) => GTK_WIDGET_VISIBLE (widget) + => GTK_WIDGET_REALIZED (widget) + + widget->parent && GTK_WIDGET_MAPPED (widget->parent) && + GTK_WIDGET_VISIBLE (widget) => GTK_WIDGET_MAPPED (widget) + +Note:, the definition + +[ GTK_WIDGET_DRAWABLE = GTK_WIDGET_VISIBLE && GTK_WIDGET_MAPPED + is made in gtkwidget.c, but by 3) and 5), + + GTK_WIDGET_MAPPED => GTK_WIDGET_VISIBLE +] + + + +III. How states are changed: +---------------------------- + +How can the user control the state of a widget: +----------------------------------------------- + +(In the following, set flag means set the flag, do appropriate +actions, and enforce above invariants) + +gtk_widget_show: + if !GTK_DESTROYED sets GTK_VISIBLE + +gtk_widget_hide: + if !GTK_VISIBLE for widget + +gtk_widget_destroy: + sets GTK_DESTROYED + For a top-level widget + +gtk_widget_realize: + if !GTK_DESTROYED sets GTK_REALIZED +- Calling gtk_widget_realize when the widget is not a descendent + of a toplevel is an ERROR. + +gtk_container_add (container, widget) [ and container-specific variants ] + Sets widget->parent + +gtk_container_remove (container, widget) + unsets widget->parent + +gtk_widget_reparent (widget, new_parent) + Equivalent to removing widget from old parent and adding it to + the new parent, except that the widget will not be temporarily + unrealized if both the old parent and the new parent are realized. + + +gtk_widget_unrealize +gtk_widget_map +gtk_widget_unmap + +These functions are not meant to be used by applications - they +are used only by GTK and widgets to enforce invariants on the +state. + +When The X window corresponding to a GTK window is destroyed: +------------------------------------------------------------- + +gtk_widget_destroy is called (as above). + + + +IV. Responsibilities of widgets +-------------------------------- + +Adding to a container +--------------------- + +When a widget is added to a container, the container: + + 1) calls gtk_widget_set_parent (widget, container) + 2) calls gtk_widget_set_parent_window (widget, window) if + the widget is being added to something other than container->window + 3) if container is realized, and not widget, realizes widget + 4) if container is mapped, and not widget and widget is GTK_VISIBLE, + maps widget + 5) Queues a resize if the widget is mapped + +Note: It would be nice to remove 3) and 4) out of widget specific code + since they are of the invariant-enforcing nature, but it is + a bit hard, since they can't be done until after 2) + + +Removing from a container +------------------------- + +When a widget is removed to a container, the container: + + 1) Calls gtk_widget_unparent (widget) + 2) Sets widget->parent to NULL + 3) Queues a resize. + +Notes: + + gtk_widget_unparent unrealizes the widget except in the + special case GTK_IN_REPARENT is set. + + +At widget creation +------------------ + +Widgets are created in an unrealized state. + + 1) The widget should allocate and initialize needed data structures + + +The Realize signal +------------------ + +When a widget recieves the "realize" signal it should: + + NO_WINDOW widgets: (probably OK to use default handler) + + 1) set the realized flag + 2) set widget->window + widget->window = gtk_widget_get_parent_window (widget); + gdk_window_ref (widget->window); + 3) attach the widget's style + + widget->style = gtk_style_attach (widget->style, widget->window); + + widget with window(s) + + 1) set the REALIZED flag + 2) create windows with the parent obtained from + gtk_widget_get_parent_window (widget); + 3) attach the widget's style + 4) set the background color for the new window based on the style + +The Map signal +-------------- + + 1) Set the MAPPED flag + 2) If the widget has any windows, gdk_window_show those windows + 3) call gtk_widget_map for all child windows that are + VISIBLE and !MAPPED. + 3) Do any other functions related to putting the widget onscreen. + (for instance, showing extra popup windows...) + +The Unmap signal +---------------- + +When a widget receives the unmap signal, it must: + + 1) If the widget has a window, gdk_window_hide that window, + 2) If the widget does not have a window, unmap all child widgets + 3) Do any other functions related to taking the widget offscreen + (for instance, removing popup windows...) + 3) Unset GTK_MAPPED + + +The Unrealize signal +-------------------- + +When a widget receives the unrealize signal, it must + + 1) For any windows other than widget->window do: + + gdk_window_set_user_data (window, NULL); + gdk_window_destroy (window); + + 2) Call the parent's unrealize handler + + +The Widget class unrealize handler will take care of unrealizing +all children if necessary. [should this be made consistent with +unmap???] + + +The Destroy Signal +------------------ + +Commentary: + + The destroy signal probably shouldn't exist at all. A widget + should merely be unrealized and removed from its parent + when the user calls gtk_widget_destroy or a GDK_DESTROY event + is received. However, a large body of code depends on + getting a definitive signal when a widget goes away. + + That could be put in the finalization step, but, especially + with language bindings, the cleanup step may need to refer + back to the widget. (To use gtk_widget_get_data, for instance) + If it does so via a pointer in a closure (natural for + Scheme, or Perl), then the finalization procedure will never + be called. + + Also, if we made that the finalization step, we would have + to propagate the GDK_DESTROY event in any case, since it is + at that point at which user-visible actions need to be taken. + + +When a widget receives the destroy signal, it must: + + 1) If the widget "owns" any widgets other than its child + widgets, (for instance popup windows) it should + call gtk_widget_destroy () for them. + + 2) Call the parent class's destroy handler. + + +The "destroy" signal will only be received once. A widget +will never receive any other signals after the destroy +signal (but see the sectionalize on "Finalize" below) + +The widget must handle calls to all publically accessible +functions in an innocuous manner even after a "destroy" +signal. (A widget can assume that it will not be realized +after a "destroy" signal is received, which may simplify +handling this requirement) + + +The Finalize Pseudo-signal +-------------------------- + +The finalize pseudo-signal is received after all references +to the widget have been removed. The finalize callback +cannot make any GTK calls with the widget as a parameter. + +1) Free any memory allocated by the widget. (But _not_ + the widget structure itself. + +2) Call the parent class's finalize signal + + +A note on chaining "destroy" signals and finalize signals: +--------------------------------------------------------- + +This is done by code like: + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); + +It may not be completely obvious why this works. Note +that parent_class is a static variable on a per-class +basis. So say: we have + + GtkFoo <- GtkBar <- GtkWidget <-GtkObject + +And that Foo, Widget, and Object all have destructors, but +not Bar. + +Then gtk_foo_destroy will call gtk_widget_destroy (because +it was not overridden in the Bar class structure) and +gtk_widget_destroy will call gtk_object_destroy because +the parent_class variable referenced by gtk_foo_destroy is the +static variable in gtkwidget.c: GtkObjectClass. + + |