![]() |
Documentation: The Application Class
![]() |
The FXApp Class
![]() |
Using the code below, the application object will be constructed on the stack and hence is automatically destroyed when the program terminates. Also, when the application object is destroyed, all the windows and other resources it knows about are destroyed as well.
int main(int argc,char *argv[]){ // Make application
// Open display
// Make window
// Create it
// Show Window
// Run
|
In the first line of code above, an application object is constructed. The constructor has two parameters, the application name, and the vendor name. The application name and vendor name are used to determine the applications registry settings.
The next line of code initializes the application object, passing in the command line arguments of the process. The application object parses its own arguments and removes them, but leaves the remaining arguments alone.
The next line creates a toplevel window, passing in a pointer to the application object.
The call to the application object's create()
function realizes the entire widget tree, i.e. creates the necessary resources
in the system (X Server or Windows GDI), to turn what was up till that
point a collection of C++ data structures into a real-life application
which is able to
receive events and draw on the screen.
The final call to run() starts the toplevel event loop. A typical application will not return from this loop until the user closes the application.
Event Loops
![]() |
The events a GUI program processes can be of different types:
The application object is solely responsible for coordinating all these events and dispatching them to the proper destination where they are handled.
FXApp performs delayed repaints on windows, i.e. almost all events are prioritized over repaint events so as to delay expensive redrawing as much as possible. Because of this, repainting can never fall behind more than one repaint, and needless repaints are avoided as much as possible. Also FXApp combines repaint rectangles so as to minimize the video card hardware setup and teardown time relative to the number of pixels drawn.
Event Queues
![]() |
Finally, the X server may have its own event queue and drawing queue, making for a total of four queues. All these queues allow for much faster performance of applications, as bigger chunks of data can be transmitted between the application and the X server, and fewer context switches of video card and cpu hardware are needed.
From the point of programming in FOX, the existence
of these queues is for the most part hidden, but in a few cases some special
functions are available that you may need to call:
FXApp::flush(sync)This function flushes the output queue, i.e. the commands which have been already performed are pushed to the X server, where they are executed.
If we want to make sure that the display shows the correct picture, however, just pushing the commands to the X server is not enough:- sometimes we need to make sure that these commands have been executed before we continue!
When a TRUE is passed for the sync parameter, the X server is forced to execute these commands.
FXApp::peekEvent()This function will return TRUE if there are any events ready to process, and FALSE if there are none. The peekEvent() function can be used when we are doing a long calculation and we want to check if the user has hit the STOP button.
Types of Event Loops
![]() |
FXApp::run()This is the top level event loop, and it will only terminate when the application is ready to call it quits. When run() finally returns, its return value is the exit value passed to stop() earlier.
FXApp::stop(code)
This function terminates the top level event loop, but also terminates all nested event loops which have been directly or indirectly invoked from this top level loop. Each nested loop is terminated with a code of zero (0), but the top level event loop is terminated with the given code.
FXApp::runOneEvent()
As the name implies, this function reads and then processes one (1) single event, and then returns. It is primarily interesting to use in combination with peekEvent(), as peekEvent() returns TRUE if there is at least one event ready to be processed.
If there is no event ready, runOneEvent() will block until there is at least one event.FXApp::runUntil(condition)
This function processes events until the variable condition, which is passed as a reference, becomes non-zero.
In FOX, the only difference between normal
dialogs and modal dialogs is how they are run:- modal dialogs are
run by calling:
FXApp::runModalFor(window)This function runs a nested or recursive invocation of the event loop, i.e. it re-enters an event loop and processes events for a while, and returns only when stopModal() or stop() is called.
As long as runModalFor() is running, user-input events to all other windows, except for window and its children, are being blocked:- no interaction with other windows is possible until runModalFor() returns.
When it returns, it returns the value passed to the stopModal() function, or 0 if stop() is called to terminate the application.
However, it is quite possible, and in fact common, that one modal dialog invokes another. In that case, only the most recently invoked dialog can be interacted with.FXApp::runModalWhileShown(window)
The function runModalWhileShown() runs until either stopModal() is called or the specified window becomes hidden. This is of interest when running popup menus or other temporary windows.
FXApp::stopModal(window,code)
Calling stopModal() causes the modal event loop with the matching window to terminate with code. However, stopModal() also causes all modal event loops which are nested more deeply to terminate with code zero (0).
FXApp::isModal(window)
This function returns TRUE if a modal loop is in effect for the given window.
Modal dialogs are always run with runModalFor(). Because it is so common to construct a dialog on the stack, run it modally, and then process the inputs thus obtained, there is a convenience member function FXDialogBox::execute() which calls create(), show(), and then runModalFor() in turn.
The FXDialogBox also understands several messages, for example ID_ACCEPT, ID_CANCEL, and SEL_CLOSE which call stopModal() returning a code 1, 0, and 0 respectively.
The return code 0 for FXDialogBox::execute()
should never cause any action to be performed
as it is the code returned when the dialog box is cancelled or closed!!
GUI Updating
![]() |
The GUI update is normally started by calling:
FXApp::refresh()This function reschedules another GUI update to be performed in the future.
FXApp::forceRefresh()
Calling this function will cause an immediate GUI update pass to be performed. Unlike the normal GUI update, which takes place unobstrusively one and a time, prior to blocking, forceRefresh() will not return until all windows have been refreshed.
It is therefore quite expensive, and should be used only when strictly necessary.
The GUI update has no impact on the perceived speed of an application because between each pair of GUI updates performed, a check for events is performed.
Visuals
![]() |
Besides depth (number of bits/pixel), there are also other characteristics which come into play describing the pixel organization, such as colormaps, and wether or not a colormap can be written or not, and the byte and bit organization.
Colormaps are commonly used on 8-bit/pixel systems. Most hardware only supports one hardware colormap, and this must be shared among all programs on the display. Because legacy toolkits such as Motif do not deal with full colormaps very gracefully, FOX applications deliberately do not try to grab all 256 colors from the colormap, but only 125 colors. Images and Icons are dithered to get the best possible rendering given the number of colors available.
You can improve the look of your program quite easily, however, as the maximum number of colors which the default visual tries to allocate can be easily changed using a command line argyment; for example, "myapp -maxcolors 256" will start myapp in such a way as to attempt to acquire all 256 colors from the colormap.
Because other programs may already be running, the desired gamut of colors may not be available. If the exact color can not be obtained, FOX will try to find the closest color available and use that.
Normally, the FXVisual a window uses is copied
from its parent. You can change this visual for each window, or you
can call:
FXApp::setDefaultVisual(visual)This function will change the default visual to be used for all toplevel windows; the child-windows will simply inherit the visual from their parent.
Wait Cursors
![]() |
FXApp supports this by means of the following
functions:
FXApp::beginWaitCursor()This will change the cursor shape for all windows to the stopwatch cursor, or the cursor designated by setWaitCursor(). Calls to beginWaitCursor() and endWaitCursor() can be nested in a stack-like fashion, with only the first call to beginWaitCursor() and last call to endWaitCursor() actually changing the cursor shape.
FXApp::endWaitCursor()
A matching call to endWaitCursor() will restore the original cursor for each window.
FXApp::setWaitCursor(cursor)
This will change the cursor shape used in during a beginWaitCursor() endWaitCursor() pair.
FXApp::getWaitCursor()
This returns the current FXCursor being used as hourglass or stopwatch cursor.
Drag Types
![]() |
Manipulating drag types is done with the following API's:
FXApp::registerDragType(name)
This will register a new drag type based on the mime type name.
FXApp::getDragTypeName(dragtype)
Obtain the name of a previously registered drag type.