Anybody know of a way to get a Gtk+ widget to draw itself to a pixmap (of my choosing) rather than its GdkWindow? Or a way to raise an expose event on a GdkWindow while its backing store is a pixmap (again, of my choosing)?
The problem is, I've got a program with some graphs in it. The graphs clear about once a day (give or take), and I want to be able to save them to a PNG file just before that happens. The actual saving to PNG format is not an issue -- the issue is what to do when my program's window is either iconified or not fully exposed. If it's iconified, my code will probably segfault (because the GtkWidget's ->window member will likely be NULL and I'm using ->window to get a pixmap to save), though I haven't specifically tried it yet. If it's not fully exposed, then I get random pixels in the pixmap (and therefore in the PNG file, since I generate the PNG file from the pixmap).
The problem is that if the X11 window doesn't have its backing_store attribute set to either Always or WhenMapped (NotUseful, the only other option, is the default), then the X server throws away the non-visible parts of that window when those parts get un-exposed. But setting backing_store to Always or WhenMapped doesn't seem to help, probably because neither of those settings is a guarantee that the X server will keep a backing store for your window. They're just hints.
So, if there's a way to get a widget to repaint itself onto a pixmap of my creation, that would be a heck of a lot better -- it would be a tiny bit slower, but it'd still work if it was not fully exposed or iconified. It would be possible to use gtk_window_present, but then users would have my program popping itself to the foreground about once a day -- decidedly not the nicest way to do it, so I'd rather not..
I know Gdk calls a gdk_window_begin_paint_region() function before generating expose events, so that drawing happens to a pixmap, then it calls gdk_window_end_paint() to blast that pixmap up to the server all in one shot to reduce flicker. So there has to be some way to do it. Looking at the ..._begin_paint_region source, though, leaves me more than a little confused. I think that doing it that way is a little too close to the implementation details of Gdk, though if there aren't any other alternatives then I suppose I could try it...
Thanks!
GaryJones32
02-24-2004, 09:01 PM
don't know if this helps but the docs say
gdk_pixmap_colormap_create_from_xpm_d ()
lets you pass in a colormap and the window can be NULL
as you say rather than getting into the guts of gdk
Havoc Pennington is always telling people to just use
Imlib directly when they ask questions like this.
bwkaz
02-24-2004, 11:05 PM
Originally posted by GaryJones32
don't know if this helps but the docs say gdk_pixmap_colormap_create_from_xpm_d () lets you pass in a colormap and the window can be NULL Thanks, but I'm not sure how to apply that. The colormap isn't the problem -- I can use the X server's default colormap without issue.
The problem is that I can't seem to get at the pixels unless they're rendered on the screen (as opposed to behind another window).
Havoc Pennington is always telling people to just use Imlib directly when they ask questions like this. (Should I know who that is? I don't... :o One of the Gdk/Gtk developers?)
The Enlightenment Imlib2 page has a big list of "things that Imlib2 can do". I don't see "take an X-Win drawable and save it to a file" anywhere, though maybe I'm looking for the wrong thing.
In other words, how would you use Imlib to do the screenshots? Basically, the constraint is that the widget doesn't have to be visible. Any ideas would be welcome, I just don't really have enough information about what you've proposed. :)
psi42
02-24-2004, 11:49 PM
Originally posted by bwkaz
(Should I know who that is? I don't... :o One of the Gdk/Gtk developers?)
He's the guy that wrote GTK+/Gnome Application Development (which I have not read yet) and "a frequent contributor to the GTK and Gnome mailing lists."
bwkaz
02-25-2004, 06:47 PM
Ah, OK. Good enough for me -- if Imlib can do it, I'll use Imlib. ;)
I also found a bunch more stuff that Havoc has written, after Googling his name. Duh, should've tried that earlier. Most of it seems to be essays on good UI design -- definitely something I should read eventually...
GaryJones32
02-26-2004, 02:03 AM
perhaps there is something i'm missing like always
(i'm not actually doing this so it's easy to see solutions that don't work)
if the image is in a GdkPixbuf *pixbuf
then their are your pixels
I'm trying to figure out how to get the image into the GdkPixbuf, though. ;)
Basically, libpng works the same way as your Imlib example -- except that it needs a 2D array rather than a 1D string of bytes, but that's easy enough to fake. The problem is that the contents of the GdkDrawable that I'm using to create the GdkPixmap (since a pixmap is client-side, and I need to get the pixels from the server) aren't accessible when my program's window is behind something else.
Maybe some example code would help to clarify what the issue is. This is the code that actually does the save (it gets called either when the user clicks the "save screenshot" button, in which case the widget's visible, or when the automatic screenshot code is finished doing its processing):
return FALSE; The problem is in the first snippet -- the GdkPixbuf doesn't get anything useful put into it when the GdkWindow isn't visible.
binaryDigit
02-26-2004, 09:51 PM
is there any reason you're saving a screenshot as opposed to just saving the data that the graph is showing?
i.e. save the data points of the graph to a text file rather than saving a picture of the graph.
you could then read that text file later and graph that information when you need to.
i don't know if that helps you any. there's probably a reason you're doing it the way you are....
bwkaz
02-26-2004, 10:44 PM
There is -- the Windows version of this program saves it as a .bmp, and the users expect an image rather than a bunch of data points (and yeah, I know, that's not a great reason...). ;)
The author of that version is using one of Borland's graphing widgets for Windows, and I think it natively supports writing to an image file (though I haven't looked at his code in a very long time).
I am saving the data in another file, also. But that data gets reset just after this screenshot gets saved -- it's only in existence for 250 generations.
Actually, I should probably explain what this program is. It monitors an installation of the Distributed Folding client. DF breaks its processing up into sets, and then into generations. It creates 100 protein structures per generation, and there are 250 generations per set. A set takes about a day to finish, depending on your hardware and the protein that it's crunching on.
Now, the purpose of the text file is to save the status of the client so that if my program is exited and then restarted later, it can pick up the previously-collected data (the two things that it collects are the time that each generation takes to finish, and the structure in each generation that has the lowest energy -- energy is loosely correlated with deviation from the true protein structure's layout, so the lower the energy, the "better" the structure).
The graphs should get saved (and the data points will be cleared) at the end of each set, so the user has a record of what happened if they're leaving that computer unattended for a while with just dfGUI (my program) running. If I were to just save the data points, my program won't have anywhere to put them when the user wants to look at them (the GtkNotebook that it uses to break things up is getting crowded already). I could make another program, I suppose... hmm.
Anyway, in short, it's just what people expect. I could change it if I had to, I guess.
GaryJones32
02-29-2004, 07:45 PM
yae i see what you are saying
hmmmmm
can't see any way to get the point data into say an XPM or something
and since the window manager is doing the expose event (focus or not focus)
the only thing seems left to do is a new popup window with the graph --
take a picture of it -- send it away.....
talk about unexpected behaviour from a user standpoint.....
perhaps a breif explanation like from twighlight zone
i am about to take over the display of you workstation for a minute
please sit on your hands untill i am done
bwkaz
02-29-2004, 08:12 PM
Hmm, now there's an idea. I was considering doing a gtk_window_present() on my main window, but then the problem would be getting my window back where it started when I was done. Popping up a new window would make it so that I could just destroy it when I'm done, and have that be that.
Of course it's not the greatest thing from a user's perspective, but it'll only be up for a few tenths of a second (just long enough for it to get painted and then for me to get at the pixels, then it'll disappear), hopefully. I still don't think it's ideal, but it might be the best thing I can do.
Thanks for all the help, everybody! And of course, if anybody else has any other ideas, I'd sure like to hear them too. :)
justlinux.com
Copyright Internet.com Inc. All Rights Reserved.