F - Operating System Issues


X-Specific Interface

On X you can include this file to access FLTK's X-specific functions. Be warned that some of the structures and calls in it are subject to change in future version of FLTK. Try to avoid doing this so your code is portable.

void Fl::add_handler(int (*f)(int))

Installs a function to parse unrecognized events. If FLTK cannot figure out what to do with an event, it calls each of these functions (most recent first) until one of them returns non-zero. If none of them returns non-zero then the event is ignored.

FLTK calls this for any X events it does not recognize, or X events with a window id that FLTK does not recognize, or for events when the widget's handle function returns zero. You can look at the X event with the fl_xevent variable.

The argument is the event number (like FL_PUSH). For X events that fltk does not understand, it is zero. For keystrokes it will be FL_SHORTCUT.

extern XEvent* fl_xvent

The most recent X event.

extern ulong fl_event_time

This is the time stamp from the most recent X event that reported it (not all do). Many X calls (like cut and paste) need this value.

int fl_handle(const XEvent &)

This call allows you to supply the X events to FLTK, which may allow FLTK to cooperate with another toolkit or library. The return value is true if FLTK understood the event (if the window does not belong to FLTK and the add_handler() functions all ignore it this returns false).

Besides feeding events your code should call Fl::flush() periodically so that FLTK redraws its windows.

This function will call the callback functions. It will not return until they complete. In particular if a callback pops up a modal window (by calling fl_ask(), for instance) it will not return until the modal function returns.

int Fl::display(const char*)

Set which X display to use. This actually does putenv("DISPLAY=...") so that child programs will display on the same screen if called with exec(). This must be done before fl_open_display is called. This call is provided under WIN32 but it has no effect.

void fl_open_display()

Opens the display. Does nothing if it is already open. You should call this if you wish to do X calls and there is a chance that your code will be called before the first show() of a window. This is called automatically by Fl_Window::show().

This may call Fl::abort() if there is an error opening the display.

void fl_open_display(Display*)

You can make fltk "open" a display that has already been opened, perhaps by another GUI library. Calling this will set fl_display to the passed display and also read information fltk needs from it. You can only call this once.

extern Display* fl_display

The open X display. This is needed as an argument to most Xlib calls. Don't attempt to change it! This is NULL before fl_open_display is called.

extern Window fl_message_window

This dummy 1x1 window is created by fl_open_display() and is never destroyed. You can use it to communicate with the window manager or other programs.

extern int fl_screen

Which screen number to use. This is set by fl_open_display() to the default screen. You can change it by setting this to a different value immediately afterwards.

extern XVisualInfo* fl_visual
extern Colormap fl_colormap

The visual and colormap that FLTK will use for all windows. These are set by fl_open_display() to the default visual and colormap. You can change them before calling show() on the first window. Typical code for changing the default visual is: You may also want to call Fl::visual(), which is a portable interface to get a full color and/or double buffered visual.

Window fl_xid(const Fl_Window*)

Returns the XID for a window, or zero if not shown().

Fl_Window* fl_find(ulong xid)

Returns the Fl_Window that corresponds to the given XID, or NULL if not found. This uses a cache so it is slightly faster than iterating through the windows yourself.

extern Window fl_window;
extern GC fl_gc;

These variables are set before Fl_Widget::draw() is called, or by Fl_Window::make_current(). They are needed by most Xlib drawing calls, a typical call is like this:

Notice that fl_window is the X window id number. Other information such as the position or size of the X window can be found by looking at Fl_Window::current(), which returns a pointer to the Fl_Window being drawn.

unsigned long fl_xpixel(Fl_Color i)

Returns the X pixel number used to draw the given FLTK color index or RGB color. This is the X pixel that fl_color(i) would use.

extern XFontStruct* fl_xfont

Points at the font selected by the most recent fl_font(). This is not necessarily the current font of fl_gc, which is not set until fl_draw() is called.

void fl_close_display()

This closes the X connection. You do not need to call this to exit, and in fact it is faster to not do so! It may be useful to call this if you want your program to continue without the X connection. You cannot open the display again, and probably cannot call any FLTK functions.

static void Fl_Window::xclass(const char*)
static const char* Fl_Window::xclass() const

This string is used to set the XA_WM_CLASS property of all the windows fltk creates. The default value is "fltk". Many window managers can use this string to select an icon. Fl::args(...) will set this to the name of the program.

This call is provided on WIN32 for compatability, but the value is ignored.

void Fl_Window::icon(char*)

Sets the icon for the window to the passed pointer. You will need to cast the icon Pixmap to a char* when calling this method. To set the icon using a bitmap compiled with your application use:

This only works if called before it is shown using the Fl_Window::show() method.

Using a Subclass of Fl_Window for Special X Stuff

FLTK can manage an X window on a different screen, visual and/or colormap, you just can't use FLTK's drawing routines to draw into it. But you can write your own draw() method that uses Xlib (and/or OpenGL) calls only.

To do this, you need to make a subclass of Fl_Window and override some of these virtual functions:

virtual void Fl_Window::create()

Creates the X window, and perhaps other data such as colormaps needed by this window. To create the X window you must call Fl_X::create(). Do not map the window, fltk does that for you.

An example:

void Fl_X::create(Fl_Window*, XVisualInfo*, Colormap, int background=-1)

This function calls XCreateWindow and sets things up so that fl_xid(window) returns the created window id. This also does a lot of other ugly X stuff, including setting the label, resize limitations, etc. The background is a pixel to use for X's automatic fill color, use -1 to indicate that no background filling should be done.

virtual void Fl_Window::flush()

This virtual function is called by Fl::flush() to update the window. For FLTK's own windows it does this by setting the global variables fl_window and fl_gc and then calling the draw() method. For your own windows you might just want to put all the drawing code in here.

The X region that is a combination of all damage() calls done so far is in Fl_X::i(this)->region. If NULL then you should redraw the entire window. The undocumented function fl_clip_region(XRegion) will initialize the FLTK clip stack with a region or NULL for no clipping. You must set region to NULL afterwards as fl_clip_region() now owns it and will delete it when done.

If damage() == FL_DAMAGE_EXPOSE then only X expose events have happened. This may be useful if you have an undamaged image (such as a backing buffer) around.

Here is a sample where an undamaged image is kept somewhere:

virtual void Fl_Window::destroy()

Destroy the window server copy of the window. Usually you will destroy contexts, pixmaps, or other resources used by the window, and then call Fl_Window::hide() to get rid of the main window identified by xid(). If you override this, you must also override the destructor as shown:

virtual void Fl_Window::~Fl_Window()

Because of the way C++ works, if you override destroy() you must override the destructor as well (otherwise only the base class destroy() is called):

WIN32-Specific Interface

The <FL/x.H> header file defines the interface to FLTK's WIN32-specific functions. Be warned that some of the structures and calls in it are subject to change in future version of FLTK. Try to avoid doing this so your code is portable.

Fltk creates a single WNDCLASSEX called "FLTK". The window class is created the first time Fl_Window::show() is called.

You can probably combine FLTK with other libraries that make their own WIN32 window classes. The easiest way is to call Fl::wait(), it will call DispatchMessage for all messages to the other windows. If necessary you can let the other library take over (as long as it calls DispatchMessage()), but you will have to arrange for the function Fl::flush() to be called regularily so that widgets are updated, timeouts are handled, and the idle functions are called.

void Fl::add_handler(int (*f)(int))

Install a function to parse unrecognized messages sent to FLTK windows. If FLTK cannot figure out what to do with a message, it calls each of these functions (most recent first) until one of them returns non-zero. The argument passed to the fuctions is zero. If all the handlers return zero then FLTK calls DefWindowProc().

extern MSG fl_msg

The most recent message read by GetMessage (which is called by Fl::wait(). This may not be the most recent message sent to an FLTK window (because our fun-loving friends at MicroSoft decided that calling the handle procedures directly would be a good idea sometimes...)

HWND fl_xid(const Fl_Window*)

Returns the window handle for a Fl_Window, or zero if not shown().

Fl_Window* fl_find(HWND xid)

Return the Fl_Window that corresponds to the given window handle, or NULL if not found. This uses a cache so it is slightly faster than iterating through the windows yourself.

extern HINSTANCE fl_display;

This is set on program initialization to GetModuleHandle(0) and can be used to identify this application.

extern HWND fl_window;
extern HDC fl_gc;

These are set before draw() is called, or by Fl_Window::make_current(), and can be used as arguments to GDI32 calls.

Notice that fl_window is the window handle. Other information such as the position or size of the window can be found by looking at Fl_Window::current(), which returns a pointer to the Fl_Window being drawn.

extern COLORREF fl_rgb;
extern HPEN fl_pen;
extern HBRUSH fl_brush;

These are set by fl_color() and by fl_line_style(), by using these in your drawing calls you can provide the illusion that GDI has a color in it's graphics state.

void Fl_Window::icon(char*)

Sets the icon for the window to the passed pointer. You will need to cast the HICON handle to a char* when calling this method. To set the icon using an icon resource compiled with your application use:

This only works if called before it is shown using the Fl_Window::show() method.

How to Not Get a MSDOS Console Window

WIN32 has a really stupid mode switch stored in the executables that controls whether or not to make a console window.

To always get a console window you simply create a console application (the "/SUBSYSTEM:CONSOLE" option for the linker). For a GUI-only application create a WIN32 application (the "/SUBSYSTEM:WINDOWS" option for the linker).

FLTK includes a WinMain() function that calls the ANSI standard main() entry point for you. This function creates a console window when you use the debug version of the library.

WIN32 applications without a console cannot write to stdout or stderr, even if they are run from a console window. Any output is silently thrown away. We are not sure why, but we do question the sanity of the software engineers there sometimes.

Known Bugs

If a program is deactivated, Fl::wait() does not return until it is activated again, even though many events are delivered to the program. This can cause idle background processes to stop unexpectedly. This also happens while the user is dragging or resizing windows or otherwise holding the mouse down. I was forced to remove most of the efficiency FLTK uses for redrawing in order to get windows to update while being moved. This is a design error in WIN32 and probably impossible to get around.

Cut text contains ^J rather than ^M^J to break lines. This is a feature, not a bug.