System-Specific Interfaces

X11/Unix

#include <fltk/x.h>

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 fltk::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. The argument is the event number (like fltk::PUSH). For keystrokes it will be fltk::SHORTCUT.

Besides events that all widgets ignored, FLTK calls this for X events that it does not recognize, or that contain a window id that FLTK does not know about. In this case the argument is zero. You can look at the X event with the fltk::xevent variable.

extern XEvent* fltk::xvent

The most recent X event.

extern ulong fltk::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 that reported it (not all do). Many X calls (like cut and paste) need this value.

int fltk::handle(const XEvent &)

This allows you to "feed" X events to fltk, in cases where you cannot give fltk control over any file descriptors. Fltk will figure out what the event is and call widgets normally and also the fltk::add_handler() functions. The return value is true if a widget accepted the event or one of the add_handler() function returned true.

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

This function will call any widget callbacks from the widget code. It will not return until they complete, for instance if it pops up a modal window with fltk::ask(), it will not return until the user clicks yes or no.

int fltk::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 fltk::open_display is called. This call is provided under WIN32 but it has no effect.

void fltk::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 fltk::Window::show().

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

void fltk::open_display(Display*)

You can make fltk "open" a display that has already been opened, perhaps by another GUI library. Calling this will set fltk::display to the passed display and also read information fltk needs from it. Don't call this if the display is already open!

extern Display* fltk::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 fltk::open_display is called.

extern Window fltk::message_window

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

extern int fltk::screen

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

extern XVisualInfo* fltk::visual
extern Colormap fltk::colormap

The visual and colormap that FLTK will use for all windows. These are set by fltk::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:
fltk::args(argc, argv); // do this first so $DISPLAY is set
fltk::open_display();
fltk::visual = find_a_good_visual(fltk::display, fltk::screen);
if (!fltk::visual) fltk::abort("No good visual");
fltk::colormap = make_a_colormap(fltk::display, fltk::visual->visual, fltk::visual->depth);
// it is now ok to show() windows:
window->show(argc, argv);
You may also want to call fltk::visual(), which is a portable interface to get a full color and/or double buffered visual.

Window fltk::xid(const fltk::Window*)

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

fltk::Window* fltk::find(ulong xid)

Returns the fltk::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 fltk::window;
extern GC fltk::gc;

These variables are set before fltk::Widget::draw() is called, or by fltk::Window::make_current(). They are needed by most Xlib drawing calls, a typical call is like this:
XDrawSomething(fltk::display, fltk::window, fltk::gc, ...);

Notice that fltk::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 fltk::Window::current(), which returns a pointer to the fltk::Window being drawn.

Region fltk::clip_region();

Return the current clip region, or NULL if we are currently clipping to the entire window. Notice that this will be destroyed by the next change to the clipping, copy it if you want to keep it.

void fltk::clip_region(Region);

Replace the current clip region with this one, or make there be no clipping if NULL is passed. The old clip region is destroyed.

unsigned long fltk::xpixel(fltk::Color i)

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

extern XFontStruct* fltk::xfont

Points at the font selected by the most recent fltk::font(). This is not necessarily the current font of fltk::gc, which is not set until fltk::draw() is called.

void fltk::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 fltk::Window::xclass(const char*)
static const char* fltk::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. fltk::args(...) will set this to the name of the program.

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

void fltk::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:
#include "icon.xbm"

Pixmap p = XCreateBitmapFromData(fltk::display, DefaultRootWindow(fltk::display),
                                 icon_bits, icon_width, icon_height);

window->icon((char*)p);

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

Drag & Drop information

The fltk::dnd_* variables allow your fltk program to use the Xdnd protocol to manipulate files and interact with file managers. You can ignore these if you just want to drag & drop blocks of text. I have little information on how to use these, I just tried to clean up the Xlib interface and present the variables nicely.

Window fltk::dnd_source_window

The id of the window being dragged from.

Atom fltk::dnd_source_action

The action the source program wants to perform. Due to oddities in the Xdnd design this variable is not set on the fltk::DND_ENTER event, instead it is set on each fltk::DND_DRAG event, and it may change each time.

To print the string value of the Atom use this code:

char* x = XGetAtomName(fltk::display, fltk::dnd_source_action);
puts(x);
XFree(x);

You can set this before calling fltk::dnd() to communicate a different action. See fltk::dnd_source_types, which you must also set.

Atom fltk::dnd_action

The program can set this before returning non-zero for an fltk::DND_DRAG event to indicate what it will do to the object. Fltk presets this to XdndActionCopy so that is returned if you don't set it.

Atom *fltk::dnd_source_types

Zero-terminated list of atoms describing the formats of the source data. This is set on the fltk::DND_ENTER event. The following code will print them all as text, a typical value is "text/plain;charset=UTF-8" (gag).
for (int i = 0; fltk::dnd_source_types[i]; i++) {
  char* x = XGetAtomName(fltk::display, fltk::dnd_source_types[i]);
  puts(x);
  XFree(x);
}

You can set this and fltk::dnd_source_action before calling fltk::dnd() to change information about the source. You must set both of these, if you don't fltk will default to "text/plain" as the type and XdndActionCopy as the action. To set this change it to point at your own array. Only the first 3 types are sent. Also, fltk has no support for reporting back what type the target requested, so all your types must use the same block of data.

Atom fltk::dnd_type

The program can set this when returning non-zero for an fltk::DND_RELEASE event to indicate the translation wanted. Fltk presets this to "text/plain" so that is returned if you don't set it (supposedly it should be limited to one of the values in fltk::dnd_source_types, but "text/plain" appears to always work).

Using a Subclass of fltk::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 fltk::Window and override some of these virtual functions:

virtual void fltk::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 fltk::X::create(). Do not map the window, fltk does that for you.

An example:

void MyWindow::create() {
  fltk::open_display();	// necessary if this is first window
  // we only calcualte the necessary visual & colormap once:
  static XVisualInfo* visual;
  static Colormap colormap;
  static int background;
  if (!visual) {
    visual = figure_out_visual();
    colormap = XCreateColormap(fltk::display, RootWindow(fltk::display,fltk::screen),
			        vis->visual, AllocNone);
    XColor xcol; xcol.red = 1; xcol.green = 2; xcol.blue = 3;
    XAllocColor(fltk::display, colormap, &xcol);
    background = xcol.pixel;
  }
  fltk::X::create(this, visual, colormap, background);
}

void fltk::X::create(fltk::Window*, XVisualInfo*, Colormap, int background=-1)

This function calls XCreateWindow and sets things up so that fltk::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 fltk::Window::flush()

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

X Expose events (and calls to expose() of the window or any widget inside it) turn on the fltk::DAMAGE_EXPOSE bit in damage(), and the regions of all of them are are accumulated into an X region that you can get from fltk::X::i(this)->region. This is set to NULL if the entire window is damaged. The undocumented function fltk::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 fltk::clip_region() now owns it and will delete it when done.

Any other bits set in damage() indicate calls to redraw() were done. Notice that the damaged items may be outside the fltk::X::i(this)->region.

If damage() == fltk::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:

void MyWindow::flush() {
  if (damage() == fltk::DAMAGE_EXPOSE) {
    fltk::clip_region(fltk::X::i(this)->region);
    fltk::X::i(this)->region = 0;
    copy_image(backing_store_pixmap, fltk::xid(this));
  } else {
    fltk::window = backing_store_pixmap;
    fltk::gc = backing_store_gc;
    this->draw();
    copy_image(backing_store_pixmap, fltk::xid(this));
  }
}

virtual void fltk::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 fltk::Window::hide() to get rid of the main window identified by xid().
void MyWindow::destroy() {
  if (backing_store_pixmap) {
    XFreePixmap(fltk::display, backing_store_pixmap);
    backing_store_pixmap = 0;
  }
  fltk::Window::destroy(); // you must call this
}

virtual void fltk::Window::~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):
MyWindow::~MyWindow() {
  destroy();
}