System-Specific Interfaces
#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.
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.
The most recent X event.
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.
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.
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.
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!
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.
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.
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.
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.
Returns the XID for a window, or zero if not shown().
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.
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.
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.
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.
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.
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.
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.
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.
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.
The id of the window being dragged from.
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.
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.
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.
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).
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();
}