Robb Main wrote:
What I find hard to reconcile is:
1. I was told that fltk should be finished with the image to be displayed by
the time show() returns.
As Ian already wrote, that's not what Matthias wanted to tell you. I think you
mean the following from fltk.development [1].
You wrote: "However, if I call show() immediately after the constructor returns,
the image is not yet ready to display - it seems there the image is still being
decompressed / rendered."
Matthias replied: "There is no parallel processing when loading the image. It is
all ready as soon as your image loading function returns."
As Ian wrote, this should only be read as: The image loading from the image file
is complete. Everything is decompressed, all pixel info is loaded in memory.
However, no drawing happened when you load the image with
pBGImage = new Fl_PNG_Image( pszBGImage );
Matthias continued: "There will be a delay if you do not call Fl::flush(),
Fl::wait() or Fl::run() though."
This is "normal" GUI behavior. Please look at your constructor again. There is
no drawing. All drawing happens in your draw() method. But the draw() method
will not be called by show(). This is delayed until FLTK decides that there is
nothing else to do, and there are no more window messages (mouse movement,
keyboard events and so on). Then FLTK will eventually call your draw() method,
and your image will be rendered on the screen.
2. usleep() is a "system call", so it will put the current (fltk) application to sleep,
granting CPU cycles to any other running applications/processes/threads (i.e., X). So if fltk is
indead "finished with the image", WHY does sleeping the fltk application for a longer
period extend the delay? If the hold up was anything to do with X, one would expect a longer sleep
of the fltk processs would speed up the display, since X would get a larger share of the CPU.
X is a client-server protocol. In this case FLTK implements the client side and
sends messages to the X server and gets replies. This server can be on the local
node or on a remote host. In any case, there will be a delay between messages
and replies. Bringing a window on an X display needs more than one client/server
communication, and there you can see the delay. Making it simple, you can assume
that FLTK can send exactly one message to the X server when you call Fl::check()
once. Because there is a delay before the X server sends the reply, FLTK returns
control to you before the answer arrived. So far nothing visible may have
happened, but you call usleep with a 1 sec. delay. That's where the delay comes
from. Then, when you call Fl::check() again, FLTK sees the X server's reply and
sends the next message, and so on... One message per Fl::check() call.
Okay, that's only a model, and nothing real, but that's how it works in general.
My own suspicion is that there IS still some level of "background processing"
being done by fltk before the image will be displayed, that explains why usleep()
increases the delay, and why frequently yielding to background processing via wait() or
run(), etc. speeds up the delay.
Yes and no. This is the normal GUI behavior. You _must_ call the FLTK event
handling functions regularly, otherwise it will "hang". If you don't call
Fl::run() to let FLTK do it, you should really know what you're doing.
Which brings me to another question: does "Fl::Window->shown()" report true if
fltk THINKS the window is visible, or if it has ACTUALLY been rendered to the screen? (and
if the latter, how does it KNOW?)
FLTK doesn't "know". There is some delaying of message processing, e.g. there's
a flag "wait-for-expose" or similar, so that FLTK can delay drawing to a window
until it gets an "expose" event from the (X) windowing system, but this is what
FLTK does for you. You shouldn't need to know the details. And to answer your
question: Fl_Window::shown() is true directly after the show() call, even if the
window is not yet visible on the screen.
Back to your problem: As I wrote above, your image will be rendered on the
screen in your draw() method. To see what happens, you can add a print statement
to your draw() method and watch the output.
Then, if you want to be sure that your image has been drawn, you could add a
flag to your splash window class, let's call it "drawn_" and initialize it to 0
in the constructor, and set it to 1 when draw() is called. Then add a method
drawn() that returns the flag. With all this you can do:
splashWindow->show();
while (!splashWindow->drawn()) Fl::check();
This will wait until your window and the image is really rendered on the screen.
Just for curiosity I wrote a small variation of FLTK's hello.cxx demo program.
I'll append it to this message: see wait_check.cxx.
Under Windows (default gdi version) I see:
(1) an empty and _transparent_ window frame
(2) the rendered box with text
The output is:
window shown(): 1, visible(): 1, box visible(): 1
sleep 5.000 s ... drawn=0, Fl::check() # 1 ... MyBox::draw()... drawn=1
sleep 5.000 s ... drawn=1, Fl::check() # 2 ... drawn=1
sleep 5.000 s ... drawn=1, Fl::check() # 3 ... drawn=1
sleep 2.500 s ... drawn=1, Fl::check() # 4 ... drawn=1
setting new label: "Hello, World!"
sleep 0.000 s ... drawn=1, Fl::check() # 5 ... MyBox::draw()... drawn=2
This is what I would expect. The first Fl::check() call does all the drawing,
and changing the label triggers another draw.
Under Windows with a local X server I see:
(1) nothing (no window, first delay...)
(2) an empty window with a gray background
(3) the rendered box with text
The output is:
window shown(): 1, visible(): 1, box visible(): 1
sleep 5.000 s ... drawn=0, Fl::check() # 1 ... drawn=0
sleep 5.000 s ... drawn=0, Fl::check() # 2 ... MyBox::draw()... drawn=1
sleep 5.000 s ... drawn=1, Fl::check() # 3 ... drawn=1
sleep 2.500 s ... drawn=1, Fl::check() # 4 ... drawn=1
setting new label: "Hello, World!"
sleep 0.000 s ... drawn=1, Fl::check() # 5 ... MyBox::draw()... drawn=2
You can see that the first call of Fl::check() does NOT call MyBox::draw(),
although there are 5 seconds delay between the show() and Fl::check().
You should also see what happens, if you occlude the window with another window
between two Fl::check() calls, or if you minimize and restore it. With my cygwin
X server the window is "magically" redrawn (without calling draw() again), but
with native Windows draw() is called always after minimizing and after occlusion
by another window.
There are more options in the source file to discover. If you uncomment
while (!box->drawn()) my_sleep(0.001);
you will see something like:
window shown(): 1, visible(): 1, box visible(): 1
sleep 0.001 s ... drawn=0, Fl::check() # 1 ... drawn=0
sleep 0.001 s ... drawn=0, Fl::check() # 2 ... MyBox::draw()... drawn=1
sleep 5.000 s ... drawn=1, Fl::check() # 3 ... drawn=1
sleep 5.000 s ... drawn=1, Fl::check() # 4 ... drawn=1
sleep 5.000 s ... drawn=1, Fl::check() # 5 ... drawn=1
With a remote (LAN) X server I could see that the first draw() call happened
somewhere between the 3rd and the 9th Fl::check() call (with 0.001 sec. delay).
With another remote X server over a VPN (internet) I just saw that it took up to
98 Fl::check() calls before draw() was called.
If you intend to do initialization work and show a progress bar, you must call
Fl::wait() or Fl::check() at regular/short intervals, otherwise strange things
may happen.
Albrecht
[1] http://www.fltk.org/newsgroups.php?gfltk.development+v:7784
//
// This is a modified version of FLTK's test/hello.cxx
//
// Hello, World! program for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2009 by Bill Spitzak and others.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please *DO* *NOT* report bugs and problems on the following page:
//
// http://www.fltk.org/str.php
//
// ===================================================================
//
// This modified version is intended to show differences of drawing
// that are operating system dependent.
//
// compile, link, and run with:
//
// fltk-config --compile wait_check.cxx && ./wait_check
//
// Note to Windows users: You won't see any output, unless you use
// MinGW or Cygwin (gcc) to compile and link this program (and run
// it from a command shell).
//
// If you're using VC++ or maybe other tools, you may try to redirect
// the output to a file, like (in a "DOS" window)
// C:\> wait_check > test.txt
//
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <stdio.h> // printf
#ifdef WIN32
# include <windows.h>
#else
# include <unistd.h>
#endif
class MyBox : public Fl_Box {
int drawn_;
protected:
void draw ();
public:
MyBox (Fl_Boxtype,int,int,int,int,char *);
int drawn() {return drawn_;}
};
MyBox::MyBox (Fl_Boxtype B, int X, int Y, int W, int H, char *L)
: Fl_Box (B,X,Y,W,H,L), drawn_(0) {}
void MyBox::draw() {
printf ("MyBox::draw()... ");
Fl_Box::draw();
drawn_++;
}
static Fl_Window *window = 0;
static MyBox *box = 0;
// special sleep function
void my_sleep(double secs) {
static int count = 0;
printf("sleep%7.3f s ... ",secs);
int msec = int(secs*1000.);
#ifdef WIN32
Sleep (msec);
#else
usleep (msec * 1000);
#endif
printf ("drawn=%d, Fl::check() # %d ... ",box->drawn(),++count);
Fl::check();
printf("drawn=%d\n",box->drawn());
if (!window->shown()) {
printf ("*** window has been closed, exiting ...\n");
exit(0);
}
}
int main(int argc, char **argv) {
window = new Fl_Window(300,180);
box = new MyBox(FL_UP_BOX,20,40,260,100,"Testing ...");
box->labelfont(FL_BOLD+FL_ITALIC);
box->labelsize(36);
box->labeltype(FL_SHADOW_LABEL);
window->end();
window->show(argc, argv);
setvbuf (stdout,NULL,_IONBF,0); // stdout unbuffered
printf ("window shown(): %d, visible(): %d, box visible(): %d\n",
window->shown(),window->visible(),box->visible());
// remove the comment from the following while loop to see what
// happens (if you can, try this on Windows and with X)
// wait until box is drawn ...
// while (!box->drawn()) my_sleep(0.001);
// if you remove the comment from the following line, then the
// window will be displayed for 1 second, and the program will
// exit after this.
// my_sleep(1); window->hide(); my_sleep(0);
// while the program is running, try to see what is different, if
// you occlude the box part of the display or if you minimize the
// window ...
my_sleep(5);
my_sleep(5);
my_sleep(5);
my_sleep(2.5);
printf("setting new label: \"Hello, World!\"\n");
box->label("Hello, World!");
my_sleep(0);
return Fl::run();
}
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk