TnFOX is a fork of FOX which can be found at
http://www.fox-toolkit.org/
TnFOX maintains virtually the same API as FOX though there are differences especially in the i/o and threading classes. Generally speaking, you should be able to compile your FOX application against TnFOX without incident as those classes which have been deprecated have thunk replacements implemented in the new code.
However, for various reasons, some semantic changes did need to happen:
- Anything using the FOX i/o classes may break. An emulation thunking to TnFOX's much superior replacements is good enough that FOX code itself doesn't know any better and so neither should your code.
- FX::FXTime is a class in TnFOX, representing a much finer time quantity than FOX's which is only per-second granularity. This can cause some trivial compile errors which were deliberately caused as often you must slightly adjust your code to use FX::FXTime::as_time_t().
- All the file metadata functions in FX::QFile return metadata for symbolic links, not for what the link points to. This can subtly break some FOX code (but it was necessary to add NTFS junction support).
- FOX's threading support was added substantially after TnFOX's and are not compatible. Through the FOX compatibility layer, a FOX compatible API is provided which thunks through to TnFOX's threading code. Note however that thread cancellation is not supported when using this emulation.
- The exception types FX::FXWindowException, FX::FXImageException and FX::FXFontException are FOR COMPATIBILITY WITH FOX ONLY. They are NOT LIKE NORMAL TNFOX EXCEPTIONS in that they are thrown from within FOX code which is not exception safe. While they have been marked as fatal exceptions, you may need to take action within your code to make very sure you do not attempt recovery from these exceptions. I did wonder about not deriving them from FX::FXException so that they'd definitely fatally exit the process, but decided that it's probably best if they are actually trappable.
- You should put a
FXProcess myprocess(argc, argv);
directly after your main()
but before creating your FXApp.
- Try to use FX::FXHandedDialog and FX::FXHandedPopup, they are so much more user friendly. Similarly have your buttons and such observe FX::FXWindow::userHandednessLayout(). FX::FXHandedMsgBox has replaced FX::FXMessageBox which is marked as deprecated.
DEFAULT_PAD
and DEFAULT_SPACING
no longer exist. Their replacement is either FX::FXWindow::defaultPadding() or FX::FXWindow::defaultSpacing(). This has been done to support small displays. You shouldn't notice the change as there are DEFAULT_PAD
and DEFAULT_SPACING
macros which point to the new code. However, you should test your code after porting to TnFOX with the -fxscreenscale=25% argument.
- All friend functions of FX::FXVecXX classes have had 'vec' prefixed before them. This was primarily to aid the python bindings where the names were clashing with python ones, but I think it is more clear anyway.
- FX::FXApp has had its event loop dispatch code split off into FX::FXEventLoop and thus some things are no longer available through FXApp. This in practice should require no source changes to your code if you are not using per-thread event loops.
- FX::FXId, and thus all derivative classes (eg; windows) now maintain what event loop it was created within.
- As TnFOX permits multiple window trees to run across multiple threads, you must not use static variables to store state in your GUI widgets unless it's read-only. Use FX::FXEventLoop_Static instead like as follows:
static FXEventLoop_Static<MyObj> pvar;
if(!pvar) pvar=new MyObj;
MyObj &var=*pvar;
- FXApp::reg() is synchronised for you as FX::FXSettings locks FXApp during its operation. However as it can return
const char *
, there is the possibility that one thread deletes an item just after another thread fetches it and so the pointer is left dangling. If this is a possibility you must lock FXApp yourself until you are done with the string.
- If you wish to run multiple event loops, you must initialise a FX::TnFXApp instead of a FX::FXApp in your code and change your
main()
slightly. See the docs for FX::TnFXApp.
- Lastly, the TnFOX extensions are exception aware whereas none of FOX is. Therefore, if you call any TnFOX code where a path exists up the call stack going through FOX code (eg; a GUI event handler) then you must surround that code with the FXEXCEPTION_FOXCALLING1 and FXEXCEPTION_FOXCALLING2 macros. These trap any exceptions thrown and show a FX::FXExceptionDialog.
Summary of what is not supported from FOX v1.6.x:
- Some FX::FXStream methods. You'll never normally notice these
- The application wide mutex. It's a bad idea anyway.
You should also see
What are the differences in a no-FOX compatibility build?