X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/73dd383f66833613f7e1e27175987758b0328b3c..81cd18944f4b070511dd041902dc2c723a2669c4:/disobedience/choose.c diff --git a/disobedience/choose.c b/disobedience/choose.c index dc86412..b740008 100644 --- a/disobedience/choose.c +++ b/disobedience/choose.c @@ -26,9 +26,72 @@ */ #include "disobedience.h" +#include "timeval.h" /* Choose track ------------------------------------------------------------ */ +#if TDEBUG +/* Timing */ +static struct { + struct timeval total; + struct timeval gtkbits; + struct timeval menuupdate; + struct timeval new_widgets; + struct timeval undisplay; + struct timeval colors; + struct timeval markers; + struct timeval location; + struct timeval selection; +} times; + +#define BEGIN(WHAT) do { \ + struct timeval started##WHAT, finished##WHAT; \ + xgettimeofday(&started##WHAT, 0) + +#define END(WHAT) \ + xgettimeofday(&finished##WHAT, 0); \ + times.WHAT = tvadd(times.WHAT, tvsub(finished##WHAT, started##WHAT)); \ +} while(0) + +#define INIT() memset(×, 0, sizeof times) + +#define REPORT() do { \ + fprintf(stderr, "total=%g\n" \ + "gtkbits=%g\n" \ + "menuupdate=%g\n" \ + "new_widgets=%g\n" \ + "undisplay=%g\n" \ + "colors=%g\n" \ + "markers=%g\n" \ + "location=%g\n" \ + "selection=%g\n" \ + "accumulation=%g\n" \ + "\n", \ + tvdouble(times.total), \ + tvdouble(times.gtkbits), \ + tvdouble(times.menuupdate), \ + tvdouble(times.new_widgets), \ + tvdouble(times.undisplay), \ + tvdouble(times.colors), \ + tvdouble(times.markers), \ + tvdouble(times.location), \ + tvdouble(times.selection), \ + (tvdouble(times.gtkbits) \ + + tvdouble(times.menuupdate) \ + + tvdouble(times.new_widgets) \ + + tvdouble(times.undisplay) \ + + tvdouble(times.colors) \ + + tvdouble(times.markers) \ + + tvdouble(times.location) \ + + tvdouble(times.selection))); \ +} while(0) +#else +#define BEGIN(WHAT) do { +#define END(WHAT) } while(0) +#define INIT() ((void)0) +#define REPORT() ((void)0) +#endif + WT(label); WT(event_box); WT(menu); @@ -381,6 +444,8 @@ static void got_files(void *v, int nvec, char **vec) { * done */ if(!(cn->flags & CN_GETTING_ANY)) filled(cn); + if(!gets_in_flight) + redisplay_tree("got_files"); } /** @brief Called with an alias resolved filename */ @@ -398,7 +463,7 @@ static void got_resolved_file(void *v, const char *track) { /* Only bother updating when we've got the lot */ if(--cn->pending == 0) { cn->flags &= ~CN_RESOLVING_FILES; - updated_node(cn, 1, "got_resolved_file"); + updated_node(cn, gets_in_flight == 0, "got_resolved_file"); if(!(cn->flags & CN_GETTING_ANY)) filled(cn); } @@ -424,7 +489,7 @@ static void got_dirs(void *v, int nvec, char **vec) { trackname_transform("dir", vec[n], "display"), trackname_transform("dir", vec[n], "sort"), CN_EXPANDABLE, fill_directory_node); - updated_node(cn, 1, "got_dirs"); + updated_node(cn, gets_in_flight == 0, "got_dirs"); cn->flags &= ~CN_GETTING_DIRS; if(!(cn->flags & CN_GETTING_ANY)) filled(cn); @@ -784,6 +849,12 @@ static void redisplay_tree(const char *why) { /*fprintf(stderr, "redisplay_tree %s suppressed\n", why);*/ return; } + if(gets_in_flight) { + /*fprintf(stderr, "redisplay_tree %s suppressed (gets_in_flight)\n", why);*/ + return; + } + INIT(); + BEGIN(total); /*fprintf(stderr, "redisplay_tree %s *** NOT SUPPRESSED ***\n", why);*/ /* We'll count these up empirically each time */ files_selected = 0; @@ -794,6 +865,8 @@ static void redisplay_tree(const char *why) { sizeof (struct choosenode *)) : 0; d = display_tree(root, 0, 0); MTAG_POP(); + + BEGIN(gtkbits); /* We must set the total size or scrolling will not work (it wouldn't be hard * for GtkLayout to figure it out for itself but presumably you're supposed * to be able to have widgets off the edge of the layuot.) @@ -807,8 +880,13 @@ static void redisplay_tree(const char *why) { if(oldwidth > d.width || oldheight > d.height) gtk_widget_queue_draw(chooselayout); gtk_layout_set_size(GTK_LAYOUT(chooselayout), d.width, d.height); + END(gtkbits); /* Notify the main menu of any recent changes */ + BEGIN(menuupdate); menu_update(-1); + END(menuupdate); + END(total); + REPORT(); } /** @brief Recursive step for redisplay_tree() @@ -834,6 +912,7 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) { * A non-expandable item has just a text label and no arrow. */ if(!cn->container) { + BEGIN(new_widgets); MTAG_PUSH("make_widgets_1"); /* Widgets need to be created */ NW(hbox); @@ -873,9 +952,14 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) { /* Show everything by default */ gtk_widget_show_all(cn->container); MTAG_POP(); + END(new_widgets); } assert(cn->container); /* Set colors */ + BEGIN(colors); + /* This section turns out to reliably take >50% of the elapsed time when + * displaying the tree, both when it's largely unexpanded and when it's + * heavily expanded. */ if(search_result) gtk_widget_modify_bg(cn->container, GTK_STATE_NORMAL, &search_bg); else @@ -885,7 +969,9 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) { gtk_widget_modify_fg(cn->label, GTK_STATE_NORMAL, &item_fg); gtk_widget_modify_fg(cn->label, GTK_STATE_SELECTED, &selected_fg); gtk_widget_modify_fg(cn->label, GTK_STATE_PRELIGHT, &selected_fg); + END(colors); /* Make sure the icon is right */ + BEGIN(markers); if(cn->flags & CN_EXPANDABLE) gtk_arrow_set(GTK_ARROW(cn->arrow), cn->flags & CN_EXPANDED ? GTK_ARROW_DOWN : GTK_ARROW_RIGHT, @@ -894,7 +980,9 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) { /* Make sure the queued marker is right */ /* TODO: doesn't always work */ (queued(cn->path) ? gtk_widget_show : gtk_widget_hide)(cn->marker); + END(markers); /* Put the widget in the right place */ + BEGIN(location); if(cn->flags & CN_DISPLAYED) gtk_layout_move(GTK_LAYOUT(chooselayout), cn->container, x, y); else { @@ -903,9 +991,12 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) { /* Now chooselayout has a ref to the container */ g_object_unref(cn->container); } + END(location); /* Set the widget's selection status */ + BEGIN(selection); if(!(cn->flags & CN_EXPANDABLE)) display_selection(cn); + END(selection); /* Find the size used so we can get vertical positioning right. */ gtk_widget_size_request(cn->container, &req); d.width = x + req.width; @@ -924,8 +1015,10 @@ static struct displaydata display_tree(struct choosenode *cn, int x, int y) { d.height = cd.height; } } else { + BEGIN(undisplay); for(n = 0; n < cn->children.nvec; ++n) undisplay_tree(cn->children.vec[n]); + END(undisplay); } if(!(cn->flags & CN_EXPANDABLE)) { ++files_visible;