Taskbar: thumbnails (use slower but safed XGetImage)
This commit is contained in:
@@ -371,8 +371,8 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
|
|||||||
const size_t bmask = 0xff;
|
const size_t bmask = 0xff;
|
||||||
for (size_t i = 0; i < tw * (th - 1) - 1; i++) {
|
for (size_t i = 0; i < tw * (th - 1) - 1; i++) {
|
||||||
u_int32_t c1 = data[i];
|
u_int32_t c1 = data[i];
|
||||||
u_int32_t c2 = data[i+1];
|
u_int32_t c2 = data[i + 1];
|
||||||
u_int32_t c3 = data[i+tw];
|
u_int32_t c3 = data[i + tw];
|
||||||
u_int32_t b = (6 * (c1 & bmask) + (c2 & bmask) + (c3 & bmask)) / 8;
|
u_int32_t b = (6 * (c1 & bmask) + (c2 & bmask) + (c3 & bmask)) / 8;
|
||||||
u_int32_t g = (6 * (c1 & gmask) + (c2 & gmask) + (c3 & gmask)) / 8;
|
u_int32_t g = (6 * (c1 & gmask) + (c2 & gmask) + (c3 & gmask)) / 8;
|
||||||
u_int32_t r = (6 * (c1 & rmask) + (c2 & rmask) + (c3 & rmask)) / 8;
|
u_int32_t r = (6 * (c1 & rmask) + (c2 & rmask) + (c3 & rmask)) / 8;
|
||||||
@@ -381,14 +381,15 @@ void smooth_thumbnail(cairo_surface_t *image_surface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is measured to be slightly faster.
|
// This is measured to be slightly faster.
|
||||||
#define GetPixel(ximg, x, y) ((u_int32_t*)&(ximg->data[y * ximg->bytes_per_line]))[x]
|
#define GetPixel(ximg, x, y) ((u_int32_t *)&(ximg->data[y * ximg->bytes_per_line]))[x]
|
||||||
//#define GetPixel XGetPixel
|
//#define GetPixel XGetPixel
|
||||||
|
|
||||||
cairo_surface_t *screenshot(Window win, size_t size)
|
cairo_surface_t *get_window_thumbnail_ximage(Window win, size_t size, gboolean use_shm)
|
||||||
{
|
{
|
||||||
cairo_surface_t *result = NULL;
|
cairo_surface_t *result = NULL;
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 || wa.map_state != IsViewable)
|
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
|
||||||
|
wa.map_state != IsViewable)
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
if (window_is_iconified(win))
|
if (window_is_iconified(win))
|
||||||
@@ -412,14 +413,18 @@ cairo_surface_t *screenshot(Window win, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
XShmSegmentInfo shminfo;
|
XShmSegmentInfo shminfo;
|
||||||
XImage *ximg = XShmCreateImage(server.display,
|
XImage *ximg;
|
||||||
wa.visual,
|
if (use_shm)
|
||||||
(unsigned)wa.depth,
|
ximg = XShmCreateImage(server.display,
|
||||||
ZPixmap,
|
wa.visual,
|
||||||
NULL,
|
(unsigned)wa.depth,
|
||||||
&shminfo,
|
ZPixmap,
|
||||||
(unsigned)wa.width,
|
NULL,
|
||||||
(unsigned)wa.height);
|
&shminfo,
|
||||||
|
(unsigned)wa.width,
|
||||||
|
(unsigned)wa.height);
|
||||||
|
else
|
||||||
|
ximg = XGetImage(server.display, win, 0, 0, (unsigned)wa.width, (unsigned)wa.height, AllPlanes, ZPixmap);
|
||||||
if (!ximg) {
|
if (!ximg) {
|
||||||
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
fprintf(stderr, RED "tint2: !ximg" RESET "\n");
|
||||||
goto err0;
|
goto err0;
|
||||||
@@ -428,24 +433,26 @@ cairo_surface_t *screenshot(Window win, size_t size)
|
|||||||
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
|
fprintf(stderr, RED "tint2: unusual bits_per_pixel" RESET "\n");
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
shminfo.shmid = shmget(IPC_PRIVATE, (size_t)(ximg->bytes_per_line * ximg->height), IPC_CREAT | 0777);
|
if (use_shm) {
|
||||||
if (shminfo.shmid < 0) {
|
shminfo.shmid = shmget(IPC_PRIVATE, (size_t)(ximg->bytes_per_line * ximg->height), IPC_CREAT | 0777);
|
||||||
fprintf(stderr, RED "tint2: !shmget" RESET "\n");
|
if (shminfo.shmid < 0) {
|
||||||
goto err1;
|
fprintf(stderr, RED "tint2: !shmget" RESET "\n");
|
||||||
}
|
goto err1;
|
||||||
shminfo.shmaddr = ximg->data = (char *)shmat(shminfo.shmid, 0, 0);
|
}
|
||||||
if (!shminfo.shmaddr) {
|
shminfo.shmaddr = ximg->data = (char *)shmat(shminfo.shmid, 0, 0);
|
||||||
fprintf(stderr, RED "tint2: !shmat" RESET "\n");
|
if (!shminfo.shmaddr) {
|
||||||
goto err2;
|
fprintf(stderr, RED "tint2: !shmat" RESET "\n");
|
||||||
}
|
goto err2;
|
||||||
shminfo.readOnly = False;
|
}
|
||||||
if (!XShmAttach(server.display, &shminfo)) {
|
shminfo.readOnly = False;
|
||||||
fprintf(stderr, RED "tint2: !xshmattach" RESET "\n");
|
if (!XShmAttach(server.display, &shminfo)) {
|
||||||
goto err3;
|
fprintf(stderr, RED "tint2: !xshmattach" RESET "\n");
|
||||||
}
|
goto err3;
|
||||||
if (!XShmGetImage(server.display, win, ximg, 0, 0, AllPlanes)) {
|
}
|
||||||
fprintf(stderr, RED "tint2: !xshmgetimage" RESET "\n");
|
if (!XShmGetImage(server.display, win, ximg, 0, 0, AllPlanes)) {
|
||||||
goto err4;
|
fprintf(stderr, RED "tint2: !xshmgetimage" RESET "\n");
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XGetWindowAttributes(server.display, win, &wa);
|
XGetWindowAttributes(server.display, win, &wa);
|
||||||
@@ -530,11 +537,14 @@ cairo_surface_t *screenshot(Window win, size_t size)
|
|||||||
smooth_thumbnail(result);
|
smooth_thumbnail(result);
|
||||||
|
|
||||||
err4:
|
err4:
|
||||||
XShmDetach(server.display, &shminfo);
|
if (use_shm)
|
||||||
|
XShmDetach(server.display, &shminfo);
|
||||||
err3:
|
err3:
|
||||||
shmdt(shminfo.shmaddr);
|
if (use_shm)
|
||||||
|
shmdt(shminfo.shmaddr);
|
||||||
err2:
|
err2:
|
||||||
shmctl(shminfo.shmid, IPC_RMID, NULL);
|
if (use_shm)
|
||||||
|
shmctl(shminfo.shmid, IPC_RMID, NULL);
|
||||||
err1:
|
err1:
|
||||||
XDestroyImage(ximg);
|
XDestroyImage(ximg);
|
||||||
err0:
|
err0:
|
||||||
@@ -545,7 +555,8 @@ cairo_surface_t *get_window_thumbnail_cairo(Window win, int size)
|
|||||||
{
|
{
|
||||||
static cairo_filter_t filter = CAIRO_FILTER_BEST;
|
static cairo_filter_t filter = CAIRO_FILTER_BEST;
|
||||||
XWindowAttributes wa;
|
XWindowAttributes wa;
|
||||||
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 || wa.map_state != IsViewable)
|
if (!XGetWindowAttributes(server.display, win, &wa) || wa.width <= 0 || wa.height <= 0 ||
|
||||||
|
wa.map_state != IsViewable)
|
||||||
return NULL;
|
return NULL;
|
||||||
int w, h;
|
int w, h;
|
||||||
w = wa.width;
|
w = wa.width;
|
||||||
@@ -616,13 +627,27 @@ cairo_surface_t *get_window_thumbnail(Window win, int size)
|
|||||||
{
|
{
|
||||||
cairo_surface_t *image_surface = NULL;
|
cairo_surface_t *image_surface = NULL;
|
||||||
if (0 && server.has_shm && server.composite_manager) {
|
if (0 && server.has_shm && server.composite_manager) {
|
||||||
image_surface = screenshot(win, (size_t)size);
|
image_surface = get_window_thumbnail_ximage(win, (size_t)size, TRUE);
|
||||||
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
||||||
cairo_surface_destroy(image_surface);
|
cairo_surface_destroy(image_surface);
|
||||||
image_surface = NULL;
|
image_surface = NULL;
|
||||||
}
|
}
|
||||||
if (!image_surface)
|
if (!image_surface)
|
||||||
fprintf(stderr, YELLOW "tint2: thumbnail fast path failed, trying slow path" RESET "\n");
|
fprintf(stderr, YELLOW "tint2: XShmGetImage failed, trying slower method" RESET "\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "tint2: captured window using XShmGetImage\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!image_surface) {
|
||||||
|
image_surface = get_window_thumbnail_ximage(win, (size_t)size, FALSE);
|
||||||
|
if (image_surface && cairo_surface_is_blank(image_surface)) {
|
||||||
|
cairo_surface_destroy(image_surface);
|
||||||
|
image_surface = NULL;
|
||||||
|
}
|
||||||
|
if (!image_surface)
|
||||||
|
fprintf(stderr, YELLOW "tint2: XGetImage failed, trying slower method" RESET "\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "tint2: captured window using XGetImage\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!image_surface) {
|
if (!image_surface) {
|
||||||
@@ -632,10 +657,11 @@ cairo_surface_t *get_window_thumbnail(Window win, int size)
|
|||||||
image_surface = NULL;
|
image_surface = NULL;
|
||||||
}
|
}
|
||||||
if (!image_surface)
|
if (!image_surface)
|
||||||
fprintf(stderr, YELLOW "tint2: thumbnail slow path failed" RESET "\n");
|
fprintf(stderr, YELLOW "tint2: capturing window failed" RESET "\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "tint2: captured window using cairo\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!image_surface)
|
if (!image_surface)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user