summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@gnugeneration.com>2017-03-11 02:29:37 -0800
committerVito Caputo <vcaputo@gnugeneration.com>2017-03-14 19:41:48 -0700
commit2373a54d2d52961a841dace71b505d2c20f5c040 (patch)
treede534cf0e4f7f1e917faf2b8fc07eb80a1749f96 /src
parentb99f0728ec7229423cfc65d25711208f6cac1c0e (diff)
overlays: extricate overlays from vwm internals
- Move vmon_proc_t under vwm_overlay_t. - Privatize vwm_overlay_t. - Update xwindow.c to dynamically create and destroy overlays. - Cease supplying vwm_t to vwm_overlays_create(), now just pass in the bare vwm_xserver_t. - Update all vwm_overlay_* functions to operate on vwm_overlays_t and vwm_overlay_t. Only vwm_overlays_create() receives the xserver, which it then embeds within the returned vwm_overlay_t. - Eliminate _xwin_ flavors of overlay functions, largely mechanical rename eliminating the _xwin_ from the names during the previous pass of switching from vwm_t & vwm_xwindow_t to vwm_overlays_t & vwm_overlay_t parameters. - Change vwm_overlay_compose() to store damage in supplied pointer, the caller is expected to make use of the damage information now because the overlay code doesn't know about the window its coordinate space.
Diffstat (limited to 'src')
-rw-r--r--src/composite.c26
-rw-r--r--src/key.c7
-rw-r--r--src/overlays.c614
-rw-r--r--src/overlays.h37
-rw-r--r--src/vwm.c4
-rw-r--r--src/xevent.c4
-rw-r--r--src/xwindow.c21
-rw-r--r--src/xwindow.h5
8 files changed, 413 insertions, 305 deletions
diff --git a/src/composite.c b/src/composite.c
index bdb2b64..3f55863 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -79,6 +79,7 @@ void vwm_composite_damage_add(vwm_t *vwm, XserverRegion damage)
{
if (combined_damage != None) {
XFixesUnionRegion(VWM_XDISPLAY(vwm), combined_damage, combined_damage, damage);
+ /* TODO FIXME: make destroy optional, change callers to reuse a persistent region where practical */
XFixesDestroyRegion(VWM_XDISPLAY(vwm), damage);
} else {
combined_damage = damage;
@@ -224,7 +225,18 @@ void vwm_composite_paint_all(vwm_t *vwm)
r.height = xwin->attrs.height + xwin->attrs.border_width * 2;
if (XRectInRegion(occluded, r.x, r.y, r.width, r.height) != RectangleIn) {
/* the window isn't fully occluded, compose it and add it to occluded */
- if (xwin->monitor && !xwin->attrs.override_redirect) vwm_overlay_xwin_compose(vwm, xwin);
+ if (xwin->overlay) {
+ XserverRegion overlay_damage = None;
+
+ vwm_overlay_compose(vwm->overlays, xwin->overlay, &overlay_damage);
+ if (overlay_damage != None) {
+ /* the damage region is in overlay coordinate space, translation necessary. */
+ XFixesTranslateRegion(VWM_XDISPLAY(vwm), overlay_damage,
+ xwin->attrs.x + xwin->attrs.border_width,
+ xwin->attrs.y + xwin->attrs.border_width);
+ vwm_composite_damage_add(vwm, overlay_damage);
+ }
+ }
XUnionRectWithRegion(&r, occluded, occluded);
xwin->occluded = 0;
} else {
@@ -256,13 +268,13 @@ void vwm_composite_paint_all(vwm_t *vwm)
r.x, r.y, /* dst x, y */
r.width, r.height);
- if (xwin->monitor && !xwin->attrs.override_redirect && xwin->overlay.width) {
+ if (xwin->overlay) {
/* draw the monitoring overlay atop the window, note we stay within the window borders here. */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, xwin->overlay.picture, None, root_buffer,
- 0, 0, 0, 0, /* src x,y, maxk x, y */
- xwin->attrs.x + xwin->attrs.border_width, /* dst x */
- xwin->attrs.y + xwin->attrs.border_width, /* dst y */
- xwin->attrs.width, vwm_overlay_xwin_composed_height(vwm, xwin)); /* w, h */
+ vwm_overlay_render(vwm->overlays, xwin->overlay, root_buffer,
+ xwin->attrs.x + xwin->attrs.border_width,
+ xwin->attrs.y + xwin->attrs.border_width,
+ xwin->attrs.width,
+ xwin->attrs.height);
}
/* subtract the region of the window from the combined damage and update the root_buffer clip region to reflect the remaining damage */
diff --git a/src/key.c b/src/key.c
index a67596e..1b3000e 100644
--- a/src/key.c
+++ b/src/key.c
@@ -338,9 +338,10 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress)
vwm_composite_toggle(vwm);
break;
- case XK_apostrophe: /* reset snowflakes of the focused window, suppressed when not compositing */
- if (vwin) {
- vwm_overlay_xwin_reset_snowflakes(vwm, vwin->xwindow);
+ case XK_apostrophe: /* reset snowflakes of the focused window */
+ if (vwin && vwin->xwindow->overlay) {
+ vwm_overlay_reset_snowflakes(vwm->overlays, vwin->xwindow->overlay);
+ vwm_composite_damage_win(vwm, vwin->xwindow);
}
break;
diff --git a/src/overlays.c b/src/overlays.c
index 19ac65f..e994dca 100644
--- a/src/overlays.c
+++ b/src/overlays.c
@@ -68,6 +68,27 @@ typedef struct _vwm_overlays_t {
overlay_finish_fill;
} vwm_overlays_t;
+/* everything needed by the per-window overlay's context */
+typedef struct _vwm_overlay_t {
+ vmon_proc_t *monitor; /* vmon process monitor handle */
+ Pixmap text_pixmap; /* pixmap for overlayed text (kept around for XDrawText usage) */
+ Picture text_picture; /* picture representation of text_pixmap */
+ Picture shadow_picture; /* text shadow layer */
+ Picture grapha_picture; /* graph A layer */
+ Picture graphb_picture; /* graph B layer */
+ Picture tmp_picture; /* 1 row worth of temporary picture space */
+ Picture picture; /* overlay picture derived from the pixmap, for render compositing */
+ int width; /* current width of the overlay */
+ int height; /* current height of the overlay */
+ int visible_width; /* currently visible width of the overlay */
+ int visible_height; /* currently visible height of the overlay */
+ int phase; /* current position within the (horizontally scrolling) graphs */
+ int heirarchy_end; /* row where the process heirarchy currently ends */
+ int snowflakes_cnt; /* count of snowflaked rows (reset to zero to truncate snowflakes display) */
+ int gen_last_composed; /* the last composed vmon generation */
+ int redraw_needed; /* if a redraw is required (like when the window is resized...) */
+} vwm_overlay_t;
+
/* space we need for every process being monitored */
typedef struct _vwm_perproc_ctxt_t {
typeof(((vmon_t *)0)->generation) generation;
@@ -100,16 +121,16 @@ static XRenderPictureAttributes pa_no_repeat = { .repeat = 0 };
/* this callback gets invoked at sample time once "per sys" */
static void sample_callback(vmon_t *vmon, void *arg)
{
- vwm_t *vwm = arg;
+ vwm_overlays_t *overlays = arg;
vmon_sys_stat_t *sys_stat = vmon->stores[VMON_STORE_SYS_STAT];
- vwm->overlays->this_total = sys_stat->user + sys_stat->nice + sys_stat->system +
+ overlays->this_total = sys_stat->user + sys_stat->nice + sys_stat->system +
sys_stat->idle + sys_stat->iowait + sys_stat->irq +
sys_stat->softirq + sys_stat->steal + sys_stat->guest;
- vwm->overlays->total_delta = vwm->overlays->this_total - vwm->overlays->last_total;
- vwm->overlays->idle_delta = sys_stat->idle - vwm->overlays->last_idle;
- vwm->overlays->iowait_delta = sys_stat->iowait - vwm->overlays->last_iowait;
+ overlays->total_delta = overlays->this_total - overlays->last_total;
+ overlays->idle_delta = sys_stat->idle - overlays->last_idle;
+ overlays->iowait_delta = sys_stat->iowait - overlays->last_iowait;
}
@@ -131,11 +152,9 @@ static void vmon_dtor_cb(vmon_t *vmon, vmon_proc_t *proc)
}
-
/* initialize overlays system */
-vwm_overlays_t * vwm_overlays_create(vwm_t *vwm)
+vwm_overlays_t * vwm_overlays_create(vwm_xserver_t *xserver)
{
- vwm_xserver_t *xserver = vwm->xserver;
vwm_overlays_t *overlays;
Window bitmask;
@@ -153,7 +172,7 @@ vwm_overlays_t * vwm_overlays_create(vwm_t *vwm)
overlays->vmon.proc_ctor_cb = vmon_ctor_cb;
overlays->vmon.proc_dtor_cb = vmon_dtor_cb;
overlays->vmon.sample_cb = sample_callback;
- overlays->vmon.sample_cb_arg = vwm;
+ overlays->vmon.sample_cb_arg = overlays;
gettimeofday(&overlays->this_sample, NULL);
/* get all the text and graphics stuff setup for overlays */
@@ -209,40 +228,42 @@ void vwm_overlays_destroy(vwm_overlays_t *overlays)
/* moves what's below a given row up above it if specified, the row becoming discarded */
-static void snowflake_row(vwm_t *vwm, vwm_xwindow_t *xwin, Picture pic, int copy, int row)
+static void snowflake_row(vwm_overlays_t *overlays, vwm_overlay_t *overlay, Picture pic, int copy, int row)
{
- VWM_TRACE("pid=%i xwin=%p row=%i copy=%i heirarhcy_end=%i", xwin->monitor->pid, xwin, row, copy, xwin->overlay.heirarchy_end);
+ vwm_xserver_t *xserver = overlays->xserver;
+
+ VWM_TRACE("pid=%i overlay=%p row=%i copy=%i heirarhcy_end=%i", overlay->monitor->pid, overlay, row, copy, overlay->heirarchy_end);
if (copy) {
/* copy row to tmp */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, pic, None, xwin->overlay.tmp_picture,
- 0, row * OVERLAY_ROW_HEIGHT, /* src */
- 0, 0, /* mask */
- 0, 0, /* dest */
- xwin->overlay.width, OVERLAY_ROW_HEIGHT); /* dimensions */
+ XRenderComposite(xserver->display, PictOpSrc, pic, None, overlay->tmp_picture,
+ 0, row * OVERLAY_ROW_HEIGHT, /* src */
+ 0, 0, /* mask */
+ 0, 0, /* dest */
+ overlay->width, OVERLAY_ROW_HEIGHT); /* dimensions */
}
/* shift up */
- XRenderChangePicture(VWM_XDISPLAY(vwm), pic, CPRepeat, &pa_no_repeat);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, pic, None, pic,
- 0, (1 + row) * OVERLAY_ROW_HEIGHT, /* src */
- 0, 0, /* mask */
- 0, row * OVERLAY_ROW_HEIGHT, /* dest */
- xwin->overlay.width, (1 + xwin->overlay.heirarchy_end) * OVERLAY_ROW_HEIGHT - (1 + row) * OVERLAY_ROW_HEIGHT); /* dimensions */
- XRenderChangePicture(VWM_XDISPLAY(vwm), pic, CPRepeat, &pa_repeat);
+ XRenderChangePicture(xserver->display, pic, CPRepeat, &pa_no_repeat);
+ XRenderComposite(xserver->display, PictOpSrc, pic, None, pic,
+ 0, (1 + row) * OVERLAY_ROW_HEIGHT, /* src */
+ 0, 0, /* mask */
+ 0, row * OVERLAY_ROW_HEIGHT, /* dest */
+ overlay->width, (1 + overlay->heirarchy_end) * OVERLAY_ROW_HEIGHT - (1 + row) * OVERLAY_ROW_HEIGHT); /* dimensions */
+ XRenderChangePicture(xserver->display, pic, CPRepeat, &pa_repeat);
if (copy) {
/* copy tmp to top of snowflakes */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.tmp_picture, None, pic,
- 0, 0, /* src */
- 0, 0, /* mask */
- 0, (xwin->overlay.heirarchy_end) * OVERLAY_ROW_HEIGHT, /* dest */
- xwin->overlay.width, OVERLAY_ROW_HEIGHT); /* dimensions */
+ XRenderComposite(xserver->display, PictOpSrc, overlay->tmp_picture, None, pic,
+ 0, 0, /* src */
+ 0, 0, /* mask */
+ 0, (overlay->heirarchy_end) * OVERLAY_ROW_HEIGHT, /* dest */
+ overlay->width, OVERLAY_ROW_HEIGHT); /* dimensions */
} else {
/* clear the snowflake row */
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, pic, &overlay_trans_color,
- 0, (xwin->overlay.heirarchy_end) * OVERLAY_ROW_HEIGHT, /* dest */
- xwin->overlay.width, OVERLAY_ROW_HEIGHT); /* dimensions */
+ XRenderFillRectangle(xserver->display, PictOpSrc, pic, &overlay_trans_color,
+ 0, (overlay->heirarchy_end) * OVERLAY_ROW_HEIGHT, /* dest */
+ overlay->width, OVERLAY_ROW_HEIGHT); /* dimensions */
}
}
@@ -251,50 +272,54 @@ static void snowflake_row(vwm_t *vwm, vwm_xwindow_t *xwin, Picture pic, int copy
*/
/* shifts what's below a given row down a row, and clears the row, preparing it for populating */
-static void allocate_row(vwm_t *vwm, vwm_xwindow_t *xwin, Picture pic, int row)
+static void allocate_row(vwm_overlays_t *overlays, vwm_overlay_t *overlay, Picture pic, int row)
{
- VWM_TRACE("pid=%i xwin=%p row=%i", xwin->monitor->pid, xwin, row);
+ vwm_xserver_t *xserver = overlays->xserver;
+
+ VWM_TRACE("pid=%i overlay=%p row=%i", overlay->monitor->pid, overlay, row);
/* shift everything below the row down */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, pic, None, pic,
- 0, row * OVERLAY_ROW_HEIGHT, /* src */
- 0, 0, /* mask */
- 0, (1 + row) * OVERLAY_ROW_HEIGHT, /* dest */
- xwin->overlay.width, xwin->overlay.height - (1 + row) * OVERLAY_ROW_HEIGHT); /* dimensions */
+ XRenderComposite(xserver->display, PictOpSrc, pic, None, pic,
+ 0, row * OVERLAY_ROW_HEIGHT, /* src */
+ 0, 0, /* mask */
+ 0, (1 + row) * OVERLAY_ROW_HEIGHT, /* dest */
+ overlay->width, overlay->height - (1 + row) * OVERLAY_ROW_HEIGHT); /* dimensions */
/* fill the space created with transparent pixels */
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, pic, &overlay_trans_color,
- 0, row * OVERLAY_ROW_HEIGHT, /* dest */
- xwin->overlay.width, OVERLAY_ROW_HEIGHT); /* dimensions */
+ XRenderFillRectangle(xserver->display, PictOpSrc, pic, &overlay_trans_color,
+ 0, row * OVERLAY_ROW_HEIGHT, /* dest */
+ overlay->width, OVERLAY_ROW_HEIGHT); /* dimensions */
}
/* shadow a row from the text layer in the shadow layer */
-static void shadow_row(vwm_t *vwm, vwm_xwindow_t *xwin, int row)
+static void shadow_row(vwm_overlays_t *overlays, vwm_overlay_t *overlay, int row)
{
+ vwm_xserver_t *xserver = overlays->xserver;
+
/* the current technique for creating the shadow is to simply render the text at +1/-1 pixel offsets on both axis in translucent black */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, vwm->overlays->overlay_shadow_fill, xwin->overlay.text_picture, xwin->overlay.shadow_picture,
+ XRenderComposite(xserver->display, PictOpSrc, overlays->overlay_shadow_fill, overlay->text_picture, overlay->shadow_picture,
0, 0,
-1, row * OVERLAY_ROW_HEIGHT,
0, row * OVERLAY_ROW_HEIGHT,
- xwin->attrs.width, OVERLAY_ROW_HEIGHT);
+ overlay->visible_width, OVERLAY_ROW_HEIGHT);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_shadow_fill, xwin->overlay.text_picture, xwin->overlay.shadow_picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_shadow_fill, overlay->text_picture, overlay->shadow_picture,
0, 0,
0, -1 + row * OVERLAY_ROW_HEIGHT,
0, row * OVERLAY_ROW_HEIGHT,
- xwin->attrs.width, OVERLAY_ROW_HEIGHT);
+ overlay->visible_width, OVERLAY_ROW_HEIGHT);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_shadow_fill, xwin->overlay.text_picture, xwin->overlay.shadow_picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_shadow_fill, overlay->text_picture, overlay->shadow_picture,
0, 0,
1, row * OVERLAY_ROW_HEIGHT,
0, row * OVERLAY_ROW_HEIGHT,
- xwin->attrs.width, OVERLAY_ROW_HEIGHT);
+ overlay->visible_width, OVERLAY_ROW_HEIGHT);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_shadow_fill, xwin->overlay.text_picture, xwin->overlay.shadow_picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_shadow_fill, overlay->text_picture, overlay->shadow_picture,
0, 0,
0, 1 + row * OVERLAY_ROW_HEIGHT,
0, row * OVERLAY_ROW_HEIGHT,
- xwin->attrs.width, OVERLAY_ROW_HEIGHT);
+ overlay->visible_width, OVERLAY_ROW_HEIGHT);
}
@@ -375,9 +400,10 @@ static int proc_heirarchy_changed(vmon_proc_t *proc) {
/* helper for drawing the vertical bars in the graph layers */
-static void draw_bars(vwm_t *vwm, vwm_xwindow_t *xwin, int row, double a_fraction, double a_total, double b_fraction, double b_total)
+static void draw_bars(vwm_overlays_t *overlays, vwm_overlay_t *overlay, int row, double a_fraction, double a_total, double b_fraction, double b_total)
{
- int a_height, b_height;
+ vwm_xserver_t *xserver = overlays->xserver;
+ int a_height, b_height;
/* compute the bar heights for this sample */
a_height = (a_fraction / a_total * (double)(OVERLAY_ROW_HEIGHT - 1)); /* give up 1 pixel for the div */
@@ -389,18 +415,19 @@ static void draw_bars(vwm_t *vwm, vwm_xwindow_t *xwin, int row, double a_fractio
if (b_fraction && !b_height) b_height = 1;
/* draw the two bars for this sample at the current phase in the graphs, note the first is ceiling-based, second floor-based */
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.grapha_picture, &overlay_visible_color,
- xwin->overlay.phase, row * OVERLAY_ROW_HEIGHT, /* dst x, y */
- 1, a_height); /* dst w, h */
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.graphb_picture, &overlay_visible_color,
- xwin->overlay.phase, row * OVERLAY_ROW_HEIGHT + (OVERLAY_ROW_HEIGHT - b_height) - 1, /* dst x, y */
- 1, b_height); /* dst w, h */
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->grapha_picture, &overlay_visible_color,
+ overlay->phase, row * OVERLAY_ROW_HEIGHT, /* dst x, y */
+ 1, a_height); /* dst w, h */
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->graphb_picture, &overlay_visible_color,
+ overlay->phase, row * OVERLAY_ROW_HEIGHT + (OVERLAY_ROW_HEIGHT - b_height) - 1, /* dst x, y */
+ 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, int heirarchy_changed)
+static void draw_heirarchy_row(vwm_overlays_t *overlays, vwm_overlay_t *overlay, vmon_proc_t *proc, int depth, int row, int heirarchy_changed)
{
+ vwm_xserver_t *xserver = overlays->xserver;
vmon_proc_stat_t *proc_stat = proc->stores[VMON_STORE_PROC_STAT];
vmon_proc_t *child;
char str[256];
@@ -411,7 +438,7 @@ static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *pro
/* process heirarchy text and accompanying per-process details like wchan/pid/state... */
/* skip if obviously unnecessary (this can be further improved, but this makes a big difference as-is) */
- if (!xwin->overlay.redraw_needed &&
+ if (!overlay->redraw_needed &&
!heirarchy_changed &&
!BITTEST(proc_stat->changed, VMON_PROC_STAT_WCHAN) &&
!BITTEST(proc_stat->changed, VMON_PROC_STAT_PID) &&
@@ -421,9 +448,9 @@ static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *pro
/* 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_XDISPLAY(vwm), 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 */
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->text_picture, &overlay_trans_color,
+ 0, row * OVERLAY_ROW_HEIGHT, /* dst x, y */
+ overlay->width, OVERLAY_ROW_HEIGHT); /* dst w, h */
}
/* put the process' wchan, state, and PID columns @ the far right */
@@ -437,27 +464,27 @@ static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *pro
} 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(vwm->overlays->overlay_font, str, str_len);
+ str_width = XTextWidth(overlays->overlay_font, str, str_len);
/* the process' comm label indented according to depth, followed with their respective argv's */
argv2xtext(proc, items, NELEMS(items), &nr_items);
- XDrawText(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
- depth * (OVERLAY_ROW_HEIGHT / 2), (row + 1) * OVERLAY_ROW_HEIGHT - 3, /* dst x, y */
+ XDrawText(xserver->display, overlay->text_pixmap, overlays->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_XDISPLAY(vwm), 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 */
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->text_picture, &overlay_trans_color,
+ overlay->visible_width - str_width, row * OVERLAY_ROW_HEIGHT, /* dst x,y */
+ overlay->width - (overlay->visible_width - str_width), OVERLAY_ROW_HEIGHT); /* dst w,h */
}
- XDrawString(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
- xwin->attrs.width - str_width, (row + 1) * OVERLAY_ROW_HEIGHT - 3, /* dst x, y */
+ XDrawString(xserver->display, overlay->text_pixmap, overlays->text_gc,
+ overlay->visible_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) {
+ if (proc != overlay->monitor) {
vmon_proc_t *ancestor, *sibling, *last_sibling = NULL;
struct list_head *rem;
int needs_tee = 0;
@@ -466,16 +493,16 @@ static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *pro
/* 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 */
+ /* walk up the ancestors until reaching overlay->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) {
+ for (sub = 1, ancestor = proc->parent; ancestor && ancestor != overlay->monitor; ancestor = ancestor->parent) {
sub++;
bar_x = (depth - sub) * (OVERLAY_ROW_HEIGHT / 2) + 4;
/* 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_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
+ XDrawLine(xserver->display, overlay->text_pixmap, overlays->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 */
@@ -524,16 +551,16 @@ static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *pro
/* if we're the last sibling, corner the tee by shortening the vbar */
if (proc == last_sibling) {
- XDrawLine(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
+ XDrawLine(xserver->display, overlay->text_pixmap, overlays->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_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
+ XDrawLine(xserver->display, overlay->text_pixmap, overlays->text_gc,
bar_x, bar_y - OVERLAY_ROW_HEIGHT, /* dst x1, y1 */
bar_x, bar_y); /* dst x2, y2 (vertical bar) */
}
- XDrawLine(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
+ XDrawLine(xserver->display, overlay->text_pixmap, overlays->text_gc,
bar_x, bar_y - 4, /* dst x1, y1 */
bar_x + 2, bar_y - 4); /* dst x2, y2 (horizontal bar) */
@@ -543,13 +570,14 @@ static void draw_heirarchy_row(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *pro
}
}
- shadow_row(vwm, xwin, row);
+ shadow_row(overlays, overlay, 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, int heirarchy_changed)
+static void draw_overlay_rest(vwm_overlays_t *overlays, vwm_overlay_t *overlay, vmon_proc_t *proc, int *depth, int *row, int heirarchy_changed)
{
+ vwm_xserver_t *xserver = overlays->xserver;
vmon_proc_t *child;
vwm_perproc_ctxt_t *proc_ctxt = proc->foo;
vmon_proc_stat_t *proc_stat = proc->stores[VMON_STORE_PROC_STAT];
@@ -576,20 +604,20 @@ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc
/* This does require that I do a separate forward recursion to determine the number of rows
* so I can correctly snowflake in reverse */
if (!in_stale) {
- VWM_TRACE("entered stale at xwin=%p depth=%i row=%i", xwin, *depth, *row);
+ VWM_TRACE("entered stale at overlay=%p depth=%i row=%i", overlay, *depth, *row);
in_stale_entrypoint = in_stale = 1;
(*row) += count_rows(proc) - 1;
}
(*depth)++;
list_for_each_entry_prev(child, &proc->children, siblings) {
- draw_overlay_rest(vwm, xwin, child, depth, row, heirarchy_changed);
+ draw_overlay_rest(overlays, overlay, child, depth, row, heirarchy_changed);
(*row)--;
}
if (!proc->is_thread) {
list_for_each_entry_prev(child, &proc->threads, threads) {
- draw_overlay_rest(vwm, xwin, child, depth, row, heirarchy_changed);
+ draw_overlay_rest(overlays, overlay, child, depth, row, heirarchy_changed);
(*row)--;
}
}
@@ -601,35 +629,35 @@ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc
(*depth), (*row), proc->is_thread);
/* stamp the graphs with the finish line */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, vwm->overlays->overlay_finish_fill, None, xwin->overlay.grapha_picture,
+ XRenderComposite(xserver->display, PictOpSrc, overlays->overlay_finish_fill, None, overlay->grapha_picture,
0, 0, /* src x, y */
0, 0, /* mask x, y */
- xwin->overlay.phase, (*row) * OVERLAY_ROW_HEIGHT, /* dst x, y */
+ overlay->phase, (*row) * OVERLAY_ROW_HEIGHT, /* dst x, y */
1, OVERLAY_ROW_HEIGHT - 1);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, vwm->overlays->overlay_finish_fill, None, xwin->overlay.graphb_picture,
+ XRenderComposite(xserver->display, PictOpSrc, overlays->overlay_finish_fill, None, overlay->graphb_picture,
0, 0, /* src x, y */
0, 0, /* mask x, y */
- xwin->overlay.phase, (*row) * OVERLAY_ROW_HEIGHT, /* dst x, y */
+ overlay->phase, (*row) * OVERLAY_ROW_HEIGHT, /* dst x, y */
1, OVERLAY_ROW_HEIGHT - 1);
/* extract the row from the various layers */
- snowflake_row(vwm, xwin, xwin->overlay.grapha_picture, 1, (*row));
- snowflake_row(vwm, xwin, xwin->overlay.graphb_picture, 1, (*row));
- snowflake_row(vwm, xwin, xwin->overlay.text_picture, 0, (*row));
- snowflake_row(vwm, xwin, xwin->overlay.shadow_picture, 0, (*row));
- xwin->overlay.snowflakes_cnt++;
+ snowflake_row(overlays, overlay, overlay->grapha_picture, 1, (*row));
+ snowflake_row(overlays, overlay, overlay->graphb_picture, 1, (*row));
+ snowflake_row(overlays, overlay, overlay->text_picture, 0, (*row));
+ snowflake_row(overlays, overlay, overlay->shadow_picture, 0, (*row));
+ overlay->snowflakes_cnt++;
/* stamp the name (and whatever else we include) into overlay.text_picture */
argv2xtext(proc, items, NELEMS(items), &nr_items);
- XDrawText(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
- 5, (xwin->overlay.heirarchy_end + 1) * OVERLAY_ROW_HEIGHT - 3,/* dst x, y */
+ XDrawText(xserver->display, overlay->text_pixmap, overlays->text_gc,
+ 5, (overlay->heirarchy_end + 1) * OVERLAY_ROW_HEIGHT - 3,/* dst x, y */
items, nr_items);
- shadow_row(vwm, xwin, xwin->overlay.heirarchy_end);
+ shadow_row(overlays, overlay, overlay->heirarchy_end);
- xwin->overlay.heirarchy_end--;
+ overlay->heirarchy_end--;
if (in_stale_entrypoint) {
- VWM_TRACE("exited stale at xwin=%p depth=%i row=%i", xwin, *depth, *row);
+ VWM_TRACE("exited stale at overlay=%p depth=%i row=%i", overlay, *depth, *row);
in_stale = 0;
}
@@ -638,37 +666,37 @@ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc
/* what to do when a process has been introduced */
VWM_TRACE("%i is new", proc->pid);
- allocate_row(vwm, xwin, xwin->overlay.grapha_picture, (*row));
- allocate_row(vwm, xwin, xwin->overlay.graphb_picture, (*row));
- allocate_row(vwm, xwin, xwin->overlay.text_picture, (*row));
- allocate_row(vwm, xwin, xwin->overlay.shadow_picture, (*row));
+ allocate_row(overlays, overlay, overlay->grapha_picture, (*row));
+ allocate_row(overlays, overlay, overlay->graphb_picture, (*row));
+ allocate_row(overlays, overlay, overlay->text_picture, (*row));
+ allocate_row(overlays, overlay, overlay->shadow_picture, (*row));
- xwin->overlay.heirarchy_end++;
+ overlay->heirarchy_end++;
}
/* CPU utilization graphs */
/* use the generation number to avoid recomputing this stuff for callbacks recurring on the same process in the same sample */
- if (proc_ctxt->generation != vwm->overlays->vmon.generation) {
+ if (proc_ctxt->generation != overlays->vmon.generation) {
proc_ctxt->stime_delta = proc_stat->stime - proc_ctxt->last_stime;
proc_ctxt->utime_delta = proc_stat->utime - proc_ctxt->last_utime;
proc_ctxt->last_utime = proc_stat->utime;
proc_ctxt->last_stime = proc_stat->stime;
- proc_ctxt->generation = vwm->overlays->vmon.generation;
+ proc_ctxt->generation = overlays->vmon.generation;
}
if (proc->is_new) {
/* we need a minimum of two samples before we can compute a delta to plot,
* so we suppress that and instead mark the start of monitoring with an impossible 100% of both graph contexts, a starting line. */
- stime_delta = utime_delta = vwm->overlays->total_delta;
+ stime_delta = utime_delta = overlays->total_delta;
} else {
stime_delta = proc_ctxt->stime_delta;
utime_delta = proc_ctxt->utime_delta;
}
- draw_bars(vwm, xwin, *row, stime_delta, vwm->overlays->total_delta, utime_delta, vwm->overlays->total_delta);
+ draw_bars(overlays, overlay, *row, stime_delta, overlays->total_delta, utime_delta, overlays->total_delta);
- draw_heirarchy_row(vwm, xwin, proc, *depth, *row, heirarchy_changed);
+ draw_heirarchy_row(overlays, overlay, proc, *depth, *row, heirarchy_changed);
(*row)++;
@@ -676,21 +704,21 @@ static void draw_overlay_rest(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc
(*depth)++;
if (!proc->is_thread) { /* XXX: the threads member serves as the list head only when not a thread */
list_for_each_entry(child, &proc->threads, threads) {
- draw_overlay_rest(vwm, xwin, child, depth, row, heirarchy_changed);
+ draw_overlay_rest(overlays, overlay, child, depth, row, heirarchy_changed);
}
}
list_for_each_entry(child, &proc->children, siblings) {
- draw_overlay_rest(vwm, xwin, child, depth, row, heirarchy_changed);
+ draw_overlay_rest(overlays, overlay, child, depth, row, heirarchy_changed);
}
(*depth)--;
}
-
/* recursive draw function entrypoint, draws the IOWait/Idle/HZ row, then enters draw_overlay_rest() */
-static void draw_overlay(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc, int *depth, int *row)
+static void draw_overlay(vwm_overlays_t *overlays, vwm_overlay_t *overlay, vmon_proc_t *proc, int *depth, int *row)
{
+ vwm_xserver_t *xserver = overlays->xserver;
vmon_proc_t *child;
vwm_perproc_ctxt_t *proc_ctxt = proc->foo;
vmon_proc_stat_t *proc_stat = proc->stores[VMON_STORE_PROC_STAT];
@@ -703,42 +731,43 @@ static void draw_overlay(vwm_t *vwm, vwm_xwindow_t *xwin, vmon_proc_t *proc, int
/* CPU utilization graphs */
/* IOWait and Idle % @ row 0 */
- draw_bars(vwm, xwin, *row, vwm->overlays->iowait_delta, vwm->overlays->total_delta, vwm->overlays->idle_delta, vwm->overlays->total_delta);
+ draw_bars(overlays, overlay, *row, overlays->iowait_delta, overlays->total_delta, overlays->idle_delta, overlays->total_delta);
/* only draw the \/\/\ and HZ if necessary */
- if (xwin->overlay.redraw_needed || vwm->overlays->prev_sampling_interval != vwm->overlays->sampling_interval) {
- snprintf(str, sizeof(str), "\\/\\/\\ %2iHz %n", (int)(vwm->overlays->sampling_interval < 0 ? 0 : 1 / sampling_intervals[vwm->overlays->sampling_interval]), &str_len);
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.text_picture, &overlay_trans_color,
- 0, 0, /* dst x, y */
- xwin->attrs.width, OVERLAY_ROW_HEIGHT); /* dst w, h */
- str_width = XTextWidth(vwm->overlays->overlay_font, str, str_len);
- XDrawString(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, vwm->overlays->text_gc,
- xwin->attrs.width - str_width, OVERLAY_ROW_HEIGHT - 3, /* dst x, y */
+ if (overlay->redraw_needed || overlays->prev_sampling_interval != overlays->sampling_interval) {
+ snprintf(str, sizeof(str), "\\/\\/\\ %2iHz %n", (int)(overlays->sampling_interval < 0 ? 0 : 1 / sampling_intervals[overlays->sampling_interval]), &str_len);
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->text_picture, &overlay_trans_color,
+ 0, 0, /* dst x, y */
+ overlay->visible_width, OVERLAY_ROW_HEIGHT); /* dst w, h */
+ str_width = XTextWidth(overlays->overlay_font, str, str_len);
+ XDrawString(xserver->display, overlay->text_pixmap, overlays->text_gc,
+ overlay->visible_width - str_width, OVERLAY_ROW_HEIGHT - 3, /* dst x, y */
str, str_len);
- shadow_row(vwm, xwin, 0);
+ shadow_row(overlays, overlay, 0);
}
(*row)++;
- if (!xwin->overlay.redraw_needed) heirarchy_changed = proc_heirarchy_changed(proc);
+ if (!overlay->redraw_needed) heirarchy_changed = proc_heirarchy_changed(proc);
- draw_overlay_rest(vwm, xwin, proc, depth, row, heirarchy_changed);
+ draw_overlay_rest(overlays, overlay, proc, depth, row, heirarchy_changed);
- xwin->overlay.redraw_needed = 0;
+ overlay->redraw_needed = 0;
return;
}
-/* consolidated version of overlay text and graph rendering, makes snowflakes integration cleaner, this always gets called regadless of the overlays mode */
-static void maintain_overlay(vwm_t *vwm, vwm_xwindow_t *xwin)
+/* consolidated version of overlay text and graph rendering, makes snowflakes integration cleaner, this always gets called regardless of the overlays mode */
+static void maintain_overlay(vwm_overlays_t *overlays, vwm_overlay_t *overlay)
{
- int row = 0, depth = 0;
+ vwm_xserver_t *xserver = overlays->xserver;
+ int row = 0, depth = 0;
- if (!xwin->monitor || !xwin->monitor->stores[VMON_STORE_PROC_STAT]) return;
+ if (!overlay->monitor || !overlay->monitor->stores[VMON_STORE_PROC_STAT]) return;
/* TODO:
- * I side effect of responding to window resizes in this function is there's a latency proportional to the current sample_interval.
+ * A side effect of responding to window resizes in this function is there's a latency proportional to the current sample_interval.
* Something to fix is to resize the overlays when the window resizes.
* However, simply resizing the overlays is insufficient. Their contents need to be redrawn in the new dimensions, this is where it
* gets annoying. The current maintain/draw_overlay makes assumptions about being run from the periodic vmon per-process callback.
@@ -749,239 +778,306 @@ static void maintain_overlay(vwm_t *vwm, vwm_xwindow_t *xwin)
* For now, the monitors will just be a little latent in window resizes which is pretty harmless artifact.
*/
- if (xwin->attrs.width != xwin->overlay.width || xwin->attrs.height != xwin->overlay.height) xwin->overlay.redraw_needed = 1;
+ overlay->phase += (overlay->width - 1); /* simply change this to .phase++ to scroll the other direction */
+ overlay->phase %= overlay->width;
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->grapha_picture, &overlay_trans_color, overlay->phase, 0, 1, overlay->height);
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->graphb_picture, &overlay_trans_color, overlay->phase, 0, 1, overlay->height);
+
+ /* recursively draw the monitored processes to the overlay */
+ draw_overlay(overlays, overlay, overlay->monitor, &depth, &row);
+}
+
+
+/* this callback gets invoked at sample time for every process we've explicitly monitored (not autofollowed children/threads)
+ * It's where we update the cumulative data for all windows, including the graph masks, regardless of their visibility
+ * It's also where we compose the graphs and text for visible windows into a picture ready for compositing with the window contents */
+static void proc_sample_callback(vmon_t *vmon, void *sys_cb_arg, vmon_proc_t *proc, void *proc_cb_arg)
+{
+ vwm_overlays_t *overlays = sys_cb_arg;
+ vwm_overlay_t *overlay = proc_cb_arg;
+
+ VWM_TRACE("proc=%p overlay=%p", proc, overlay);
+
+ /* render the various always-updated overlays, this is the component we do regardless of the overlays mode and window visibility,
+ * essentially the incrementally rendered/historic components */
+ maintain_overlay(overlays, overlay);
+
+ /* XXX TODO: we used to mark repaint as being needed if this overlay's window was mapped, but
+ * since extricating overlays from windows that's no longer convenient, and repaint is
+ * always performed after a sample. Make sure the repainting isn't costly when nothing
+ * overlayed is mapped (the case that code optimized)
+ */
+}
+
+
+/* return the composed height of the overlay */
+static int vwm_overlay_composed_height(vwm_overlays_t *overlays, vwm_overlay_t *overlay)
+{
+ int snowflakes = overlay->snowflakes_cnt ? 1 + overlay->snowflakes_cnt : 0; /* don't include the separator row if there are no snowflakes */
- /* if the window is larger than the overlays currently are, enlarge them */
- if (xwin->attrs.width > xwin->overlay.width || xwin->attrs.height > xwin->overlay.height) {
+ return MIN((overlay->heirarchy_end + snowflakes) * OVERLAY_ROW_HEIGHT, overlay->visible_height);
+}
+
+
+/* reset snowflakes on the specified overlay */
+void vwm_overlay_reset_snowflakes(vwm_overlays_t *overlays, vwm_overlay_t *overlay)
+{
+ if (overlay->snowflakes_cnt) {
+ overlay->snowflakes_cnt = 0;
+ overlay->redraw_needed = 1;
+ }
+}
+
+
+static void vwm_overlay_free_pictures(vwm_overlays_t *overlays, vwm_overlay_t *overlay)
+{
+ vwm_xserver_t *xserver = overlays->xserver;
+
+ XRenderFreePicture(xserver->display, overlay->grapha_picture);
+ XRenderFreePicture(xserver->display, overlay->graphb_picture);
+ XRenderFreePicture(xserver->display, overlay->tmp_picture);
+ XRenderFreePicture(xserver->display, overlay->text_picture);
+ XFreePixmap(xserver->display, overlay->text_pixmap);
+ XRenderFreePicture(xserver->display, overlay->shadow_picture);
+ XRenderFreePicture(xserver->display, overlay->picture);
+
+}
+
+
+/* (re)size the specified overlay's visible dimensions */
+int vwm_overlay_set_visible_size(vwm_overlays_t *overlays, vwm_overlay_t *overlay, int width, int height)
+{
+ vwm_xserver_t *xserver = overlays->xserver;
+
+ if (width != overlay->visible_width || height != overlay->visible_height) overlay->redraw_needed = 1;
+
+ /* TODO error handling: if a create failed but we had an overlay, free whatever we created and leave it be, succeed.
+ * if none existed it's a hard error and we must propagate it. */
+
+ /* if larger than the overlays currently are, enlarge them */
+ if (width > overlay->width || height > overlay->height) {
vwm_overlay_t existing;
Pixmap pixmap;
- existing = xwin->overlay;
+ existing = *overlay;
- xwin->overlay.width = MAX(xwin->overlay.width, MAX(xwin->attrs.width, OVERLAY_GRAPH_MIN_WIDTH));
- xwin->overlay.height = MAX(xwin->overlay.height, MAX(xwin->attrs.height, OVERLAY_GRAPH_MIN_HEIGHT));
+ overlay->width = MAX(overlay->width, MAX(width, OVERLAY_GRAPH_MIN_WIDTH));
+ overlay->height = MAX(overlay->height, MAX(height, OVERLAY_GRAPH_MIN_HEIGHT));
- pixmap = XCreatePixmap(VWM_XDISPLAY(vwm), VWM_XROOT(vwm), xwin->overlay.width, xwin->overlay.height, OVERLAY_MASK_DEPTH);
- xwin->overlay.grapha_picture = XRenderCreatePicture(VWM_XDISPLAY(vwm), pixmap, XRenderFindStandardFormat(VWM_XDISPLAY(vwm), OVERLAY_MASK_FORMAT), CPRepeat, &pa_repeat);
- XFreePixmap(VWM_XDISPLAY(vwm), pixmap);
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.grapha_picture, &overlay_trans_color, 0, 0, xwin->overlay.width, xwin->overlay.height);
+ pixmap = XCreatePixmap(xserver->display, XSERVER_XROOT(xserver), overlay->width, overlay->height, OVERLAY_MASK_DEPTH);
+ overlay->grapha_picture = XRenderCreatePicture(xserver->display, pixmap, XRenderFindStandardFormat(xserver->display, OVERLAY_MASK_FORMAT), CPRepeat, &pa_repeat);
+ XFreePixmap(xserver->display, pixmap);
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->grapha_picture, &overlay_trans_color, 0, 0, overlay->width, overlay->height);
- pixmap = XCreatePixmap(VWM_XDISPLAY(vwm), VWM_XROOT(vwm), xwin->overlay.width, xwin->overlay.height, OVERLAY_MASK_DEPTH);
- xwin->overlay.graphb_picture = XRenderCreatePicture(VWM_XDISPLAY(vwm), pixmap, XRenderFindStandardFormat(VWM_XDISPLAY(vwm), OVERLAY_MASK_FORMAT), CPRepeat, &pa_repeat);
- XFreePixmap(VWM_XDISPLAY(vwm), pixmap);
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.graphb_picture, &overlay_trans_color, 0, 0, xwin->overlay.width, xwin->overlay.height);
+ pixmap = XCreatePixmap(xserver->display, XSERVER_XROOT(xserver), overlay->width, overlay->height, OVERLAY_MASK_DEPTH);
+ overlay->graphb_picture = XRenderCreatePicture(xserver->display, pixmap, XRenderFindStandardFormat(xserver->display, OVERLAY_MASK_FORMAT), CPRepeat, &pa_repeat);
+ XFreePixmap(xserver->display, pixmap);
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->graphb_picture, &overlay_trans_color, 0, 0, overlay->width, overlay->height);
- pixmap = XCreatePixmap(VWM_XDISPLAY(vwm), VWM_XROOT(vwm), xwin->overlay.width, OVERLAY_ROW_HEIGHT, OVERLAY_MASK_DEPTH);
- xwin->overlay.tmp_picture = XRenderCreatePicture(VWM_XDISPLAY(vwm), pixmap, XRenderFindStandardFormat(VWM_XDISPLAY(vwm), OVERLAY_MASK_FORMAT), 0, NULL);
- XFreePixmap(VWM_XDISPLAY(vwm), pixmap);
+ pixmap = XCreatePixmap(xserver->display, XSERVER_XROOT(xserver), overlay->width, OVERLAY_ROW_HEIGHT, OVERLAY_MASK_DEPTH);
+ overlay->tmp_picture = XRenderCreatePicture(xserver->display, pixmap, XRenderFindStandardFormat(xserver->display, OVERLAY_MASK_FORMAT), 0, NULL);
+ XFreePixmap(xserver->display, pixmap);
/* keep the text_pixmap reference around for XDrawText usage */
- xwin->overlay.text_pixmap = XCreatePixmap(VWM_XDISPLAY(vwm), VWM_XROOT(vwm), xwin->overlay.width, xwin->overlay.height, OVERLAY_MASK_DEPTH);
- xwin->overlay.text_picture = XRenderCreatePicture(VWM_XDISPLAY(vwm), xwin->overlay.text_pixmap, XRenderFindStandardFormat(VWM_XDISPLAY(vwm), OVERLAY_MASK_FORMAT), 0, NULL);
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.text_picture, &overlay_trans_color, 0, 0, xwin->overlay.width, xwin->overlay.height);
+ overlay->text_pixmap = XCreatePixmap(xserver->display, XSERVER_XROOT(xserver), overlay->width, overlay->height, OVERLAY_MASK_DEPTH);
+ overlay->text_picture = XRenderCreatePicture(xserver->display, overlay->text_pixmap, XRenderFindStandardFormat(xserver->display, OVERLAY_MASK_FORMAT), 0, NULL);
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->text_picture, &overlay_trans_color, 0, 0, overlay->width, overlay->height);
- pixmap = XCreatePixmap(VWM_XDISPLAY(vwm), VWM_XROOT(vwm), xwin->overlay.width, xwin->overlay.height, OVERLAY_MASK_DEPTH);
- xwin->overlay.shadow_picture = XRenderCreatePicture(VWM_XDISPLAY(vwm), pixmap, XRenderFindStandardFormat(VWM_XDISPLAY(vwm), OVERLAY_MASK_FORMAT), 0, NULL);
- XFreePixmap(VWM_XDISPLAY(vwm), pixmap);
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.shadow_picture, &overlay_trans_color, 0, 0, xwin->overlay.width, xwin->overlay.height);
+ pixmap = XCreatePixmap(xserver->display, XSERVER_XROOT(xserver), overlay->width, overlay->height, OVERLAY_MASK_DEPTH);
+ overlay->shadow_picture = XRenderCreatePicture(xserver->display, pixmap, XRenderFindStandardFormat(xserver->display, OVERLAY_MASK_FORMAT), 0, NULL);
+ XFreePixmap(xserver->display, pixmap);
+ XRenderFillRectangle(xserver->display, PictOpSrc, overlay->shadow_picture, &overlay_trans_color, 0, 0, overlay->width, overlay->height);
- pixmap = XCreatePixmap(VWM_XDISPLAY(vwm), VWM_XROOT(vwm), xwin->overlay.width, xwin->overlay.height, 32);
- xwin->overlay.picture = XRenderCreatePicture(VWM_XDISPLAY(vwm), pixmap, XRenderFindStandardFormat(VWM_XDISPLAY(vwm), PictStandardARGB32), 0, NULL);
- XFreePixmap(VWM_XDISPLAY(vwm), pixmap);
+ pixmap = XCreatePixmap(xserver->display, XSERVER_XROOT(xserver), overlay->width, overlay->height, 32);
+ overlay->picture = XRenderCreatePicture(xserver->display, pixmap, XRenderFindStandardFormat(xserver->display, PictStandardARGB32), 0, NULL);
+ XFreePixmap(xserver->display, pixmap);
if (existing.width) {
/* XXX: note the graph pictures are copied from their current phase in the x dimension */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, existing.grapha_picture, None, xwin->overlay.grapha_picture,
+ XRenderComposite(xserver->display, PictOpSrc, existing.grapha_picture, None, overlay->grapha_picture,
existing.phase, 0, /* src x, y */
0, 0, /* mask x, y */
0, 0, /* dest x, y */
existing.width, existing.height);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, existing.graphb_picture, None, xwin->overlay.graphb_picture,
+ XRenderComposite(xserver->display, PictOpSrc, existing.graphb_picture, None, overlay->graphb_picture,
existing.phase, 0, /* src x, y */
0, 0, /* mask x, y */
0, 0, /* dest x, y */
existing.width, existing.height);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, existing.text_picture, None, xwin->overlay.text_picture,
+ XRenderComposite(xserver->display, PictOpSrc, existing.text_picture, None, overlay->text_picture,
0, 0, /* src x, y */
0, 0, /* mask x, y */
0, 0, /* dest x, y */
existing.width, existing.height);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, existing.shadow_picture, None, xwin->overlay.shadow_picture,
+ XRenderComposite(xserver->display, PictOpSrc, existing.shadow_picture, None, overlay->shadow_picture,
0, 0, /* src x, y */
0, 0, /* mask x, y */
0, 0, /* dest x, y */
existing.width, existing.height);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, existing.picture, None, xwin->overlay.picture,
+ XRenderComposite(xserver->display, PictOpSrc, existing.picture, None, overlay->picture,
0, 0, /* src x, y */
0, 0, /* mask x, y */
0, 0, /* dest x, y */
existing.width, existing.height);
- xwin->overlay.phase = 0; /* having unrolled the existing graph[ab] pictures into the larger ones, phase is reset to 0 */
- XRenderFreePicture(VWM_XDISPLAY(vwm), existing.grapha_picture);
- XRenderFreePicture(VWM_XDISPLAY(vwm), existing.graphb_picture);
- XRenderFreePicture(VWM_XDISPLAY(vwm), existing.tmp_picture);
- XRenderFreePicture(VWM_XDISPLAY(vwm), existing.text_picture);
- XFreePixmap(VWM_XDISPLAY(vwm), existing.text_pixmap);
- XRenderFreePicture(VWM_XDISPLAY(vwm), existing.shadow_picture);
- XRenderFreePicture(VWM_XDISPLAY(vwm), existing.picture);
+ overlay->phase = 0; /* having unrolled the existing graph[ab] pictures into the larger ones, phase is reset to 0 */
+
+ vwm_overlay_free_pictures(overlays, &existing);
}
}
- xwin->overlay.phase += (xwin->overlay.width - 1); /* simply change this to .phase++ to scroll the other direction */
- xwin->overlay.phase %= xwin->overlay.width;
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.grapha_picture, &overlay_trans_color, xwin->overlay.phase, 0, 1, xwin->overlay.height);
- XRenderFillRectangle(VWM_XDISPLAY(vwm), PictOpSrc, xwin->overlay.graphb_picture, &overlay_trans_color, xwin->overlay.phase, 0, 1, xwin->overlay.height);
+ overlay->visible_width = width;
+ overlay->visible_height = height;
- /* recursively draw the monitored processes to the overlay */
- draw_overlay(vwm, xwin, xwin->monitor, &depth, &row);
+ return 1;
}
-/* this callback gets invoked at sample time for every process we've explicitly monitored (not autofollowed children/threads)
- * It's where we update the cumulative data for all windows, including the graph masks, regardless of their visibility
- * It's also where we compose the graphs and text for visible windows into a picture ready for compositing with the window contents */
-static void proc_sample_callback(vmon_t *vmon, void *sys_cb_arg, vmon_proc_t *proc, void *proc_cb_arg)
+/* create an overlay and start monitoring for the supplied pid */
+vwm_overlay_t * vwm_overlay_create(vwm_overlays_t *overlays, int pid, int width, int height)
{
- vwm_t *vwm = sys_cb_arg;
- vwm_xwindow_t *xwin = proc_cb_arg;
- //VWM_TRACE("proc=%p xwin=%p", proc, xwin);
- /* render the various always-updated overlays, this is the component we do regardless of the overlays mode and window visibility,
- * essentially the incrementally rendered/historic components */
- maintain_overlay(vwm, xwin);
+ vwm_overlay_t *overlay;
- /* if we've updated overlays for a mapped window, kick the compositor to do the costly parts of overlay drawing and compositing. */
- if (vwm_xwin_is_mapped(vwm, xwin)) vwm_composite_repaint_needed(vwm);
-}
-
-
-/* return the composed height of the overlay */
-int vwm_overlay_xwin_composed_height(vwm_t *vwm, vwm_xwindow_t *xwin)
-{
- int snowflakes = xwin->overlay.snowflakes_cnt ? 1 + xwin->overlay.snowflakes_cnt : 0; /* don't include the separator row if there are no snowflakes */
-
- return MIN((xwin->overlay.heirarchy_end + snowflakes) * OVERLAY_ROW_HEIGHT, xwin->attrs.height);
-}
+ overlay = calloc(1, sizeof(vwm_overlay_t));
+ if (!overlay) {
+ VWM_PERROR("Unable to allocate vwm_overlay_t");
+ goto _err;
+ }
-/* reset snowflakes on the specified window */
-void vwm_overlay_xwin_reset_snowflakes(vwm_t *vwm, vwm_xwindow_t *xwin) {
- if (xwin->overlay.snowflakes_cnt) {
- xwin->overlay.snowflakes_cnt = 0;
- vwm_composite_damage_win(vwm, xwin);
+ /* add the client process to the monitoring heirarchy */
+ /* XXX note libvmon here maintains a unique callback for each unique callback+xwin pair, so multi-window processes work */
+ overlay->monitor = vmon_proc_monitor(&overlays->vmon, NULL, pid, VMON_WANT_PROC_INHERIT, (void (*)(vmon_t *, void *, vmon_proc_t *, void *))proc_sample_callback, overlay);
+ if (!overlay->monitor) {
+ VWM_ERROR("Unable to establish proc monitor");
+ goto _err_free;
}
-}
-/* install a monitor on the window if it doesn't already have one and has _NET_WM_PID set */
-void vwm_overlay_xwin_create(vwm_t *vwm, vwm_xwindow_t *xwin)
-{
- Atom type;
- int fmt;
- unsigned long nitems;
- unsigned long nbytes;
- long *foo = NULL;
- int pid = -1;
+ /* FIXME: count_rows() isn't returning the right count sometimes (off by ~1), it seems to be related to racing with the automatic child monitoring */
+ /* the result is an extra row sometimes appearing below the process heirarchy */
+ overlay->heirarchy_end = 1 + count_rows(overlay->monitor);
+ overlay->gen_last_composed = -1;
- if (xwin->monitor) return;
+ if (!vwm_overlay_set_visible_size(overlays, overlay, width, height)) {
+ VWM_ERROR("Unable to set initial overlay size");
+ goto _err_unmonitor;
+ }
- if (XGetWindowProperty(VWM_XDISPLAY(vwm), xwin->id, vwm->wm_pid_atom, 0, 1, False, XA_CARDINAL,
- &type, &fmt, &nitems, &nbytes, (unsigned char **)&foo) != Success || !foo) return;
+ return overlay;
- pid = *foo;
- XFree(foo);
+_err_unmonitor:
+ vmon_proc_unmonitor(&overlays->vmon, overlay->monitor, (void (*)(vmon_t *, void *, vmon_proc_t *, void *))proc_sample_callback, overlay);
- /* add the client process to the monitoring heirarchy */
- /* XXX note libvmon here maintains a unique callback for each unique callback+xwin pair, so multi-window processes work */
- xwin->monitor = vmon_proc_monitor(&vwm->overlays->vmon, NULL, pid, VMON_WANT_PROC_INHERIT, (void (*)(vmon_t *, void *, vmon_proc_t *, void *))proc_sample_callback, xwin);
- /* FIXME: count_rows() isn't returning the right count sometimes (off by ~1), it seems to be related to racing with the automatic child monitoring */
- /* the result is an extra row sometimes appearing below the process heirarchy */
- xwin->overlay.heirarchy_end = 1 + count_rows(xwin->monitor);
- xwin->overlay.snowflakes_cnt = 0;
+_err_free:
+ free(overlay);
+_err:
+ return NULL;
}
-/* remove monitoring on the window if installed */
-void vwm_overlay_xwin_destroy(vwm_t *vwm, vwm_xwindow_t *xwin)
+/* stop monitoring and destroy the supplied overlay */
+void vwm_overlay_destroy(vwm_overlays_t *overlays, vwm_overlay_t *overlay)
{
- if (xwin->monitor) vmon_proc_unmonitor(&vwm->overlays->vmon, xwin->monitor, (void (*)(vmon_t *, void *, vmon_proc_t *, void *))proc_sample_callback, xwin);
+ vmon_proc_unmonitor(&overlays->vmon, overlay->monitor, (void (*)(vmon_t *, void *, vmon_proc_t *, void *))proc_sample_callback, overlay);
+ vwm_overlay_free_pictures(overlays, overlay);
+ free(overlay);
}
-/* this composes the maintained overlay into the window's overlay picture, this gets called from paint_all() on every repaint of xwin */
+/* this composes the maintained overlay into the base overlay picture, this gets called from paint_all() on every repaint of xwin */
/* we noop the call if the gen_last_composed and monitor->proc.generation numbers match, indicating there's nothing new to compose. */
-void vwm_overlay_xwin_compose(vwm_t *vwm, vwm_xwindow_t *xwin)
+void vwm_overlay_compose(vwm_overlays_t *overlays, vwm_overlay_t *overlay, XserverRegion *res_damaged_region)
{
- XserverRegion region;
- XRectangle damage;
+ vwm_xserver_t *xserver = overlays->xserver;
int height;
- if (!xwin->overlay.width) return; /* prevent winning race with maintain_overlay() and using an unready overlay... */
+ if (!overlay->width || !overlay->height) return;
- if (xwin->overlay.gen_last_composed == xwin->monitor->generation) return; /* noop if no sampling occurred since last compose */
- xwin->overlay.gen_last_composed = xwin->monitor->generation; /* remember this generation */
+ if (overlay->gen_last_composed == overlay->monitor->generation) return; /* noop if no sampling occurred since last compose */
+ overlay->gen_last_composed = overlay->monitor->generation; /* remember this generation */
- //VWM_TRACE("composing %p", xwin);
+ //VWM_TRACE("composing %p", overlay);
- height = vwm_overlay_xwin_composed_height(vwm, xwin);
+ height = vwm_overlay_composed_height(overlays, overlay);
/* fill the overlay picture with the background */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpSrc, vwm->overlays->overlay_bg_fill, None, xwin->overlay.picture,
+ XRenderComposite(xserver->display, PictOpSrc, overlays->overlay_bg_fill, None, overlay->picture,
0, 0,
0, 0,
0, 0,
- xwin->attrs.width, height);
+ overlay->visible_width, height);
/* draw the graphs into the overlay through the stencils being maintained by the sample callbacks */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_grapha_fill, xwin->overlay.grapha_picture, xwin->overlay.picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_grapha_fill, overlay->grapha_picture, overlay->picture,
0, 0,
- xwin->overlay.phase, 0,
+ overlay->phase, 0,
0, 0,
- xwin->attrs.width, height);
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_graphb_fill, xwin->overlay.graphb_picture, xwin->overlay.picture,
+ overlay->visible_width, height);
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_graphb_fill, overlay->graphb_picture, overlay->picture,
0, 0,
- xwin->overlay.phase, 0,
+ overlay->phase, 0,
0, 0,
- xwin->attrs.width, height);
+ overlay->visible_width, height);
/* draw the shadow into the overlay picture using a translucent black source drawn through the shadow mask */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_shadow_fill, xwin->overlay.shadow_picture, xwin->overlay.picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_shadow_fill, overlay->shadow_picture, overlay->picture,
0, 0,
0, 0,
0, 0,
- xwin->attrs.width, height);
+ overlay->visible_width, height);
/* render overlay text into the overlay picture using a white source drawn through the overlay text as a mask, on top of everything */
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_text_fill, xwin->overlay.text_picture, xwin->overlay.picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_text_fill, overlay->text_picture, overlay->picture,
0, 0,
0, 0,
0, 0,
- xwin->attrs.width, (xwin->overlay.heirarchy_end * OVERLAY_ROW_HEIGHT));
+ overlay->visible_width, (overlay->heirarchy_end * OVERLAY_ROW_HEIGHT));
- XRenderComposite(VWM_XDISPLAY(vwm), PictOpOver, vwm->overlays->overlay_snowflakes_text_fill, xwin->overlay.text_picture, xwin->overlay.picture,
+ XRenderComposite(xserver->display, PictOpOver, overlays->overlay_snowflakes_text_fill, overlay->text_picture, overlay->picture,
0, 0,
- 0, xwin->overlay.heirarchy_end * OVERLAY_ROW_HEIGHT,
- 0, xwin->overlay.heirarchy_end * OVERLAY_ROW_HEIGHT,
- xwin->attrs.width, height - (xwin->overlay.heirarchy_end * OVERLAY_ROW_HEIGHT));
+ 0, overlay->heirarchy_end * OVERLAY_ROW_HEIGHT,
+ 0, overlay->heirarchy_end * OVERLAY_ROW_HEIGHT,
+ overlay->visible_width, height - (overlay->heirarchy_end * OVERLAY_ROW_HEIGHT));
/* damage the window to ensure the updated overlay is drawn (TODO: this can be done more selectively/efficiently) */
- damage.x = xwin->attrs.x + xwin->attrs.border_width;
- damage.y = xwin->attrs.y + xwin->attrs.border_width;
- damage.width = xwin->attrs.width;
- damage.height = height;
- region = XFixesCreateRegion(VWM_XDISPLAY(vwm), &damage, 1);
- vwm_composite_damage_add(vwm, region);
+ if (res_damaged_region) {
+ XRectangle damage = {};
+
+ damage.width = overlay->visible_width;
+ damage.height = overlay->visible_height;
+
+ *res_damaged_region = XFixesCreateRegion(xserver->display, &damage, 1);
+ }
+}
+
+
+/* render the overlay into a picture at the specified coordinates and dimensions */
+void vwm_overlay_render(vwm_overlays_t *overlays, vwm_overlay_t *overlay, Picture dest, int x, int y, int width, int height)
+{
+ vwm_xserver_t *xserver = overlays->xserver;
+
+ if (!overlay->width || !overlay->height) return;
+
+ /* draw the monitoring overlay atop dest, note we stay within the window borders here. */
+ XRenderComposite(xserver->display, PictOpOver, overlay->picture, None, dest,
+ 0, 0, 0, 0, /* src x,y, maxk x, y */
+ x, /* dst x */
+ y, /* dst y */
+ width, MIN(vwm_overlay_composed_height(overlays, overlay), height) /* FIXME */); /* w, h */
}
+
void vwm_overlays_rate_increase(vwm_overlays_t *overlays)
{
if (overlays->sampling_interval + 1 < sizeof(sampling_intervals) / sizeof(sampling_intervals[0])) overlays->sampling_interval++;
}
+
void vwm_overlays_rate_decrease(vwm_overlays_t *overlays)
{
if (overlays->sampling_interval >= 0) overlays->sampling_interval--;
}
-/* comvenience function for returning the time delta as a seconds.fraction float */
+/* convenience function for returning the time delta as a seconds.fraction float */
static float delta(struct timeval *cur, struct timeval *prev)
{
struct timeval res;
diff --git a/src/overlays.h b/src/overlays.h
index 19678e5..0c00101 100644
--- a/src/overlays.h
+++ b/src/overlays.h
@@ -1,40 +1,25 @@
#ifndef _OVERLAYS_H
#define _OVERLAYS_H
-#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xrender.h>
-typedef struct _vwm_t vwm_t;
-typedef struct _vwm_xwindow_t vwm_xwindow_t;
+#include "xserver.h"
-/* everything needed by the per-window overlay's context */
-typedef struct _vwm_overlay_t {
- Pixmap text_pixmap; /* pixmap for overlayed text (kept around for XDrawText usage) */
- Picture text_picture; /* picture representation of text_pixmap */
- Picture shadow_picture; /* text shadow layer */
- Picture grapha_picture; /* graph A layer */
- Picture graphb_picture; /* graph B layer */
- Picture tmp_picture; /* 1 row worth of temporary picture space */
- Picture picture; /* overlay picture derived from the pixmap, for render compositing */
- int width; /* current width of the overlay */
- int height; /* current height of the overlay */
- int phase; /* current position within the (horizontally scrolling) graphs */
- int heirarchy_end; /* row where the process heirarchy currently ends */
- int snowflakes_cnt; /* count of snowflaked rows (reset to zero to truncate snowflakes display) */
- int gen_last_composed; /* the last composed vmon generation */
- int redraw_needed; /* if a redraw is required (like when the window is resized...) */
-} vwm_overlay_t;
typedef struct _vwm_overlays_t vwm_overlays_t;
+typedef struct _vwm_overlay_t vwm_overlay_t;
-int vwm_overlay_xwin_composed_height(vwm_t *vwm, vwm_xwindow_t *xwin);
-void vwm_overlay_xwin_reset_snowflakes(vwm_t *vwm, vwm_xwindow_t *xwin);
-void vwm_overlay_xwin_create(vwm_t *vwm, vwm_xwindow_t *xwin);
-void vwm_overlay_xwin_destroy(vwm_t *vwm, vwm_xwindow_t *xwin);
-void vwm_overlay_xwin_compose(vwm_t *vwm, vwm_xwindow_t *xwin);
-vwm_overlays_t * vwm_overlays_create(vwm_t *vwm);
+vwm_overlays_t * vwm_overlays_create(vwm_xserver_t *xserver);
void vwm_overlays_destroy(vwm_overlays_t *overlays);
void vwm_overlays_rate_increase(vwm_overlays_t *overlays);
void vwm_overlays_rate_decrease(vwm_overlays_t *overlays);
int vwm_overlays_update(vwm_overlays_t *overlays, int *desired_delay);
+vwm_overlay_t * vwm_overlay_create(vwm_overlays_t *overlays, int pid, int width, int height);
+void vwm_overlay_destroy(vwm_overlays_t *overlays, vwm_overlay_t *overlay);
+void vwm_overlay_reset_snowflakes(vwm_overlays_t *overlays, vwm_overlay_t *overlay);
+int vwm_overlay_set_visible_size(vwm_overlays_t *overlays, vwm_overlay_t *overlay, int width, int height);
+void vwm_overlay_compose(vwm_overlays_t *overlays, vwm_overlay_t *overlay, XserverRegion *res_damaged_region);
+void vwm_overlay_render(vwm_overlays_t *overlays, vwm_overlay_t *overlay, Picture dest, int x, int y, int width, int height);
+
#endif
diff --git a/src/vwm.c b/src/vwm.c
index 979824a..1502ea3 100644
--- a/src/vwm.c
+++ b/src/vwm.c
@@ -79,7 +79,7 @@ static vwm_t * vwm_startup(void)
goto _err_free;
}
- if (!(vwm->overlays = vwm_overlays_create(vwm))) {
+ if (!(vwm->overlays = vwm_overlays_create(vwm->xserver))) {
VWM_ERROR("Failed to create overlays");
goto _err_xclose;
}
@@ -311,7 +311,7 @@ int main(int argc, char *argv[])
do {
int delay;
- vwm_overlays_update(vwm->overlays, &delay);
+ if (vwm_overlays_update(vwm->overlays, &delay)) vwm_composite_repaint_needed(vwm);
XFlush(VWM_XDISPLAY(vwm));
diff --git a/src/xevent.c b/src/xevent.c
index 97c4930..1d79ae6 100644
--- a/src/xevent.c
+++ b/src/xevent.c
@@ -110,6 +110,8 @@ void vwm_xevent_handle_configure_notify(vwm_t *vwm, XConfigureEvent *ev)
vwm_xwin_restack(vwm, xwin, ev->above);
XGetWindowAttributes(VWM_XDISPLAY(vwm), ev->window, &attrs);
vwm_composite_handle_configure(vwm, xwin, &attrs);
+ if (xwin->overlay) vwm_overlay_set_visible_size(vwm->overlays, xwin->overlay, attrs.width, attrs.height);
+
VWM_TRACE("pre x=%i y=%i w=%i h=%i\n", xwin->attrs.x, xwin->attrs.y, xwin->attrs.width, xwin->attrs.height);
xwin->attrs = attrs;
VWM_TRACE("post x=%i y=%i w=%i h=%i\n", xwin->attrs.x, xwin->attrs.y, xwin->attrs.width, xwin->attrs.height);
@@ -269,7 +271,7 @@ void vwm_xevent_handle_property_notify(vwm_t *vwm, XPropertyEvent *ev)
if ((xwin = vwm_xwin_lookup(vwm, ev->window)) &&
ev->atom == vwm->wm_pid_atom &&
- ev->state == PropertyNewValue) vwm_overlay_xwin_create(vwm, xwin);
+ ev->state == PropertyNewValue) vwm_xwin_setup_overlay(vwm, xwin);
}
diff --git a/src/xwindow.c b/src/xwindow.c
index a01b212..8dd2937 100644
--- a/src/xwindow.c
+++ b/src/xwindow.c
@@ -115,6 +115,20 @@ static int vwm_xwin_get_pid(vwm_t *vwm, vwm_xwindow_t *xwin)
}
+/* establishes an overlay on xwin if appropriate and the pid is available */
+void vwm_xwin_setup_overlay(vwm_t *vwm, vwm_xwindow_t *xwin)
+{
+ /* XXX FIXME: handle getting called multiple times on the same xwin */
+
+ /* for regular windows create a monitoring overlay */
+ if (!xwin->attrs.override_redirect) {
+ int pid = vwm_xwin_get_pid(vwm, xwin);
+
+ if (pid != -1) xwin->overlay = vwm_overlay_create(vwm->overlays, pid, xwin->attrs.width, xwin->attrs.height);
+ }
+}
+
+
/* creates and potentially manages a new window (called in response to CreateNotify events, and during startup for all existing windows) */
/* if the window is already mapped and not an override_redirect window, it becomes managed here. */
vwm_xwindow_t * vwm_xwin_create(vwm_t *vwm, Window win, vwm_grab_mode_t grabbed)
@@ -145,8 +159,6 @@ vwm_xwindow_t * vwm_xwin_create(vwm_t *vwm, Window win, vwm_grab_mode_t grabbed)
xwin->attrs = attrs;
XFetchName(VWM_XDISPLAY(vwm), win, &xwin->name);
- xwin->overlay.gen_last_composed = -1;
-
/* This is so we get the PropertyNotify event and can get the pid when it's set post-create,
* with my _NET_WM_PID patch the property is immediately available */
XSelectInput(VWM_XDISPLAY(vwm), win, PropertyChangeMask);
@@ -156,7 +168,7 @@ vwm_xwindow_t * vwm_xwin_create(vwm_t *vwm, Window win, vwm_grab_mode_t grabbed)
* otherwise we could just use !xwin.managed to indicate unmapped, which is more vwm2-like, but insufficient when compositing. */
xwin->mapped = (attrs.map_state != IsUnmapped);
- vwm_overlay_xwin_create(vwm, xwin);
+ vwm_xwin_setup_overlay(vwm, xwin);
vwm_composite_xwin_create(vwm, xwin);
list_add_tail(&xwin->xwindows, &vwm->xwindows); /* created windows are always placed on the top of the stacking order */
@@ -186,7 +198,8 @@ void vwm_xwin_destroy(vwm_t *vwm, vwm_xwindow_t *xwin)
if (xwin->name) XFree(xwin->name);
- vwm_overlay_xwin_destroy(vwm, xwin);
+ if (xwin->overlay) vwm_overlay_destroy(vwm->overlays, xwin->overlay);
+
vwm_composite_xwin_destroy(vwm, xwin);
free(xwin);
diff --git a/src/xwindow.h b/src/xwindow.h
index c72abc4..7c77692 100644
--- a/src/xwindow.h
+++ b/src/xwindow.h
@@ -5,7 +5,6 @@
#include <X11/extensions/Xrender.h>
#include <X11/Xlib.h>
-#include "libvmon/vmon.h"
#include "list.h"
#include "overlays.h"
@@ -22,8 +21,7 @@ typedef struct _vwm_xwindow_t {
Picture picture; /* X picture object representing the window (for compositing) */
Pixmap pixmap; /* X pixmap object representing the window (for compositing) */
- vmon_proc_t *monitor; /* vmon process monitor handle, may be NULL if for example the X client doesn't supply a PID */
- vwm_overlay_t overlay; /* monitoring overlay state */
+ vwm_overlay_t *overlay; /* monitoring overlay state */
char *name; /* client name */
unsigned int mapped:1; /* is the window currently mapped (by client) */
@@ -46,6 +44,7 @@ void vwm_xwin_monitor(vwm_t *vwm, vwm_xwindow_t *xwin);
vwm_xwindow_t * vwm_xwin_create(vwm_t *vwm, Window win, vwm_grab_mode_t grabbed);
void vwm_xwin_destroy(vwm_t *vwm, vwm_xwindow_t *xwin);
void vwm_xwin_restack(vwm_t *vwm, vwm_xwindow_t *xwin, Window new_above);
+void vwm_xwin_setup_overlay(vwm_t *vwm, vwm_xwindow_t *xwin);
int vwm_xwin_create_existing(vwm_t *vwm);
© All Rights Reserved