Re: Muffling widget repaints

2004-08-21 Thread Stephen Bach
BTW, I'm writing towards GTK+ 2.4.

On Sat, Aug 21, 2004 at 02:16:52PM -0400, Stephen Bach wrote:
> Hello,
> 
> I have a container which periodically loses some of its widgets and gains
> others, sometimes on the order of hundreds.  The changeover happens all at
> once (i.e. there's a big loop which does all the adding and destroying), but
> it's still pretty ugly and slow because sometimes many repaints are done.  I
> only care about the final repaint.
> 
> Is there some way that I can prevent the intervening repaints from happening?
> I've tested hiding and reshowing the container, and it is indeed much faster,
> but of course I don't want the user to see the container disappear.  Ideally
> I'd have the "before" painting sit until the widget switch-over is done, and
> then display the "after" painting.
> 
> I was hoping gdk_window_freeze_updates() and gdk_window_thaw_updates() would
> help, but they don't seem to do anything.  As a test I even tried freezing
> the root gdk window right before calling gtk_main() (and after showing its
> widget), but the program proceeded normally.  Maybe I'm not understanding
> what these functions are for.
> 
> Any insight would be very welcome.
> 
> Thanks
> 
> ___
> gtk-list mailing list
> [EMAIL PROTECTED]
> http://mail.gnome.org/mailman/listinfo/gtk-list
> 
> 
___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list


Re: Muffling widget repaints

2004-08-21 Thread Paul Davis
>I have a container which periodically loses some of its widgets and gains
>others, sometimes on the order of hundreds.  The changeover happens all at
>once (i.e. there's a big loop which does all the adding and destroying), but
>it's still pretty ugly and slow because sometimes many repaints are done.  I
>only care about the final repaint.

by "repaint" do you mean an "expose" signal? you should only be
drawing within an expose handler (there is one exception: drawing into
an off-screen drawable, typically a pixmap). drawing at any other time
is just not the correct model.

--p

___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list


Re: Muffling widget repaints

2004-08-21 Thread Stephen Bach
When I say "repaint" I just mean that the there is a visible change in the
widget.  I guess I'm not using the word in its conventional GTK sense.

FWIW, I did connect to the expose signal of the container and found that it's
only called once, after the widget switchover is finished.  Which I guess is
ideal.  But the container still appears to be being updated ("repainted" in
my incorrect terminology) many times during the switchover.  For example, I
can sometimes see the the container's children repositioning themselves.

On Sat, Aug 21, 2004 at 02:22:56PM -0400, Paul Davis wrote:
> >I have a container which periodically loses some of its widgets and gains
> >others, sometimes on the order of hundreds.  The changeover happens all at
> >once (i.e. there's a big loop which does all the adding and destroying), but
> >it's still pretty ugly and slow because sometimes many repaints are done.  I
> >only care about the final repaint.
> 
> by "repaint" do you mean an "expose" signal? you should only be
> drawing within an expose handler (there is one exception: drawing into
> an off-screen drawable, typically a pixmap). drawing at any other time
> is just not the correct model.
> 
> --p
> 
> 
___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list


Re: Muffling widget repaints

2004-08-24 Thread Stephen Bach
I've come up with an acceptable solution to my problem, which I'll post here
for posterity.  First my observations:

- The expose signal for the container was emitted only once, and after all the
  widgets had been added/removed.  This is good and means GTK is being smart,
  and that gdk_window_freeze_updates() wouldn't help me.

- If I left the container showing, a changeover involving 2000 widgets took
  about 30 seconds, with X cpu usage hovering at about 85% and the program's
  cpu usage at about 15% (i.e. all of it).  During the switchover, I could
  see widgets in the container shifting periodically, but the container never
  fully redrew itself during the switchover (and expose-event was not
  emitted).

- If I hid the container immediately before the changeover and showed it
  directly afterwards, the changeover took only about 3 seconds, and X cpu
  usage only seemed to reach about 40% and the program's about the same.

Eventually I found that most of the processing was because of (or related to)
size negotiations.  The container received size-request and size-allocate
signals for each widget added/removed.  Since only the final
size-request/size-allocate pair was relevant, I took out the
gtk_widget_queue_resize() calls from the pack and remove functions of the
container.

This worked great for the removal, but for the packing I'd still get the size
negotiation thrashing as soon as I gtk_widget_show'd the new children
(whether I did so before adding them or after they were all added).  So I
connected to the size-request signal of the container and added a condition
to prevent signal propagation if it was during a switchover.

This works okay -- it takes about 8 seconds for a changeover.  Certainly
there's a more complete solution, and hopefully something a little more
elegant (insight welcome), but it'll do for now.

___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list


Re: Muffling widget repaints

2004-08-24 Thread Todd Fisher
Hi,
This sounds like a very similar problem I'm having.  I'm curious if you 
have some test case code that you could
post?

thanks,
Todd
Stephen Bach wrote:
I've come up with an acceptable solution to my problem, which I'll post here
for posterity.  First my observations:
- The expose signal for the container was emitted only once, and after all the
 widgets had been added/removed.  This is good and means GTK is being smart,
 and that gdk_window_freeze_updates() wouldn't help me.
- If I left the container showing, a changeover involving 2000 widgets took
 about 30 seconds, with X cpu usage hovering at about 85% and the program's
 cpu usage at about 15% (i.e. all of it).  During the switchover, I could
 see widgets in the container shifting periodically, but the container never
 fully redrew itself during the switchover (and expose-event was not
 emitted).
- If I hid the container immediately before the changeover and showed it
 directly afterwards, the changeover took only about 3 seconds, and X cpu
 usage only seemed to reach about 40% and the program's about the same.
Eventually I found that most of the processing was because of (or related to)
size negotiations.  The container received size-request and size-allocate
signals for each widget added/removed.  Since only the final
size-request/size-allocate pair was relevant, I took out the
gtk_widget_queue_resize() calls from the pack and remove functions of the
container.
This worked great for the removal, but for the packing I'd still get the size
negotiation thrashing as soon as I gtk_widget_show'd the new children
(whether I did so before adding them or after they were all added).  So I
connected to the size-request signal of the container and added a condition
to prevent signal propagation if it was during a switchover.
This works okay -- it takes about 8 seconds for a changeover.  Certainly
there's a more complete solution, and hopefully something a little more
elegant (insight welcome), but it'll do for now.
___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list
 


___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list


Re: Muffling widget repaints

2004-08-24 Thread Stephen Bach
Hi Todd,

> This sounds like a very similar problem I'm having.  I'm curious if you 
> have some test case code that you could
> post?

My testing was all done within the context of my program, but I can try.  The
containers in question are WrapBox, which I've based on the GtkWrapBox class
from Gimp 2.0, and its subclass FileBox.

Here's most of the packing function, with the relevant changes commented.
Both this and the removal function are called with do_resize == FALSE during
the changeover.

void wrap_box_pack_pos(WrapBox* wbox, GtkWidget* child, guint pos,
   gboolean do_resize) {  /* This variable added. */
WrapBoxChild* child_info;

g_return_if_fail(IS_WRAP_BOX (wbox));
g_return_if_fail(GTK_IS_WIDGET (child));
g_return_if_fail(child->parent == NULL);

child_info = g_new(WrapBoxChild, 1);
child_info->widget = child;

/* snipping out irrelevant child insertion code */

gtk_widget_set_parent(child, GTK_WIDGET(wbox));

if (GTK_WIDGET_REALIZED(wbox))
gtk_widget_realize(child);

if (GTK_WIDGET_VISIBLE(wbox) && GTK_WIDGET_VISIBLE(child)) {
if (GTK_WIDGET_MAPPED(wbox))
gtk_widget_map(child);

if (do_resize)   /* This conditional added. */
gtk_widget_queue_resize (child);
}
}


And the removal function with a similar change:

void wrap_box_remove(GtkContainer* container, GtkWidget* widget,
  gboolean do_resize) {  /* This variable added. */
WrapBox* wbox = WRAP_BOX(container);
WrapBoxChild *child, *last = NULL;

child = wbox->children;
while (child) {
if (child->widget == widget) {
gboolean was_visible;

was_visible = GTK_WIDGET_VISIBLE(widget);
gtk_widget_unparent(widget);

if (last)
last->next = child->next;
else
wbox->children = child->next;
g_free(child);
wbox->n_children--;

if (was_visible && do_resize)  /* && do_resize added here */
gtk_widget_queue_resize(GTK_WIDGET (container));

break;
}

last = child;
child = last->next;
}
}


In the initialization of the subclass object:

static void file_box_init(FileBox *fbox) {
GTK_WIDGET_SET_FLAGS (fbox, GTK_NO_WINDOW);

fbox->optimal_width = 0;
fbox->show_hidden_files = FALSE;
fbox->n_files = 0;
fbox->file_max = 32767;
fbox->file_display_limit = DEFAULT_FILE_DISPLAY_LIMIT;
fbox->fi_slist = NULL;

/* This class variable and the next line added. */
fbox->eat_size_requests = FALSE;
g_signal_connect(fbox, "size-request",
 G_CALLBACK(size_request_kludge), NULL);
}

And the callback function:

static gboolean size_request_kludge(GtkWidget* widget,
GtkRequisition* requisition, gpointer data) {
FileBox* fbox = FILE_BOX(widget);
return fbox->eat_size_requests;
}


Then before entering the add/remove loop, this function is called with FALSE,
and then with TRUE afterward:

static void file_box_allow_size_requests(FileBox* fbox, gboolean allow) {

if (fbox->eat_size_requests != allow)
return;

if (allow) {
fbox->eat_size_requests = FALSE;
gtk_widget_queue_resize(GTK_WIDGET(fbox));
/* ^^^ This is the final size request, and the only one
   to go through. */
}
else
fbox->eat_size_requests = TRUE;
}


Hopefully that's clear and of some use.

___
gtk-list mailing list
[EMAIL PROTECTED]
http://mail.gnome.org/mailman/listinfo/gtk-list