summaryrefslogtreecommitdiff
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
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.
-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