diff options
author | Vito Caputo <vcaputo@gnugeneration.com> | 2016-09-08 20:09:18 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@gnugeneration.com> | 2016-09-09 14:17:08 -0700 |
commit | 1ad1805654961482811f63f355f1aa57cf326863 (patch) | |
tree | fcbe43ad303429e32cb64f44cac1d1a14b159f25 /src | |
parent | 7a5e600e8f67f6fa170d3bd27de7e28150c2dca5 (diff) |
overlay: move heirarchy row drawing to function
Diffstat (limited to 'src')
-rw-r--r-- | src/overlay.c | 279 |
1 files changed, 148 insertions, 131 deletions
diff --git a/src/overlay.c b/src/overlay.c index d53a864..25d6edf 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -261,6 +261,148 @@ static void draw_bars(vwm_t *vwm, vwm_xwindow_t *xwin, int row, double a_fractio 1, b_height); /* dst w, h */ } + +/* draws proc in a row of the process heirarchy */ +static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc, int depth, int row) +{ + vmon_proc_stat_t *proc_stat = proc->stores[VMON_STORE_PROC_STAT]; + vmon_proc_t *child; + char str[256]; + int str_len, str_width; + XTextItem items[1024]; /* XXX TODO: dynamically allocate this and just keep it at the high water mark.. create a struct to encapsulate this, nr_items, and alloc_items... */ + int nr_items; + +/* process heirarchy text and accompanying per-process details like wchan/pid/state... */ + /* this stuff can be skipped when monitors aren't visible */ + /* TODO: make the columns interactively configurable @ runtime */ + if (!proc->is_new) { + /* XXX for now always clear the row, this should be capable of being optimized in the future (if the datums driving the text haven't changed...) */ + XRenderFillRectangle(vwm->display, PictOpSrc, xwin->overlay.text_picture, &overlay_trans_color, + 0, row * OVERLAY_ROW_HEIGHT, /* dst x, y */ + xwin->overlay.width, OVERLAY_ROW_HEIGHT); /* dst w, h */ + } + + /* put the process' wchan, state, and PID columns @ the far right */ + if (proc->is_thread || list_empty(&proc->threads)) { /* only threads or non-threaded processes include the wchan and state */ + snprintf(str, sizeof(str), " %.*s %5i %c %n", + proc_stat->wchan.len, + proc_stat->wchan.len == 1 && proc_stat->wchan.array[0] == '0' ? "-" : proc_stat->wchan.array, + proc->pid, + proc_stat->state, + &str_len); + } else { /* we're a process having threads, suppress the wchan and state, as they will be displayed for the thread of same pid */ + snprintf(str, sizeof(str), " %5i %n", proc->pid, &str_len); + } + str_width = XTextWidth(overlay_font, str, str_len); + + /* the process' comm label indented according to depth, followed with their respective argv's */ + argv2xtext(proc, items, &nr_items); + XDrawText(vwm->display, xwin->overlay.text_pixmap, text_gc, + depth * (OVERLAY_ROW_HEIGHT / 2), (row + 1) * OVERLAY_ROW_HEIGHT - 3, /* dst x, y */ + items, nr_items); + + /* ensure the area for the rest of the stuff is cleared, we don't put much text into thread rows so skip it for those. */ + if (!proc->is_thread) { + XRenderFillRectangle(vwm->display, PictOpSrc, xwin->overlay.text_picture, &overlay_trans_color, + xwin->attrs.width - str_width, row * OVERLAY_ROW_HEIGHT, /* dst x,y */ + xwin->overlay.width - (xwin->attrs.width - str_width), OVERLAY_ROW_HEIGHT); /* dst w,h */ + } + + XDrawString(vwm->display, xwin->overlay.text_pixmap, text_gc, + xwin->attrs.width - str_width, (row + 1) * OVERLAY_ROW_HEIGHT - 3, /* dst x, y */ + str, str_len); + + /* only if this process isn't the root process @ the window shall we consider all relational drawing conditions */ + if (proc != xwin->monitor) { + vmon_proc_t *ancestor, *sibling, *last_sibling = NULL; + struct list_head *rem; + int needs_tee = 0; + int bar_x = 0, bar_y = 0; + int sub; + + /* XXX: everything done in this code block only dirties _this_ process' row in the rendered overlay output */ + + /* walk up the ancestors until reaching xwin->monitor, any ancestors we encounter which have more siblings we draw a vertical bar for */ + /* this draws the |'s in something like: | | | | comm */ + for (sub = 1, ancestor = proc->parent; ancestor && ancestor != xwin->monitor; ancestor = ancestor->parent) { + sub++; + bar_x = (depth - sub) * (OVERLAY_ROW_HEIGHT / 2) + 4; + bar_y = (row + 1) * OVERLAY_ROW_HEIGHT; + + /* determine if the ancestor has remaining siblings which are not stale, if so, draw a connecting bar at its depth */ + for (rem = ancestor->siblings.next; rem != &ancestor->parent->children; rem = rem->next) { + if (!(list_entry(rem, vmon_proc_t, siblings)->is_stale)) { + XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, + bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */ + bar_x, bar_y); /* dst x2, y2 (vertical line) */ + break; /* stop looking for more siblings at this ancestor when we find one that isn't stale */ + } + } + } + + /* determine if _any_ of our siblings have children requiring us to draw a tee immediately before our comm string. + * The only sibling which doesn't cause this to happen is the last one in the children list, if it has children it has no impact on its remaining + * siblings, as there are none. + * + * This draws the + in something like: | | | | +comm + */ + + /* find the last sibling (this has to be done due to the potential for stale siblings at the tail, and we'd rather not repeatedly check for it) */ + list_for_each_entry(sibling, &proc->parent->children, siblings) { + if (!sibling->is_stale) last_sibling = sibling; + } + + /* now look for siblings with non-stale children to determine if a tee is needed, ignoring the last sibling */ + list_for_each_entry(sibling, &proc->parent->children, siblings) { + /* skip stale siblings, they aren't interesting as they're invisible, and the last sibling has no bearing on wether we tee or not. */ + if (sibling->is_stale || sibling == last_sibling) continue; + + /* if any of the other siblings have children which are not stale, put a tee in front of our name, but ignore stale children */ + list_for_each_entry(child, &sibling->children, siblings) { + if (!child->is_stale) { + needs_tee = 1; + break; + } + } + + /* if we still don't think we need a tee, check if there are threads */ + if (!needs_tee) { + list_for_each_entry(child, &sibling->threads, threads) { + if (!child->is_stale) { + needs_tee = 1; + break; + } + } + } + + /* found a tee is necessary, all that's left is to determine if the tee is a corner and draw it accordingly, stopping the search. */ + if (needs_tee) { + bar_x = (depth - 1) * (OVERLAY_ROW_HEIGHT / 2) + 4; + + /* if we're the last sibling, corner the tee by shortening the vbar */ + if (proc == last_sibling) { + XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, + bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */ + bar_x, bar_y - 4); /* dst x2, y2 (vertical bar) */ + } else { + XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, + bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */ + bar_x, bar_y); /* dst x2, y2 (vertical bar) */ + } + + XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, + bar_x, bar_y - 4, /* dst x1, y1 */ + bar_x + 2, bar_y - 4); /* dst x2, y2 (horizontal bar) */ + + /* terminate the outer sibling loop upon drawing the tee... */ + break; + } + } + } + shadow_row(vwm, xwin, row); +} + + /* recursive draw function for "rest" of overlay: the per-process rows (heirarchy, argv, state, wchan, pid...) */ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc, int *depth, int *row) { @@ -272,11 +414,14 @@ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc double utime_delta, stime_delta; /* text variables */ - char str[256]; - int str_len, str_width; XTextItem items[1024]; /* XXX TODO: dynamically allocate this and just keep it at the high water mark.. create a struct to encapsulate this, nr_items, and alloc_items... */ int nr_items; + /* Some parts of this we must do on every sample to maintain coherence in the graphs, since they're incrementally kept + * in sync with the process heirarchy, allocating and shifting the rows as processes are created and destroyed. Everything + * else we should be able to skip doing unless overlay.redraw_needed or their contents changed. + */ + if (proc->is_stale) { /* what to do when a process (subtree) has gone away */ static int in_stale = 0; @@ -379,135 +524,7 @@ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc draw_bars(vwm, xwin, *row, stime_delta, total_delta, utime_delta, total_delta); -/* process heirarchy text and accompanying per-process details like wchan/pid/state... */ - if (1 /* FIXME TODO compositing_mode */) { /* this stuff can be skipped when monitors aren't visible */ - /* TODO: make the columns interactively configurable @ runtime */ - if (!proc->is_new) { - /* XXX for now always clear the row, this should be capable of being optimized in the future (if the datums driving the text haven't changed...) */ - XRenderFillRectangle(vwm->display, PictOpSrc, xwin->overlay.text_picture, &overlay_trans_color, - 0, (*row) * OVERLAY_ROW_HEIGHT, /* dst x, y */ - xwin->overlay.width, OVERLAY_ROW_HEIGHT); /* dst w, h */ - } - - /* put the process' wchan, state, and PID columns @ the far right */ - if (proc->is_thread || list_empty(&proc->threads)) { /* only threads or non-threaded processes include the wchan and state */ - snprintf(str, sizeof(str), " %.*s %5i %c %n", - proc_stat->wchan.len, - proc_stat->wchan.len == 1 && proc_stat->wchan.array[0] == '0' ? "-" : proc_stat->wchan.array, - proc->pid, - proc_stat->state, - &str_len); - } else { /* we're a process having threads, suppress the wchan and state, as they will be displayed for the thread of same pid */ - snprintf(str, sizeof(str), " %5i %n", proc->pid, &str_len); - } - str_width = XTextWidth(overlay_font, str, str_len); - - /* the process' comm label indented according to depth, followed with their respective argv's */ - argv2xtext(proc, items, &nr_items); - XDrawText(vwm->display, xwin->overlay.text_pixmap, text_gc, - (*depth) * (OVERLAY_ROW_HEIGHT / 2), ((*row) + 1) * OVERLAY_ROW_HEIGHT - 3, /* dst x, y */ - items, nr_items); - - /* ensure the area for the rest of the stuff is cleared, we don't put much text into thread rows so skip it for those. */ - if (!proc->is_thread) { - XRenderFillRectangle(vwm->display, PictOpSrc, xwin->overlay.text_picture, &overlay_trans_color, - xwin->attrs.width - str_width, (*row) * OVERLAY_ROW_HEIGHT, /* dst x,y */ - xwin->overlay.width - (xwin->attrs.width - str_width), OVERLAY_ROW_HEIGHT); /* dst w,h */ - } - - XDrawString(vwm->display, xwin->overlay.text_pixmap, text_gc, - xwin->attrs.width - str_width, ((*row) + 1) * OVERLAY_ROW_HEIGHT - 3, /* dst x, y */ - str, str_len); - - /* only if this process isn't the root process @ the window shall we consider all relational drawing conditions */ - if (proc != xwin->monitor) { - vmon_proc_t *ancestor, *sibling, *last_sibling = NULL; - struct list_head *rem; - int needs_tee = 0; - int bar_x = 0, bar_y = 0; - int sub; - - /* XXX: everything done in this code block only dirties _this_ process' row in the rendered overlay output */ - - /* walk up the ancestors until reaching xwin->monitor, any ancestors we encounter which have more siblings we draw a vertical bar for */ - /* this draws the |'s in something like: | | | | comm */ - for (sub = 1, ancestor = proc->parent; ancestor && ancestor != xwin->monitor; ancestor = ancestor->parent) { - sub++; - bar_x = ((*depth) - sub) * (OVERLAY_ROW_HEIGHT / 2) + 4; - bar_y = ((*row) + 1) * OVERLAY_ROW_HEIGHT; - - /* determine if the ancestor has remaining siblings which are not stale, if so, draw a connecting bar at its depth */ - for (rem = ancestor->siblings.next; rem != &ancestor->parent->children; rem = rem->next) { - if (!(list_entry(rem, vmon_proc_t, siblings)->is_stale)) { - XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, - bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */ - bar_x, bar_y); /* dst x2, y2 (vertical line) */ - break; /* stop looking for more siblings at this ancestor when we find one that isn't stale */ - } - } - } - - /* determine if _any_ of our siblings have children requiring us to draw a tee immediately before our comm string. - * The only sibling which doesn't cause this to happen is the last one in the children list, if it has children it has no impact on its remaining - * siblings, as there are none. - * - * This draws the + in something like: | | | | +comm - */ - - /* find the last sibling (this has to be done due to the potential for stale siblings at the tail, and we'd rather not repeatedly check for it) */ - list_for_each_entry(sibling, &proc->parent->children, siblings) { - if (!sibling->is_stale) last_sibling = sibling; - } - - /* now look for siblings with non-stale children to determine if a tee is needed, ignoring the last sibling */ - list_for_each_entry(sibling, &proc->parent->children, siblings) { - /* skip stale siblings, they aren't interesting as they're invisible, and the last sibling has no bearing on wether we tee or not. */ - if (sibling->is_stale || sibling == last_sibling) continue; - - /* if any of the other siblings have children which are not stale, put a tee in front of our name, but ignore stale children */ - list_for_each_entry(child, &sibling->children, siblings) { - if (!child->is_stale) { - needs_tee = 1; - break; - } - } - - /* if we still don't think we need a tee, check if there are threads */ - if (!needs_tee) { - list_for_each_entry(child, &sibling->threads, threads) { - if (!child->is_stale) { - needs_tee = 1; - break; - } - } - } - - /* found a tee is necessary, all that's left is to determine if the tee is a corner and draw it accordingly, stopping the search. */ - if (needs_tee) { - bar_x = ((*depth) - 1) * (OVERLAY_ROW_HEIGHT / 2) + 4; - - /* if we're the last sibling, corner the tee by shortening the vbar */ - if (proc == last_sibling) { - XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, - bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */ - bar_x, bar_y - 4); /* dst x2, y2 (vertical bar) */ - } else { - XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, - bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */ - bar_x, bar_y); /* dst x2, y2 (vertical bar) */ - } - - XDrawLine(vwm->display, xwin->overlay.text_pixmap, text_gc, - bar_x, bar_y - 4, /* dst x1, y1 */ - bar_x + 2, bar_y - 4); /* dst x2, y2 (horizontal bar) */ - - /* terminate the outer sibling loop upon drawing the tee... */ - break; - } - } - } - shadow_row(vwm, xwin, (*row)); - } + draw_heirarchy_row(vwm, xwin, proc, *depth, *row); (*row)++; |