[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In this chapter we give a brief overview of all the main functions that are available. For an overview of all routines related to specific object classes see Part III.
32.1 Version Information | ||
32.2 Initialization | ||
32.3 Creating Forms | ||
32.4 Object Attributes | ||
32.5 Doing Interaction | ||
32.6 Signals | ||
32.7 Idle Callbacks and Timeouts | ||
32.8 Global Variables |
The header file `forms.h' defines three symbolic constants which you can use to conditionally compile your application. They are
FL_VERSION
The major version number.
FL_REVISION
Revision number.
FL_INCLUDE_VERSION
1000 * FL_VERSION + FL_REVISION
There is also a routine that can be used to obtain the library version at run time:
int fl_library_version(int *version, int *revision) |
The function returns a consolidated version information, computed as
1000 * version + revision
. For example, for library version 1
revision 21 (1.21), the function returns a value of 1021 with
version
and revision
(if not NULL
) set to 1 and
21, respectively.
It is always a good idea to check if the header and the run time library are of the same version and take appropriate actions when they are not. This is especially important for versions less than 1.
To obtain the version number of the library used in an executable, run
the command with -flversion
option, which will print the
complete version information.
Display *fl_initialize(int *argc, char *argv[], const char *appclass, XrmOptionDescList app_opt, int n_app_opt); |
initializes the Forms Library and returns a pointer to the
Display
structure if a connection could be made, otherwise
NULL
. This function must be called before any other calls
to the Forms Library (except fl_set_defaults()
and a few
other functions that alter some of the defaults of the library).
The meaning of the arguments is as follows
argc, argv
Number and array of the command line arguments the application was
started with. The application name is derived from argv[0]
by
stripping leading path names and trailing period and extension, if
any. Due to the way the X resources (and command line argument
parsing) work, the executable name should not contain a dot .
or a star *
.
appclass
The application class name, which typically is the generic name for all instances of this application. If no meaningful class name exists, it is typically given (or converted to if non given) as the application name with the first letter capitalized (second if the first letter is an X).
app_opt
Specifies how to parse the application-specific resources.
n_app_opt
Number of entries in the option list.
The fl_initialize()
function builds the resource
database, calls the Xlib XrmParseCommand()
function to parse
the command line arguments and performs other per display
initialization. After the creation of the database, it is associated
with the display via XrmSetDatabase()
, so the application can
get at it if necessary.
All recognized options are removed from the argument list and their corresponding values set. The XForms library provides appropriate defaults for all options. The following are recognized by the library:
Option | Type | Meaning | Default |
-fldebug level | int | Print debug information | 0 (off) |
-name appname | string | Change application name | none |
-flversion | Print version of the library | ||
-sync | Synchronous X11 mode (debug) | false | |
-display host:dpy | string | Set (remote) host | $DISPLAY |
-visual class | string | TrueColor, PseudoColor... | best |
-depth depth | int | Set prefered visual depth | best |
-vid id | long | Set prefered visual ID | 0 |
-private | Force use of private colormap | false | |
-shared | Force use of shared colormap | false | |
-stdcmap | Force use of standard colormap | false | |
-double | Enable double buffering for forms | false | |
-bw width | int | Set object border width | 1 |
-rgamma gamma | float | Set red gamma | 1.0 |
-ggamma gamma | float | Set green gamma | 1.0 |
-bgamma gamma | float | Set blue gamma | 1.0 |
In the above table "best" means the visual that has the most colors,
which may or may not be the server's default. There is a special
command option -visual Default
that sets both the visual and
depth to the X servers default. If a visual ID is requested, it
overrides depth or visual if specified. The visual ID can also be
requested programmatically (before fl_initialize()
is
called) via the function
void fl_set_visualID(long id); |
Note that all command line options can be abbreviated, thus if the
application program uses single character options, they might clash
with the built-ins. For example, if you use -g
as a command
line option to indicate geometry, it might not work as -g
matches -ggamma
in the absence of -ggamma
. Thus you
should avoid using single character command line options.
If the border width is set to a negative number, all objects appear to have a softer appearance. Older version of the library used a larger default for the border width of 3.
As mentioned the fl_initialize()
function removes all the
above listed values from the command line arguments, leaving you with
a cleaned-up list. To get again at the complete list you can use the
function
char **fl_get_cmdline_args( int *arg_cnt ); |
returning a copy to the values from the original list and
their number via the arg_cnt
argument.
Depending on your application XForms defaults may or may not be appropriate. E.g., on machines capable of 24 bits visuals, Forms Library always selects the deeper 24 bits visual. If your application only uses a limited number of colors, it might be faster if a visual other than 24 bits is selected.
There are a couple of ways to override the default settings. You can
provide an application specific resource database distributed with
your program. The easiest way, however, is to set up your own program
defaults programmatically without affecting the users' ability to
override them with command line options. For this, you can use the
following routine before calling fl_initialize()
:
void fl_set_defaults(unsigned long mask, FL_IOPT *flopt); |
In addition to setting a preferred visual, this function can also be used to set other program defaults, such as label font size, unit of measure for form sizes etc.
The following table lists the fields, masks and their meanings of
FL_IOPT
:
Structure | Mask Name | Meaning |
---|---|---|
typedef struct { | ||
int debug; | FL_PDDebug | Debug level (0-5) |
int depth; | FL_PDDepth | Preferred visual depth |
int vclass; | FL_PDVisual | Prefered visual, TrueColor etc. |
int doubleBuffer; | FL_PDDouble | Simulate double buffering |
int buttonFontSize; | FL_PDButtonFontSize | Default button label font size |
int menuFontSize; | FL_PDMenuFontSize | Menu label font size |
int choiceFontSize; | FL_PDChoiceFontSize | Choice label and choice text font size |
int browserFontSize; | FL_PDBrowserFontSize | Browser label and text font size |
int inputFontSize; | FL_PDInputFontSize | Input label and text font size |
int labelFontSize; | FL_PDLabelFontSize | Label font size for all other objects (box, pixmap etc.) |
int pupFontSize; | FL_PDPupFontSize | Font size for pop-ups |
int privateColormap; | FL_PDPrivateMap | Select private colormap if appropriate |
int sharedColormap; | FL_PDSharedMap | Force use of shared colormap |
int standardColormap; | FL_PDStandardMap | Force use of standard colormap |
int scrollbarType; | FL_PDScrollbarType | Scrollbar type to use for browser and input |
int ulThickness; | FL_PDULThickness | Underline thickness |
int ulPropWidth; | FL_PDULPropWidth | Underline width, 0 for const. width fonts |
int backingStore; | FL_PDBS | Turn BackingStore on or off |
int coordUnit; | FL_PDCoordUnit | Unit of measure: pixel, mm, point |
int borderWidth; | FL_PDBorderWidth | Default border width |
} FL IOPT; |
A special visual designation, FL_DefaultVisual
and a command
line option equivalent, -visual Default
are provided to set the
program default to the server's default visual class and depth.
If you set up your resource specifications to use class names instead
of instance names, users can then list instance resources under
an arbitrary name that is specified with the -name
option.
Coordinate units can be in pixels, points (1/72 inch), mm (millimeters), cp (centi-point, i.e., 1/100 of a point) or cmm (centi-millimeter). The the type of unit in use can be queried or set via the functions
int fl_get_coordunit(void); void fl_set_coordunit(int coordUnit); |
coordUnit
can have the following values:
FL_COORD_PIXEL
, FL_COORD_POINT
, FL_COORD_MM
,
FL_COORD_centiPOINT
and FL_COORD_centiMM
.
The unit in use can be changed anytime, but typically you would do this prior to creating a form, presumably to make the size of the form screen resolution independent. The basic steps in doing this may look something like the following:
int oldcoordUnit = fl_get_coordunit(); fl_set_coordunit(FL_COORD_POINT); fl_bgn_form(...); /* add more objects */ fl_end_form(); fl_set_coordunit(oldcoordunit); |
Some of the defaults are "magic" in that their exact values depend on the context or platform. For example, the underline thickness by default is 1 for normal fonts and 2 for bold fonts.
There exists a convenience function to set the application default border width
void fl_set_border_width(int border_width) |
which is equivalent to
FL_IOPT fl_cntl; fl_cntl.borderWidth = border_width; fl_set_defaults(FL_PDBorderWidth, &fl_cntl); |
Typically this function, if used, should appear before
fl_initialize()
is called so the user has the option to
override the default via resource or command line options.
The cirrent setting of the borderwidth can also tested via
int fl_get_border_width(void); |
To change the default scrollbar type (which is THIN_SCROLLBAR
)
used in browser and input object, the following convenience function
can be used:
void fl_set_scrollbar_type(int type); |
where type
can be one of the following
FL_NORMAL_SCROLLBAR
Basic scrollbar
FL_THIN_SCROLLBAR
Thin scrollbar
FL_NICE_SCROLLBAR
Nice scrollbar
FL_PLAIN_SCROLLBAR
Similar to thin scrollbar, but not as fancy
Setting the scrollbar type before calling fl_initialize()
is equivalent to
FL_IOPT fl_cntl; fl_cntl.scrollbarType = type; fl_set_defaults(FL_PDScrollbarType, &fl_cntl); |
It is recommended that this function be used before
fl_initialize()
so the user has the option to override
the default through application resources.
Prior to version 0.80 the origin of XForms' coordinate system was at
the lower left-hand corner of the form. The new Form Designer will
convert the form definition file to the new coordinate system, i.e.,
with the origin at the upper left-hand corner, so no manual
intervention is required. To help those who lost the .fd
files
or otherwise can't use a newer version of fdesign
, a
compatibility function is provided
void fl_flip_yorigin(void); |
Note however that this function must be called prior to
fl_initialize()
and is a no-op after that.
If this function has been called functions like
fl_get_object_position()
or
fl_get_object_bbox()
, reporting an objects positions and
bounding box, will return y
-coordinates in the old-fashioned
coordinate system with the origin at the left bottom corner of the
form. Similarly, the functions for setting or changing an objects
position (fl_set_object_position()
and
fl_move_object()
) then expect to receive arguments for
the y
-coordinates in this system. The y
-coordinate
stored in the object itself (i.e., obj->y
) is always for the
normal coordinate system with the origin at the top left corner.
For proportional font, substituting tabs with spaces is not always appropriate because this most likely will fail to align text properly. Instead, a tab is treated as an absolute measure of distance, in pixels, and a tab stop will always end at multiples of this distance. Application program can adjust this distance by setting the tab stops using the following routine
void fl_set_tabstop(const char *s); |
where s
is a string whose width in pixels is to be used as the
tab length. The font used to calculate the width is the same font that
is used to render the string in which the tab is embedded. The default
"aaaaaaaa"
, i.e., eight 'a'
s.
Before we proceed further, some comments about double buffering are in order. Since Xlib does not support double buffering, Forms Library simulates this functionality with pixmap bit-bliting. In practice, the effect is hardly distinguishable from double buffering and performance is on par with multi-buffering extensions (It is slower than drawing into a window directly on most workstations however). Bear in mind that a pixmap can be resource hungry, so use this option with discretion.
In addition to using double buffering throughout an application, it is also possible to use double buffering on a per-form or per-object basis by using the following routines:
void fl_set_form_dblbuffer(FL_FORM *form, int yes_no); void fl_set_object_dblbuffer(FL_OBJECT *obj, int yes_no); |
Currently double buffering for objects having a non-rectangular box
might not work well. A nonrectangular box means that there are regions
within the bounding box that should not be painted, which is not
easily done without complex and expensive clipping and unacceptable
inefficiency. XForms gets around this by painting these regions with
the form's backface color. In most cases, this should prove to be
adequate. If needed, you can modify the background of the pixmap by
changing obj->dbl_background
after switching to double buffer.
Normally the Forms Library reports errors to stderr
. This can
be avoided or modified by registering an error handling function
void fl_set_error_handler(void (*user_handler)(const char *where, const char *fmt,...)); |
The library will call the user_handler
function with a string
indicating in which function an error occured and a formatting string
(see sprintf()
) followed by zero or more arguments. To restore
the default handler, call the function again with user_handler
set to NULL
. You can call this function anytime and as many
times as you wish.
You can also instruct the default message handler to log the error to
a file instead of printing to stderr
void fl_set_error_logfp(FILE *fp); |
For example
fl_set_error_logfp(fopen("/dev/null","w")); |
redirects all error messages to `/dev/null', effectively turning
off the default error reporting to stderr
.
In XForms versions older than 1.0.01 for some error messages, in addition to being printed to stderr, a dialog box were shown that requires actions from the user. This could be turned off and on with the function
void fl_show_errors(int show); |
where show
indicates whether to show (1) or not show (0) the
errors. With newer versions of the Forms Library this function has
no effect.
The fonts used in all forms can be changed using the routines
int fl_set_font_name(int n, const char *name); int fl_set_font_name_f(int n, const char *fmt, ,,,); |
The first function just accepts a simple string while the second
constructs the font name from a format string just as it's used for
printf()
etc. and the following arguments. The first argument,
n
, must be a number between 0 and FL_MAXFONTS-1
. The
function returns 0
on success, 1
if called before proper
initialization of the library and -1
for either invalid
arguments (name
or the result of the expansion of the format
string doesn't name an available font, n
negative or not less
than FL_MAXFONTS
). See section Label Attributes and Fonts, for
details. A redraw of all forms is required to actually see the change
for visible forms.
Since the dimension of an object is typically given in pixels,
depending on the server resolution and the font used, this can lead to
unsatisfactory user interfaces. For example, a button designed to
(just) contain a label in a 10 pt font on a 75 DPI monitor
will have the label overflow the button on a 100 DPI monitor. This
comes about because a character of a 10 pt font when rendered with
75 DPI
resolution may have 10 pixels while the same character
in the same 10 pt font with 100 DPI resolution may have 14
pixels. Thus, when designing the interfaces, leave a few extra pixels
for the object. Or use a resolution independent unit, such as point,
or centi-point etc.
Using a resolution independent unit for the object size should solve the font problems, theoretically. In practice, this approach may still prove to be vulnerable. The reason is the discreteness of both the font resolution and the monitor/server resolutions. The standard X fonts only come in two discrete resolutions, 75 DPI and 100 DPI. Due to the variations in monitor resolutions, the theoretically identical sized font, say a 10 pt font, can vary in sizes (pixels) by up to 30%, depending on the server (rendering a font on a 80 DPI monitor will cause errors in sizes regardless if a 75 DPI or 100 DPI font is used.) This has not even taken into account the fact that a surprising number of systems have wrong font paths (e.g., a 90 DPI monitor using 75 DPI fonts etc.).
With the theoretical and practical problems associated with X fonts, it is not practical for XForms to hard-code default font resolution and it is not practical to use the resolution information obtained from the server either as information obtained from the server regarding monitor resolution is highly unreliable. Thus, XForms does not insist on using fonts with specific resolutions and instead it leaves the freedom to select the default fonts of appropriate resolutions to the system administrators.
Given all these uncertainties regarding fonts, as a workaround, XForms provides a function that can be used to adjust the object size dynamically according to the actual fonts loaded:
double fl_adjust_form_size(FL_FORM *form); |
This function works by computing the size (in pixels) of every object
on the form that has an inside label and compares it to the size of
the object. Scaling factors are computed for all object labels that
don't fit. The maximum scaling factor found is then used to scale the
form so every object label fits inside the object. It will never
shrink a form. The function returns the resulting scaling factor. In
scaling the aspect ratio of the form is left unmodified and all object
gravity specifications are ignored. Since this function is meant to
compensate for font size and server display resolution variations,
scaling is limited to 125% per invocation. The best place to use this
function is right after the creation of the forms. If the forms are
properly designed this function should be a no-op on the machine the
forms were designed on. Form Designer has a special option
-compensate
and resource compensate
to request the
emission of this function automatically for every form created. It is
likely that this will become the default once the usefulness of it has
been established.
There is a similar function that works the same way, but on an object-by-object basis and further allows explicit margin specifications:
void fl_fit_object_label(FL_OBJECT *obj, FL_Coord hm, FL_Coord vm); |
where hm
and vm
are the horizontal and vertical margins
to leave on each side of the object, respectively. This function works
by computing the object labels size and comparing it to the object
size. If the label does not fit inside the object with the given
margin, the entire form the object is on is scaled so the object label
fits. In scaling the form, all gravity specification is ignored but
the aspect ratio of the form (and thus of all objects) is kept. This
function will not shrink a form. You can use this function on as many
objects as you choose. Of course the object has to have a label inside
the object for this function to work.
All colors with indices smaller than FL_FREE_COL1
are used (or
can potentially be used) by the Forms Library. If you wish they can be
changed using the following function prior to
fl_initialize()
:
void fl_set_icm_color(FL_COLOR index, int r, int g, int b); |
Using this function you can actually change all entries in the
internal colormap (with index
going up to
FL_MAX_COLORS-1
). You may also inspect the internal colormap
using
void fl_get_icm_color(FL_COLOR index, int *r, int *g, int *b); |
In some situations Forms Library may modify some of the server
defaults. All modified defaults are restored as early as possible by
the main loop and in general, when the application exits, all server
defaults are restored. The only exception is when exiting from a
callback that is activated by shortcuts. Thus it is recommended that
the cleanup routine fl_finish()
is called prior to
exiting an application or register it via atexit()
.
void fl_finish(void); |
In addition to restoring all server defaults, fl_finish()
also shuts down the connection and frees dynamically allocated memory.
To start the definition of a form call
FL_FORM *fl_bgn_form(int type, FL_Coord w, FL_Coord h); |
When the form is created it automatically acquires one object, a box
object covering the full area of the form, which is used as the
background of the form. The type
argument is the type of this
box object, so you can "style" the look of your forms (but don't use
any non-rectangular box types). w
and h
are the width
and height of the new form. The function returns a pointer to the new
form.
Note: if you look at the code generated by fdesign
for the
creation of a form you may notice that the type of this automatically
assigned box is FL_NO_BOX
(which is invisible) and that
for the background another box of the same size but a different
(visible) type is added. This is because in fdesign
the very
first object can't be accessed and thus its properties can not be
adjusted (like the box type or its color that then becomes the
background color of the form). By using an extra box, which can be
accessed from within fdesign
, that problem is circumvented.
There also exist functions for setting and requesting the background color of a form
void fl_set_form_background_color(FL_FORM *form, FL_COLOR col); FL_COLOR fl_get_form_background_color(FL_FORM *form); |
These functions use the color of the very first object of the form,
or, if this is a box of type FL_NO_BOX
as it is the case
with forms created via code generated by fdesign
, the color of
the second object. If these object(s) don't exist the function can't
work properly.
Once all objects required have been added to a form call
void fl_end_form(void); |
Between these two calls objects and groups of objects are added to the
form with functions like fl_add_button()
.
To start a new group of objects use
FL_OBJECT *fl_bgn_group(void); |
The function returns a pointer to the group (actually to an invisible
pseudo-object of class
FL_BEGIN_GROUP
). Groups can't be nested.
When all objects that are supposed to belong to the group are added call
void fl_end_group(void); |
Also this function creates an (invisible) pseudo-object, belonging to class
FL_END_GROUP
, but since it can't be used its address isn ot
returned.
Groups are useful for two reasons. First of all, it is possible to hide or deactivate groups of objects with a single function call. This is often very handy to dynamically change the appearance of a form depending on the context or selected options. In addition it can also be used as a shortcut to set some particular attributes of several objects. It is not uncommon that you want several objects to maintain their relative positioning upon form resizing. This requires to set the gravity for each object. If these objects are placed inside a group, setting the gravity attributes of the group will suffice.
The second reason for use of groups is radio buttons. Radio buttons are considered related only if they belong to the same group. Using groups is the only way to place unrelated groups of radio buttons on a single form without interference from each other.
Both forms and groups that have been ended by
fl_end_form()
or fl_end_group()
can be
"reopened" by using
FL_FORM *fl_addto_form(FL_FORM *form) FL_OBJECT *fl_addto_group(FL_OBJECT *group); |
Both functions return their argument on success and NULL
on
failure (e.g., because a different group or form is still open).
On success further objects can be appended to the form or group.
To remove an object from a form use
void fl_delete_object(FL_OBJECT *obj); |
This does not yet destroy the object, it just breaks its connection to the form it did belong to, so it can still be referenced and added to the same form again or some other form using
void fl_add_object(FL_FORM *form, FL_OBJECT *obj); |
even without "reopening" the form using fl_addto_form()
.
To finally destroy an object use
void fl_free_object(FL_OBJECT *obj); |
If fl_delete_object()
hadn't been called for the object
this will happen now. The object receives a final event of type
FL_FREEMEM
to allow it to free memory it did allocate and
do whatever other clean-up required. Finally all memory allocated for
the object is freed. After being freed an object can not be referenced
anymore.
A form as a whole, together with all the objects it contains can be deleted by calling
void fl_free_form(FL_FORM *form); |
This will first hide the form (emitting warning if this is necessary), then free all of its objects and finally release memory allocated for the form.
A number of general routines are available for setting and querying attributes. Unless stated otherwise, all attributes altering routines affect the appearance or geometry of the object immediately if the object is visible.
Since the object class and type of an object can't be changed anymore once an object has been created there are only functions for querying these attributes:
int fl_get_object_objclass(FL_OBJECT *obj); int fl_get_object_type(FL_OBJECT *obj); |
Receiving a negative value indicates that a NULL
pointer
was passed to the functions.
To set the two colors that influence the appearance of the object use
void fl_set_object_color(FL_OBJECT *obj, FL_COLOR col1, FL_COLOR col2); |
and to find out about the colors of an object use
void fl_get_object_color(FL_OBJECT *obj, FL_COLOR *col1, FL_COLOR *col2); |
void fl_set_object_boxtype(FL_OBJECT *obj, int boxtype); |
Changes the shape of the box of the object. Please note that not all possible boxtypes are suitable for all types of objects, see the documentation for the different objects for limitations.
To find out the current boxtype of an object use
int fl_get_object_boxtype(FL_OBJECT *obj); |
Receiving a negative value indicates that a NULL
pointer
was passed to the function.
There are also functions to change or query the border width of an object:
void fl_set_object_bw(FL_OBJECT *obj, int bw); void fl_get_object_bw(FL_OBJECT *obj, int *bw); |
If the requested border width is 0, -1 is used.
To change or inquire the objects position (relative to the form it belongs to) the functions
void fl_set_object_position(FL_OBJECT *obj, FL_Coord x, FL_Coord y); void fl_get_object_position(FL_OBJECT *obj, FL_Coord *x, FL_Coord *y); |
exist. If the object is visible it's redrawn at the new position.
An object can also be moved relative to its current position using the function
void fl_move_object(FL_OBJECT *obj, FL_Coord dx, FL_Coord dy); |
where dx
and dy
are the amounts by which the object
is moved to the right and down.
To change or inquire about the size of an object use
void fl_set_object_size(FL_OBJECT *obj, FL_Coord w, FL_Coord h); void fl_get_object_size(FL_OBJECT *obj, FL_Coord *w, FL_Coord *h); |
When changing the size of the object the position of its upper left hand corner remains unchanged.
To set or query both the position and the size of an object the functions
void fl_set_object_geometry(FL_OBJECT *obj, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h); void fl_get_object_geometry(FL_OBJECT *obj, FL_Coord *x, FL_Coord *y, FL_Coord (*w, FL_Coord *h); |
can be used.
Please note: always use one of the above functions to change the position and/or size of an object and don't try to change the information stored in the object directly. There's some double bookkeeping going on under the hood that makes sure that the objects position and size won't change due to rounding errors when the whole form gets resized and changing the internal information kept in the objects structure would interfere with this.
There's a second function for calculation an objects geometry:
void fl_get_object_bbox(FL_OBJECT *obj, FL_Coord *x, FL_Coord *y, FL_Coord *w, FL_Coord *h); |
The difference between this functions and
fl_get_object_geometry()
is that
fl_get_object_bbox()
returns the bounding box size that
has the label, which could be drawn outside of the object figured in.
Some objects in the library are composite objects that consist of other objects. For example, the scrollbar object is made of a slider and two scroll buttons. To get a handle to one of the components of the composite object, the following routine is available:
FL_OBJECT *fl_get_object_component(FL_OBJECT *obj, int objclass, int type, int number); |
where obj
is the composite object, objclass
and
type
are the component object's class ID and type; and
number
is the sequence number of the desired object in case the
composite has more than one object of the same class and type. You can
use a constant -1 for type
to indicate any type of class
objclass
. The function returns the object handle if the
requested object is found, otherwise NULL
. For example to
obtain the object handle to the horizontal scrollbar in a browser,
code similiar to the following can be used
hscrollbar = fl_get_object_component(browser, FL_SCROLLBAR, FL_HOR_THIN_SCROLLBAR, 0) |
To influence change the color, font size, font style, alignment and text of the label of an object use
void fl_set_object_lcolor(FL_OBJECT *obj, FL_COLOR lcol); void fl_set_object_lsize(FL_OBJECT *obj, int lsize); void fl_set_object_lstyle(FL_OBJECT *obj, int lstyle); void fl_set_object_lalign(FL_OBJECT *obj, int align); void fl_set_object_label(FL_OBJECT *obj, const char *label); void fl_set_object_label(FL_OBJECT *obj, const char *fmt, ...); |
To find out about the object labels color, font size, style, alignment and the string itself use
FL_COLOR fl_get_object_lcolor(FL_OBJECT *obj); int fl_get_object_lsize(FL_OBJECT *obj); int fl_get_object_lstyle(FL_OBJECT *obj); int fl_get_object_lalign(FL_OBJECT *obj); const char * fl_get_object_label(FL_OBJECT *obj); |
To set a tool-tip text for an object use the following routines
void fl_set_object_helper(FL_OBJECT *obj, const char *helpmsg); void fl_set_object_helper_f(FL_OBJECT *obj, const char *fmt, ...); |
where helpmsg
is a text string (with possible embedded newlines
in it) that will be shown when the mouse hovers over the object for
nore than about 600 msec. A copy of the string is made internally.
The second functions accepts instead of a simple string a format
string just as it's used for printf()
etc., followed by as many
further arguments as the format string contains format specifiers.
The boxtype, color and font for the tool-tip message displayed can be customized further using the following routines:
void fl_set_tooltip_boxtype(int boxtype); void fl_set_tooltip_color(FL_COLOR textcolor, FL_COLOR background); void fl_set_tooltip_font(int style, int size); |
where boxtype
is the backface of the form that displays the
text. The default is FL_BORDER_BOX
. textcolor
and
background
specify the color of the text and the color of the
backface. The defaults for these are FL_BLACK
and
FL_YELLOW
. style
and size
are the font style and
size of the text.
There are four function for controlling how an object reacts to resizing the form it belongs to or to find out what its current settings are:
void fl_set_object_resize(FL_OBJECT *obj, unsigned int howresize); void fl_get_object_resize(FL_OBJECT *obj, unsigned int *howresize); void fl_set_object_gravity(FL_OBJECT *obj, unsigned int NWgravity, unsigned int SEgravity); void fl_get_object_gravity(FL_OBJECT *obj, unsigned int *NWgravity, unsigned int *SEgravity); |
See section Doing Interaction, for more details on the resizing behaviour of objects.
If you change many attributes of a single object or many objects in a visible form the changed object is redrawn after each change. To avoid this put the changes between calls of the two functions
void fl_freeze_form(FL_FORM *form); void fl_unfreeze_form(FL_FORM *form); |
The form is automatically redrawn once it is "unfrozen", so a call of
fl_redraw_form()
isn't required (and, while the form is
"frozen", calling this function as well as fl_redraw_object()
has no effects).
You may also freeze and unfreeze all forms at once by using
void fl_freeze_all_forms(void); void fl_unfreeze_all_forms(void); |
There are also routines that influence the way events are dispatched. These routines are provided mainly to facilitate the development of (unusual) new objects where attributes need to be changed on the fly. These routines should not be used on the built-in ones.
To enable or disable an object to receive the FL_STEP
event,
use the following routine
void fl_set_object_automatic(FL_OBJECT *obj, int yes_no); |
To determine if an object receives FL_STEP
events use
int fl_object_is_automatic(FL_OBJECT *obj); |
To enable or disable an object to receive the FL_DBLCLICK
event use the following routine
void fl_set_object_dblclick(FL_OBJECT *obj, unsigned long timeout); |
where timeout
specifies the maximum time interval (in msec)
between two clicks for them to be considered a double-click (using 0
disables double-click detection). To determine the current setting
of the timeout use
unsigned fl_get_object_dblclick(FL_OBJECT *obj); |
To make an object or a group invisible or visible use the following two functions
void fl_hide_object(FL_OBJECT *obj); void fl_show_object(FL_OBJECT *obj); |
obj
can be the pseudo-object returned by
fl_bgn_group()
and then allows to hide or show whole
groups of objects.
To determine if an object is visible (given that the form it belongs to is also visible) use
int fl_object_is_visible(FL_OBJECT *obj); |
void fl_trigger_object(FL_OBJECT *obj); |
returns obj
to the application program after calling its
callback if one exists.
void fl_set_focus_object(FL_FORM *form, FL_OBJECT *obj); |
sets the input focus in form form
to object obj
. Note
however, if this routine is used as a response to an
FL_UNFOCUS
event, i.e., as an attempt to override the
focus assignment by the main loop from within an objects event
handler, this routine will not work as the main loop assigns a new
focus object upon return from the object event handler, which undoes
the focus change inside the event handler. To override the
FL_UNFOCUS
event the following routine should be used:
void fl_reset_focus_object(FL_OBJECT *obj); |
Use the following routine to obtain the object that has the focus on a form
FL_OBJECT *fl_get_focus_object(FL_FORM *form); |
void fl_set_object_callback(FL_OBJECT *obj, void (*callback)(FL_OBJECT *, long), long argument); |
binds a callback routine to an object.
To invoke the callback manually (as opposed to invocation by the main loop), use the following function
void fl_call_object_callback(FL_OBJECT *obj); |
If the object obj
does not have a callback associated with it,
this call has not effect.
void fl_set_form_callback(FL_FORM *form, void (*callback)(FL_OBJECT *, void *), void *data); |
binds a callback routine to an entire form.
It is sometimes useful to obtain the last X event from within a callback function, e.g., to implement different functionalities depending on which button triggers the callback. For this, the following routine can be used from within a callback function.
const XEvent *fl_last_event(void); |
In other rare circumstances one might not be interested not in the X event but instead the internal XForms event resulting in the invocation of an object or form callback. This information can be obtained by calling
int fl_current_event(void); |
A callback invocation resulting from a call of
fl_call_object_callback()
will return
FL_TRIGGER
.
For other possible return value see the chapter about XForms internal events. Calling this function is only useful
while within an object or form callback, at all other times it returns
just
FL_NOEVENT
.
Also in objects callback it might be of interest to find out if the mouse is on top of a certain letter of the (inside) label (one trivial use of this can be found in the program `demo/strange_button.c'. To find out about this use
int fl_get_label_char_at_mouse(FL_OBJECT *obj); |
The function returns the index of the character in the label of the
object the mouse is on or -1
if it's not over the label. Note
that this function has some limitations: it can only be used on labels
inside of the object and the label string may not contain underline
characters (and the label can't be a symbol) - if you try to use it on
labels that don't satisfy these requirements -1
is returned.
Sometimes, it may be desirable to obtain hardcopies of some objects in a what-you-see-is-what-you-get (WYSISYG) way, especially those that are dynamic and of vector-graphics in nature. To this end, the following routine exists:
int fl_object_ps_dump(FL_OBJECT *obj, const char *fname); |
The function will output the specified object in PostScript. If
fname
is NULL
, a file selector will be shown to ask the
user for a file name. The function returns a negative number if no
output is generated due to errors. At the moment, only the
FL_XYPLOT
object is supported. Nothe that this function isn't
part of the statndard XForms library (libforms
) but the
XForms image library (libflimage
discussed in Images.
The object must be visible at the time of the function call. The hardcopy should mostly be WYSIWYG and centered on the printed page. The orientation is determined such that a balanced margin results, i.e., if the width of the object is larger than the height, landscape mode will be used. Further, if the object is too big to fit on the printed page, a scale factor will be applied so the object fits. The box underneath the object is by default not drawn and in the default black&white mode, all curves are drawn in black. See demo program `xyplotover.c' for an example output.
It is possible to customize the output by changing the PostScript output control parameters via the function
FLPS_CONTROL *flps_init(void); |
A typical use is to call this routine to obtain a handle to the
PostScript output control structure and change the control structure
members to suit your needs before calling
fl_object_ps_dump()
. You should not free the returned
buffer.
The control structure has the following members
int ps_color
The choices are full color (FLPS_COLOR
), grayscale
(FLPS_GRAYSCALE
) and black&white (FLPS_BW
). The default
for xyplot is black and white. In this mode, all drawings are black,
on a white background. If drawbox
(see below) is true, the
drawing color can be either white or black depending on the specified
color.
int orientation
Valid choices are FLPS_AUTO
, FLPS_PORTRAIT
and
FLPS_LANDSCAPE
. The default is FLPS_AUTO
.
auto_fit
By default, this is true so the object always fits the printed page. Set it to false (0) to turn off auto-scaling.
int eps
Set this to 1 if output in EPS format is required.
int drawbox
Set this to 1 if the box of the object is to be drawn.
float xdpi, ydpi
These two are the screen resolution. The default is to use the actual resolution of the display. Note by setting a dpi number smaller or larger than the actual resolution, the output object is in effect being enlarged or shrunken.
float paper_w
The paper width in inches. The default is 8.5 in.
float paper_h
The paper height in inches. The default is 11 in.
To generate a PostScript output of a form or forms, use the
fd2ps
program documented in Generating Hardcopies.
To display the form form
on the screen use one of
Window fl_show_form(FL_FORM *form, int place, int border, const char *title); Window fl_show_form(FL_FORM *form, int place, int border, const char *fmt, ...); |
place
controls the position and size of the form. border
indicates whether a border (window manager's decoration) should be
drawn around the form. If a border is to be drawn title
is the
name of the window (and its associated icon). The routine returns the
window identifier of the form. For resource and identification
purposes, the form name is taken to be the title with spaces removed
and the first character lower-cased. E.g., if a form has a title
"Foo Bar
the forms name is derived as "fooBar"
.
The only difference between the two functions is that the first one
accepts a simple string for the title while the second expects a
format string like printf()
, followed by the appropriate number
of arguments.
For the the location and size of the window controlled by place
the following possibilities exist:
FL_PLACE_SIZE
The user can control the position but the size is fixed. Interactive resizing is not allowed once the form becomes visible.
FL_PLACE_POSITION
Initial position used will be the one set via
fl_set_form_position()
. Interactive resizing is allowed.
FL_PLACE GEOMETRY
Place at the latest position and size (see also below) or the geometry
set via fl_set_form_geometry()
etc. A form so shown will
have a fixed size and interactive resizing is not allowed.
FL_PLACE_ASPECT
Allows interactive resizing but any new size will have the aspect ratio as that of the initial size.
FL_PLACE_MOUSE
The form is placed centered below the mouse. Interactive resizing will
not be allowed unless this option is accompanied by
FL_FREE_SIZE
as in
FL_PLACE_MOUSE|FL_FREE_SIZE
.
FL_PLACE_CENTER
The form is placed in the center of the screen. If
FL_FREE_SIZE
is also specified, interactive resizing will
be allowed.
FL_PLACE_FULLSCREEN
The form is scaled to cover the full screen. If
FL_FREE_SIZE
is also specified, interative resizing will
be allowed.
FL_PLACE_FREE
Both the position and size are completely free. The initial size used
is the designed size. Initial position, if set via
fl_set_form_position()
, will be used, otherwise
interactive positioning may be possible if the window manager allows
it.
FL_PLACE_HOTSPOT
The form is so placed that mouse is on the "hotspot". If
FL_FREE_SIZE
is also specified, interactive resizing will
be allowed.
FL_PLACE_CENTERFREE
Same as FL_PLACE_CENTER|FL_FREE_SIZE
, i.e., place
the form at the center of the screen and allow resizing.
FL_PLACE ICONIC
The form is shown initially iconified. The size and location used are the window manager's default.
If no size is specified, the designed (or later scaled) size will be used. Note that the initial position is dependent upon the window manager used. Some window managers will allow interactive placement of the windows and some will not.
There are three values that can be passed for border
:
FL_FULLBORDER
Draw full border with title
FL_TRANSIENT
Draw borders with possibly less decoration (depends on the window managers behaviour)
FL_NOBORDER
Draw no border at all
Since multiple forms can be displayed at the same time note that using
FL_NOBORDER
might have adverse effect on keyboard focus and is
not very friendly to other applications (it is close to impossible to
move a form that has no border). Thus use this feature with
discretion. The only situation where FL_NOBORDER
is appropriate
is for automated demonstration suites or when the application program
must obtain an input or a mouse click from the user, and even then all
other forms should be deactivated while a borderless form is active.
For almost all situations where the application must demand an action
from the user FL_TRANSIENT
is preferable. Also note that you
can't iconify a form that has no borders and under most window
managers forms displayed with FL_TRANSIENT
can't be iconified
either.
One additional property (under almost all window managers) of a transient window is that it will stay on top of the main form, which the application program can designate using
void fl_set_app_mainform(FL_FORM *form); |
By default, the main form is set automatically by the library to the first full-bordered form shown.
To obtain the current main form, use the following routine
FL_FORM *fl_get_app_mainform(void); |
In some situations, either because the concept of an application main form does not apply (for example, an application might have multiple full-bordered windows), or under some (buggy) window managers, the designation of a main form may cause stacking order problems. To workaround these, the following routine can be used to disable the designation of a main form (must be called before any full-bordered form is shown):
void fl_set_app_nomainform(int yes_no); |
with a true flag.
All visible forms will have the properties WM_CLASS
,
WM_CLIENT_MACHINE
and WM_NAME
set. In addition, the
first full-bordered form will have the WM_COMMAND
property set
and is by default the applications main form.
Sometimes it is necessary to have access to the window resource ID before the window is mapped (shown). For this, the following routines can be used
Window fl_prepare_form_window(FL_FORM *form, int place, int border, const char *name); Window fl_prepare_form_window_f(FL_FORM *form, int place, int border, const char *fmt, ...); |
These routines create a window that obeys any and all constraints just
as fl_show_form()
does but remains unmapped. The only
difference between the two functions is that the first one takes a
simple string for the forms name while the second expects a format
string like printf()
, followed by the appropriate number of
further arguments.
To map such a window, the following must be used
Window fl_show_form_window(FL_FORM *form); |
Between these two calls, the application program has full access to
the window and can set all attributes, such as icon pixmaps etc., that
are not set by fl_show_form()
.
The application program can raise a form to the top of the screen so no other forms obscures it by calling
void fl_raise_form(FL_FORM *form); |
To instead lower a form to the bottom of the stack use
void fl_lower_form(FL_FORM *form); |
When placing a form on the screen using FL_PLACE_GEOMETRY
for
the place
argument to fl_show_form()
the position
and size can be set before by using the routines
void fl_set_form_position(FL_FORM *form, FL_Coord x, FL_Coord y); void fl_set_form_size(FL_FORM *form, FL_Coord w, FL_Coord h); void fl_set_form_geometry(FL_FORM form*, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h); void fl_scale_form(FL_FORM *form, double xsc, double ysc); |
where fl_set_form_geometry()
combines the functionality
of fl_set_form_position()
and
fl_set_form_size()
and the last routine,
fl_scale_form()
, scales the form in horizontal and
vertical direction by the factors passed to the function. These
routines can also be used when the form is visible.
Sometimes it is desirable to know how large the decoration are the window manager puts around a forms window. They can be obtained by a call of
void fl_get_decoration_sizes(FL_FORM *form, int *top, int *right, int *bottom, int *left); |
This is especially useful if it is necessary to open a window at some previously stored position since in that case one needs the position of of the window, which deviates from the position reported for the form by the window manager's decorations. Obviously, the above function can't be used for forms that are embedded into another form.
int fl_form_is_iconified(FL_FORM *form); |
allows to test if the (visible) window of a form is in iconified state.
If interactive resizing is allowed (e.g., by showing the form with
FL_PLACE_POSITION
) it can be useful to limit the range of
the size of a form can take. To this end, the following functions are
available
void fl_set_form_minsize(FL_FORM *form, FL_Coord minw, FL_Coord minh); void fl_set_form_maxsize(FL_FORM *form, FL_Coord maxw, FL_Coord maxh); |
Although these two routines can be used before or after a form becomes
visible, not all window managers honor such requests once the window
is visible. Also note that the constraints only apply to the next call
of fl_show_form()
for the form.
To set or change the icon shown when a form is iconified use the following routine
void fl_set_form_icon(FL_FORM *form, Pixmap icon, Pixmap mask); |
where icon
can be any valid pixmap ID. (see section Pixmap Object
for some of the routines that can be used to create pixmaps.) Note
that a previously set icon if not freed or modified in anyway.
If, for any reason, you would like to change the form title after the form has been made visible, the following calls can be used (they will also change the icon title)
void fl_set_form_title(FL_FORM *form, const char *name); void fl_set_form_title_f(FL_FORM *form, const char *fmt, ...); |
(While the first function expects a simple string, the second has to
be called with a format string as printf()
etc., followed by
the corresponding number of arguments.)
void fl_hide_form(FL_FORM *form); |
hides the particular form, i.e., closes its window and all subwindows.
To check if a form is visible or not, the following function can be used
int fl_form_is_visible(FL_FORM *form)' |
The function can return that the form is visible
(FL_VISIBLE
), is invisible (FL_INVISIBLE
) or
is in the processing of becoming invisible
(FL_BEING_HIDDEN
).
The most important function for doing the actual interaction with forms is
FL_OBJECT *fl_do_forms(void); |
It starts the main loop of the program and returns only when either
the state of an object changes that has no callback bound to it or
fl_finish()
is called in a callback. In the first case
the address of the object is returned, in the latter NULL
.
A second way of doing interaction with the currently displayed forms is using
FL_OBJECT *fl_check_forms(void); |
This routine returns NULL
immediately unless the state of one
of the object (without a callback bound to it) changed. In that case a
pointer to this object gets returned. NULL
also gets returned
after a call of fl_finish()
.
Then there are two more functions:
FL_OBJECT *fl_do_only_forms(void); FL_OBJECT *fl_check_only_forms(void); |
Both functions do the same as fl_do_forms()
and
fl_check_forms()
except that they do not handle user
events generated by application windows opened via
fl_winopen()
or similar routines.
To activate or deactivate a form for user interaction you can use
void fl_activate_form(FL_FORM *form); void fl_deactivate_form(FL_FORM *form); |
The same can also be done for all forms at once using
void fl_deactivate_all_forms(void) void fl_activate_all_forms(void) |
To find out if a form is currently active call
int fl_form_is_activated(FL_FORM *form); |
A return value of 0 tells you that the form is currently deactivated.
You can also register callbacks for a form that are invoked whenever the activation status of the form is changed:
typedef void (*FL_FORM_ATACTIVATE)(FL_FORM *, void *); FL_FORM_ACTIVATE fl_set_form_atactivate(FL_FORM *form, FL_FORM_ATACTIVATE callback, void *data); typedef void (*FL_FORM_ATDEACTIVATE)(FL_FORM *, void *); FL_FORM_ACTIVATE fl_set_form_atdeactivate(FL_FORM *form, FL_FORM_ATACTIVATE callback, void *data); |
Also individual objects (or groups of objects if the argument of the
function is an object returned by fl_bgn_group()
) can be
activated and deactivated to enable or disable user interaction:
void fl_activate_object(FL_OBJECT *obj); void fl_deactivate_object(FL_OBJECT *obj); |
It is normally useful to give the user a visual clue when an object gets deactivated, e.g., by graying out its label etc.
To find out if an object is active use
int fl_object_is_active(FL_OBJECT *obj); |
void fl_redraw_object(FL_OBJECT *obj); |
This routine redraws the particular object. If obj
is a group
it redraws the complete group. Normally you should never need this
routine because all library routines take care of redrawing objects
when necessary, but there might be situations in which an explicit
redraw is required.
void fl_redraw_form(FL_FORM *form); |
For non-form windows, i.e., those created with
fl_winopen()
or similar routines by the application
program, the following means of interaction are provided (note that
these do not work on form windows, for which a different set of
functions exist, see section Windowing Support for details.)
You may set up a callback routine (of type FL_APPEVENT_CB
for
all user events using
typedef int (*FL_APPEVENT_CB)(XEvent *, void *); FL_APPEVENT_CB fl_set_event_callback(FL_APPEVENT_CB callback, void *data); |
The function returns the previously set callback (or NULL
).
It is also possible to set up callback functions on a per window/event basis using the following routines:
typedef int (*FL_APPEVENT_CB)(XEvent *xev, void *user_data); FL_APPEVENT_CB fl_add_event_callback(Window win, int xevent_type, FL_APPEVENT_CB callback, void *user_data); void fl_remove_event_callback(Window win, int xevent_type); |
These functions manipulate the event callback functions for the window
specified, which will be called when an event of type
xevent_type
is pending for the window. If xevent_type
is
0 it signifies a callback for all event for window win
. Note
that the Forms Library does not solicit any event for the caller,
i.e., the Forms Library assumes the caller opens the window and
solicits all events before calling these routines.
To let the Forms Library handle event solicitation, the following function may be used
void fl_activate_event_callbacks(Window win); |
Typically, when a signal is delivered, the application does not know what state the application is in, thus limiting the tasks a signal handler can do. In a GUI system and with a main loop inside the library, it's even harder to know what's safe or unsafe to do in a signal handler. Given all these difficulties, the Forms Library's main loop is made to be aware of signal activities and invoke signal handlers only when it's appropriate to do so, thus removing most limitations on what a signal handler can do.
The application program can elect to handle the receipt of a signal by registering a callback function that gets called when a signal is caught
typedef void (*FL_SIGNAL_HANDLER)(int, void *); void fl_add_signal_callback(int signal, FL_SIGNAL_HANDLER sh, void *data); |
Only one callback per signal is permitted. By default,
fl_add_signal_callback()
will store the callback function
and initiate a mechanism for the OS to deliver the signal when it
occurs. When the signal is received by the library, the main loop will
invoke the registered callback function when it is appropriate to do
so. The callback function can make use of all of XForms's functions as
well as Xlib functions as if they were reentrant. Further, a signal
callback registered his way is persistent and will cease to function
only when explicitly removed.
It is very simple to use this routine. For example, to prevent a program from exiting prematurely due to signals, a code fragment similar to the following can be used:
void clean_up(int signum, void *data) { /* clean up, of course */ } /* call this somewhere after fl_initialize() */ fl_add_signal_callback(SIGINT, clean_up, &mydata); |
After this, whenever a SIGINT
signal is received,
clean_up()
is called.
To remove a signal callback, the following routine should be used
void fl_remove_signal_callback(int signal); |
Although very easy to use, there are limitations with the default
behavior outlined above. For example on some platforms there is no
blocking of signals of any kind while handling a signal. In addition,
use of fl_add_signal_callback()
prevents the application
program from using any, potentially more flexible, system signal
handling routines on some platforms. Also there might be perceptible
delays from the time a signal is delivered by the OS and the time its
callback is invoked by XForms' main loop. This delay can be particular
troublesome for timing sensitive tasks (playing music for example).
In light of these limitations, provisions are made so an application
program may choose to take over the initial signal handling setup and
receipt via various system dependent methods (sigaction()
for
example).
To change the default behavior of the built-in signal facilities, the
following routine should be called prior to any use of
fl_add_signal_callback(
) with a true value for flag
:
void fl_app_signal_direct(int flag); |
After this call fl_add_signal_callback()
will not
initiate any actions to receive a signal. The application program
should handle the receipt and blocking of signals (via e.g.,
signal(2)
, sigaction(2)
, sigprocmask(2
) etc.) When
the signal is received by the application program, it should call the
following routine to inform the main loop of the delivery of the
signal signum
, possibly after performing some timing sensitive
tasks:
void fl_signal_caught(int signum); |
This routine is the only one in the library that can be safely called
from within a direct application signal handler. If multiple
invocations of fl_signal_caught()
occur before the main
loop is able to call the registered callback, the callback is called
only once.
The following example illustrates how to handle a timing critical
situation (for most application, idle callback, timeouts or
FL_TIMER
object should be sufficient).
First, you need to define the function that will handle the timing critical tasks. The function will be registered with the OS to be invoked directly by it. There are limitations on what you can do within a (OS) signal handler, in particular, GUI activity is not safe.
void timing_critical_task(int sig) { /* handle timing critical tasks that does not involve GUI */ ... /* Now tell the library the signal has been delivered by the OS. * The library will invoke the xforms signal handler when it's * appropriate to do so */ fl_signal_caught(sig); } |
Now define a (XForms) signal handler that will be responsible for handling the response of the GUI upon receipt of the signal
void gui_signal_handler(int sig, void *data) { /* within an XForms signal handler, there is no limitation * on GUI activitity */ fl_set_object_color(....); ... } |
To make all this work, a set-up similar to the following can be used
/* setup the signal */ fl_app_signal_direct(1); setitimer(ITIMER_REAL, interval); /* setup the OS signal handler */ signal(SIGALRM, timing_critical_tasks); /* setup the XForms signal handler */ fl_add_signal_callback(SIGALRM, gui_signal_handler, &myData); |
For application programs that need to perform some light, but
semi-continuous or periodic tasks, idle callback and timeouts (also
FL_TIMER
objects) can be utilized.
To register an idle callback with the system, use the following routine
typedef int (*FL_APPEVENT_CB)(XEvent *, void *); FL_APPEVENT_CB fl_set_idle_callback(FL_APPEVENT_CB callback, void *user_data); |
where callback
is the function that will get called whenever
the main loop is idle. The time interval between invocations of the
idle callback can vary considerably depending on interface activity
and other factors. A range between 50 and 300 msec should be
expected. While the idle callback is executed it won't be called again
(i.e., no call of any XForms function from within the idle callback
function will call the idle callback function), so it does not need to
be reentrant.
It is possible to change what the library considers to be "idle" with the following function:
void fl_set_idle_delta(long msec); |
Here msec
is the minimum time interval of inactivity after
which the main loop is considered to be in an idle state. However it
should be noted that under some conditions an idle callback can be
called sooner than the minimum interval.
If the timing of the idle callback is of concern, timeouts should be used. Timeouts are similar to idle callbacks but with the property that the user can specify a minimum time interval that must elapse before the callback is called. The precision of timeouts tends to be quite a bit better than that of idle callbacks since they internally get prefered treatent. To register a timeout callback, the following routine can be used
typedef void (*FL_TIMEOUT_CALLBACK)(int, void *); int fl_add_timeout(long msec, FL_TIMEOUT_CALLBACK callback, void *data); |
The function returns the timeout ID (note: the function will not
return 0 and -1, so the application can use these values to mark
invalid or expired timeouts). When the time interval specified by the
msec
argument (in milli-second) is elapsed, the timeout is
removed and the callback function is called with the timeout ID as the
first argument. Although a timeout offers some control over the
timing, due to performance and CPU load compromises, while the
resolution can be better than 10 ms under favourable conditions,
it can also be much worse, occasionally up to 150 ms.
To remove a timeout before it triggers, use the following routine
void fl_remove_timeout(int id); |
where id
is the timeout ID returned by
fl_add_timeout()
. See section Timer Object, for the usage of
FL_TIMER
object. For tasks that need more accurate timing the
use of signal should be considered.
For convenience the library exports a number of global variables. These are:
FL_OBJECT *FL_EVENT
This is a special object returned by fl_do_forms()
etc.
when an X event is received that isn't coming from a form under the
control of the library, e.g., for a window that was opened directly
via Xlib functions. Upon receiving this special event the application
program can and must remove the pending event from the queue using
fl_XNextEvent()
.
FL_FORM *fl_current_form
This variable is always set to the currently active form.
Display *fl_display
This variable is set to the display (X server) the program is
connected to and is needed as an argument for many Xlib functions.
It's recommended not to use this global variable but instead either
the function fl_get_display()
or
FL_FormDisplay()
(the latter accepts a form pointer as
its argument and will also be safe in future versions of the library
that may support multiple connections).
int fl_screen
This variable is set to the default screen of the display connection.
Window fl_root
This variable is set to the root window.
Window fl_vroot
Some window managers have problems with obtaining the corrent root
window and applications don't work with the normal root windows. In
this case fl_vroot
can be used instead.
int fl_scrw, fl_scrh
These variables contain the screens width and height.
int fl_mode
The variable contains the visual mode in use, it should be one of the
Xlib constants PseudoColor
, TrueColor
,
DirectColor
, StaticColor
, GrayScale or
can be
used (the latter accepts a form pointer as its argument and is thus
also safe for future versions that may allow multiple connections).
StaticGray
. Alternatively, the functions
fl_get_vclass()
or fl_get_form_vclass()
FL_State fl_state[ 6 ]
This array of structure of type FL_State
contains a lot
of information about the graphics mode, where each structure has the
information for each of the cisual modes. Interesting is only the
entry for the visual mode used, fl_vmode
.
char *fl_ul_magic_char
This variable points to the character used to indicate underlining
in labels and other texts. If it appears as the very first character
of a string all characters in that string are underlined, otherwise
the character direct in front of it. Per default it's set to
'\b'
.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Build Daemon on October 16, 2020 using texi2html 1.82.