The GTK-server interface module (gsv) in the FFL library implements an ANS compatible way to use the GTK library. This module is added in version 0.8.0.
To actually display the GUI, the GTK-server tool is used. This tool can receive GTK calls through a pipe or TCP-IP connection from an external process (the forth engine).
The gsv module supports this by connecting to the GTK-server, translating the forth calls to GTK-server calls, sending the calls, receiving the response and translating the response back.
This way the module makes it possible for a forth engine to display a GTK GUI.
Currently the module supports UNIX/LINUX.
You will need the GTK library and the GTK-server application. See the relevant docs for installing.
For using the GTK-server it is important to read the relevant documentation. In particular the documentation of the gtk-server.cfg file is very important. This file describes what requests can be made to the GTK-server. By adding or deleting calls in this file, you can optimize the gtk-server.cfg file for your project. For example the gtk-server.cfg file used in the examples directory of the ffl library, is expanded with a number of requests to make the examples possible.
For a project using GTK and Forth, the best setup is a dedicated directory. In this directory you can put the project specific gtk-server.cfg file. This file can then be used by the GTK-server and the gsv-module. As a result both use the same configuration file.
After a gtk-server.cfg is copied to the project directory, you can start the GTK-server (on linux) in this project directory:
gtk-server -fifo=prj-fifo &
The prj-fifo is the fifo filename that is used to communicate with the GTK-server. You can use any file name. All the examples in the ffl library use the 'ffl-fifo' filename.
The next step is to start the forth engine (gforth):
In gforth you should include the gsv-module:
Then read the gtk-server.cfg file and open a connection to the GTK-server:
s" gtk-server.cfg" s" prj-fifo" gsv+open throw
The gsv+open call returns an ior. If it is 0, there is a connection to the GTK-server and the gtk-server.cfg is processed.
From now on you can send GTK calls to the GTK-server. First initialise the toolkit:
Then create a toplevel window and save the handle in the window value:
GTK_WINDOW_TOPLEVEL gtk_window_new VALUE window
Give the window a title:
s" Title: hello world" window gtk_window_set_title
Show the window:
Wait for events:
s" WAIT" gtk_server_callback 2drop
The window is shown. After pressing the close button of the window ('X'), the call will return.
This will close all windows and stop the GTK-server process.
There are a number of examples in the library available. These are inspired by the GTK-tutorial.
The examples use the fifo name: ffl-fifo. To run an example start the GTK-server in the example directory:
gtk-server -fifo=ffl-fifo &
Then start one of the following forth engines with the example file:
spf4 ffl/config.fs gsv_expl.fs
lxf include gsv_expl.fs
vfxlin include gsv_expl.fs
The following examples are shipped with the library (in the examples directory):
|gsv6_expl.fs||Toggle Button Widget|
|gsv9_expl.fs||Arrow & Tooltip Widget|
|gsv10_expl.fs||Timer & Progress bar Widget|
|gsv17_expl.fs||File Chooser Dialog|
My experience is that the GTK-server will not always clean up the fifo file after an error. You can manually remove it (on linux):
The GTK-server is running as a process. You can see the process ID by entering:
ps -e | grep gtk-server
This ID can then be used to stop the GTK-server after problems:
The GTK-server uses the gtk-server.cfg file to determine which requests can be made and what the arguments are for that requests.
To keep the gsv-module in sync with the GTK-server, the module reads the gtk-server.cfg file. It parses the file and translates the contents into forth words and forth constants in the dictionary.
If you use your own gtk-server.cfg, then make sure that the definition of gtk_server_enable_c_string_escaping is present in your configuration file. The gsv module uses this call to check if the gtk calls are loaded, if the connection to the gtk-server is working and to support quoted strings.
If this call is missing in your gtk-server.cfg file, the gsv module will not work.
The gsv-module translates the arguments of the requests in the gtk-server.cfg file to the following forth stack data types :
|gtk-server.cfg argument datatype||forth stack data type|
|VARARGS||i*x j*r c-addr u|
Note: The argument STRING is quoted by the gsv-module.
The return value of the requests in the gtk-server.cfg file is translated to the following forth data type:
|gtk-server.cfg returnvalue datatype||forth stack data type|
Note: Keep in mind that returned addresses and pointers refer to memory in the GTK-server and not in the forth engine.
The VARARGS argument is special. It expects different arguments for different calls. To implement this the gsv module expects for GTKserver calls with VARARGS a format string and the variable arguments.
For example if the next call is defined in the gtk-server.cfg:
FUNCTION_NAME = callWithVARARGS, NONE, NONE, 2, INT, VARARGS
you can call this function in Forth by:
s" String" 10 s" %d %q" 15 callWithVARARGS
in which case 15 is the normal INT argument and s" %d %q" defines the variable arguments. The values for the variable arguments are s" String" and 10.
Special attention should be given to the event handling by the GTK-server. The server links a default event to most widget types. If this default event is triggered, the widget ID is returned by gtk_server_callback. See the gtk-server.cfg file for the default event per widget type.
If another event triggering is necessary for a widget, the gtk_server_connect request must be used to connect an event to a widget. According to the gtk-server.cfg file, the type of the ID for this event is string, but this is not always convenient. So the gsv-module also defines: gsv+server-connect and gsv+server-connect-after. Those two words use the same parameters as the gtk_server_connect call, except that the event ID is numerically.
Events that are triggered, are returned to your program via the gtkservercallback request. According to the gtk-server.cfg file this request returns the event in a string. If you make sure that all events are numerically, you can easily convert the string event ID to a number and use the CASE - OF - ENDOF - ENDCASE construct to check which event is triggered. Most examples in the library use this method.
Another method is the use of the AVL binary tree. The key in this tree is the numerical event ID and the linked data is the execution token (XT) of the forth word that must be executed when the event is triggered. When an event is created, the event ID and the XT of the callback word are stored in the tree. In the mainloop the event ID, that is returned by gtkservercallback, is fed to the tree. The tree will return the callback XT which is then executed. See Menu for an example using this method.