Eliminate implicit conversions

Use explicit conversions everywhere. Adding bounds check assertions when
necessary.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-03-30 09:07:21 +00:00
parent 532a90d573
commit 0037b7e5fb
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
35 changed files with 786 additions and 671 deletions

View File

@ -46,8 +46,8 @@ endif
add_global_arguments('-D_GNU_SOURCE', language: 'c') add_global_arguments('-D_GNU_SOURCE', language: 'c')
warns = [ 'all', 'extra', 'no-unused-parameter', 'nonnull', 'shadow', warns = [ 'all', 'extra', 'no-unused-parameter', 'nonnull', 'shadow', 'no-type-limits',
'implicit-fallthrough', 'no-unknown-warning-option', 'no-missing-braces' ] 'implicit-fallthrough', 'no-unknown-warning-option', 'no-missing-braces', 'conversion' ]
foreach w : warns foreach w : warns
if cc.has_argument('-W'+w) if cc.has_argument('-W'+w)
add_global_arguments('-W'+w, language: 'c') add_global_arguments('-W'+w, language: 'c')

View File

@ -39,8 +39,8 @@ region_t get_damage(session_t *ps, bool all_damage) {
pixman_region32_copy(&region, &ps->screen_reg); pixman_region32_copy(&region, &ps->screen_reg);
} else { } else {
for (int i = 0; i < buffer_age; i++) { for (int i = 0; i < buffer_age; i++) {
const int curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage; auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
log_trace("damage index: %d, damage ring offset: %d", i, curr); log_trace("damage index: %d, damage ring offset: %ld", i, curr);
dump_region(&ps->damage_ring[curr]); dump_region(&ps->damage_ring[curr]);
pixman_region32_union(&region, &region, &ps->damage_ring[curr]); pixman_region32_union(&region, &region, &ps->damage_ring[curr]);
} }

View File

@ -38,10 +38,10 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a
return XCB_NONE; return XCB_NONE;
} }
col.alpha = a * 0xffff; col.alpha = (uint16_t)(a * 0xffff);
col.red = r * 0xffff; col.red = (uint16_t)(r * 0xffff);
col.green = g * 0xffff; col.green = (uint16_t)(g * 0xffff);
col.blue = b * 0xffff; col.blue = (uint16_t)(b * 0xffff);
rect.x = 0; rect.x = 0;
rect.y = 0; rect.y = 0;
@ -74,21 +74,22 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
assert(shadow_sum); assert(shadow_sum);
// We only support square kernels for shadow // We only support square kernels for shadow
assert(kernel->w == kernel->h); assert(kernel->w == kernel->h);
int d = kernel->w, r = d / 2; int d = kernel->w;
int r = d / 2;
int swidth = width + r * 2, sheight = height + r * 2; int swidth = width + r * 2, sheight = height + r * 2;
assert(d % 2 == 1); assert(d % 2 == 1);
assert(d > 0); assert(d > 0);
ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8, ximage = xcb_image_create_native(c, to_u16_checked(swidth), to_u16_checked(sheight),
0, 0, NULL); XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
if (!ximage) { if (!ximage) {
log_error("failed to create an X image"); log_error("failed to create an X image");
return 0; return 0;
} }
unsigned char *data = ximage->data; unsigned char *data = ximage->data;
uint32_t sstride = ximage->stride; long sstride = ximage->stride;
// If the window body is smaller than the kernel, we do convolution directly // If the window body is smaller than the kernel, we do convolution directly
if (width < r * 2 && height < r * 2) { if (width < r * 2 && height < r * 2) {
@ -96,13 +97,14 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
for (int x = 0; x < swidth; x++) { for (int x = 0; x < swidth; x++) {
double sum = sum_kernel_normalized( double sum = sum_kernel_normalized(
kernel, d - x - 1, d - y - 1, width, height); kernel, d - x - 1, d - y - 1, width, height);
data[y * sstride + x] = sum * 255.0; data[y * sstride + x] = (uint8_t)(sum * 255.0);
} }
} }
return ximage; return ximage;
} }
if (height < r * 2) { if (height < r * 2) {
// Implies width >= r * 2
// If the window height is smaller than the kernel, we divide // If the window height is smaller than the kernel, we divide
// the window like this: // the window like this:
// -r r width-r width+r // -r r width-r width+r
@ -114,14 +116,15 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
double sum = sum_kernel_normalized(kernel, d - x - 1, double sum = sum_kernel_normalized(kernel, d - x - 1,
d - y - 1, d, height) * d - y - 1, d, height) *
255.0; 255.0;
data[y * sstride + x] = sum; data[y * sstride + x] = (uint8_t)sum;
data[y * sstride + swidth - x - 1] = sum; data[y * sstride + swidth - x - 1] = (uint8_t)sum;
} }
} }
for (int y = 0; y < sheight; y++) { for (int y = 0; y < sheight; y++) {
double sum = double sum =
sum_kernel_normalized(kernel, 0, d - y - 1, d, height) * 255.0; sum_kernel_normalized(kernel, 0, d - y - 1, d, height) * 255.0;
memset(&data[y * sstride + r * 2], sum, width - 2 * r); memset(&data[y * sstride + r * 2], (uint8_t)sum,
(size_t)(width - 2 * r));
} }
return ximage; return ximage;
} }
@ -132,49 +135,52 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
double sum = sum_kernel_normalized(kernel, d - x - 1, double sum = sum_kernel_normalized(kernel, d - x - 1,
d - y - 1, width, d) * d - y - 1, width, d) *
255.0; 255.0;
data[y * sstride + x] = sum; data[y * sstride + x] = (uint8_t)sum;
data[(sheight - y - 1) * sstride + x] = sum; data[(sheight - y - 1) * sstride + x] = (uint8_t)sum;
} }
} }
for (int x = 0; x < swidth; x++) { for (int x = 0; x < swidth; x++) {
double sum = double sum =
sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0; sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0;
for (int y = r * 2; y < height; y++) { for (int y = r * 2; y < height; y++) {
data[y * sstride + x] = sum; data[y * sstride + x] = (uint8_t)sum;
} }
} }
return ximage; return ximage;
} }
// Implies: width >= r * 2 && height >= r * 2
// Fill part 3 // Fill part 3
for (int y = r; y < height + r; y++) { for (int y = r; y < height + r; y++) {
memset(data + sstride * y + r, 255 * opacity, width); memset(data + sstride * y + r, (uint8_t)(255 * opacity), (size_t)width);
} }
// Part 1 // Part 1
for (int y = 0; y < r * 2; y++) { for (int y = 0; y < r * 2; y++) {
for (int x = 0; x < r * 2; x++) { for (int x = 0; x < r * 2; x++) {
double tmpsum = shadow_sum[y * d + x] * opacity * 255.0; double tmpsum = shadow_sum[y * d + x] * opacity * 255.0;
data[y * sstride + x] = tmpsum; data[y * sstride + x] = (uint8_t)tmpsum;
data[(sheight - y - 1) * sstride + x] = tmpsum; data[(sheight - y - 1) * sstride + x] = (uint8_t)tmpsum;
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = tmpsum; data[(sheight - y - 1) * sstride + (swidth - x - 1)] = (uint8_t)tmpsum;
data[y * sstride + (swidth - x - 1)] = tmpsum; data[y * sstride + (swidth - x - 1)] = (uint8_t)tmpsum;
} }
} }
// Part 2, top/bottom // Part 2, top/bottom
for (int y = 0; y < r * 2; y++) { for (int y = 0; y < r * 2; y++) {
double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0; double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0;
memset(&data[y * sstride + r * 2], tmpsum, width - r * 2); memset(&data[y * sstride + r * 2], (uint8_t)tmpsum, (size_t)(width - r * 2));
memset(&data[(sheight - y - 1) * sstride + r * 2], tmpsum, width - r * 2); memset(&data[(sheight - y - 1) * sstride + r * 2], (uint8_t)tmpsum,
(size_t)(width - r * 2));
} }
// Part 2, left/right // Part 2, left/right
for (int x = 0; x < r * 2; x++) { for (int x = 0; x < r * 2; x++) {
double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0; double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0;
for (int y = r * 2; y < height; y++) { for (int y = r * 2; y < height; y++) {
data[y * sstride + x] = tmpsum; data[y * sstride + x] = (uint8_t)tmpsum;
data[y * sstride + (swidth - x - 1)] = tmpsum; data[y * sstride + (swidth - x - 1)] = (uint8_t)tmpsum;
} }
} }
@ -256,8 +262,9 @@ shadow_picture_err:
return false; return false;
} }
void *default_backend_render_shadow(backend_t *backend_data, int width, int height, void *
const conv *kernel, double r, double g, double b, double a) { default_backend_render_shadow(backend_t *backend_data, int width, int height,
const conv *kernel, double r, double g, double b, double a) {
xcb_pixmap_t shadow_pixel = solid_picture(backend_data->c, backend_data->root, xcb_pixmap_t shadow_pixel = solid_picture(backend_data->c, backend_data->root,
true, 1, r, g, b), true, 1, r, g, b),
shadow = XCB_NONE; shadow = XCB_NONE;

View File

@ -12,16 +12,17 @@
typedef struct session session_t; typedef struct session session_t;
typedef struct win win; typedef struct win win;
typedef struct conv conv; typedef struct conv conv;
typedef struct backend_base backend_t;
bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, const int width, bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, int width,
const int height, const conv *kernel, xcb_render_picture_t shadow_pixel, int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict); xcb_pixmap_t *pixmap, xcb_render_picture_t *pict);
xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb, xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb,
double a, double r, double g, double b); double a, double r, double g, double b);
xcb_image_t * xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel, double opacity,
make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height); int width, int height);
/// The default implementation of `is_win_transparent`, it simply looks at win::mode. So /// The default implementation of `is_win_transparent`, it simply looks at win::mode. So
/// this is not suitable for backends that alter the content of windows /// this is not suitable for backends that alter the content of windows
@ -31,5 +32,6 @@ bool default_is_win_transparent(void *, win *, void *);
/// caveat as `default_is_win_transparent` applies. /// caveat as `default_is_win_transparent` applies.
bool default_is_frame_transparent(void *, win *, void *); bool default_is_frame_transparent(void *, win *, void *);
void *default_backend_render_shadow(backend_t *backend_data, int width, int height, void *
const conv *kernel, double r, double g, double b, double a); default_backend_render_shadow(backend_t *backend_data, int width, int height,
const conv *kernel, double r, double g, double b, double a);

View File

@ -119,14 +119,16 @@ GLuint gl_create_program_from_str(const char *vert_shader_str, const char *frag_
{ {
GLuint shaders[2]; GLuint shaders[2];
unsigned int count = 0; int count = 0;
if (vert_shader) if (vert_shader) {
shaders[count++] = vert_shader; shaders[count++] = vert_shader;
if (frag_shader) }
if (frag_shader) {
shaders[count++] = frag_shader; shaders[count++] = frag_shader;
assert(count <= sizeof(shaders) / sizeof(shaders[0])); }
if (count) if (count) {
prog = gl_create_program(shaders, count); prog = gl_create_program(shaders, count);
}
} }
if (vert_shader) if (vert_shader)
@ -185,7 +187,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
if (gd->win_shader.prog) { if (gd->win_shader.prog) {
glUseProgram(gd->win_shader.prog); glUseProgram(gd->win_shader.prog);
if (gd->win_shader.unifm_opacity >= 0) { if (gd->win_shader.unifm_opacity >= 0) {
glUniform1f(gd->win_shader.unifm_opacity, ptex->opacity); glUniform1f(gd->win_shader.unifm_opacity, (float)ptex->opacity);
} }
if (gd->win_shader.unifm_invert_color >= 0) { if (gd->win_shader.unifm_invert_color >= 0) {
glUniform1i(gd->win_shader.unifm_invert_color, ptex->color_inverted); glUniform1i(gd->win_shader.unifm_invert_color, ptex->color_inverted);
@ -194,7 +196,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
glUniform1i(gd->win_shader.unifm_tex, 0); glUniform1i(gd->win_shader.unifm_tex, 0);
} }
if (gd->win_shader.unifm_dim >= 0) { if (gd->win_shader.unifm_dim >= 0) {
glUniform1f(gd->win_shader.unifm_dim, ptex->dim); glUniform1f(gd->win_shader.unifm_dim, (float)ptex->dim);
} }
} }
@ -224,23 +226,23 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
// Calculate texture coordinates // Calculate texture coordinates
// (texture_x1, texture_y1), texture coord for the _bottom left_ corner // (texture_x1, texture_y1), texture coord for the _bottom left_ corner
GLfloat texture_x1 = crect.x1 - dst_x; auto texture_x1 = (GLfloat)(crect.x1 - dst_x);
GLfloat texture_y1 = crect.y2 - dst_y2; auto texture_y1 = (GLfloat)(crect.y2 - dst_y2);
GLfloat texture_x2 = texture_x1 + crect.x2 - crect.x1; auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1);
GLfloat texture_y2 = texture_y1 + crect.y1 - crect.y2; auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2);
// X pixmaps might be Y inverted, invert the texture coordinates // X pixmaps might be Y inverted, invert the texture coordinates
if (ptex->y_inverted) { if (ptex->y_inverted) {
texture_y1 = ptex->height - texture_y1; texture_y1 = (GLfloat)ptex->height - texture_y1;
texture_y2 = ptex->height - texture_y2; texture_y2 = (GLfloat)ptex->height - texture_y2;
} }
// GL_TEXTURE_2D coordinates are normalized // GL_TEXTURE_2D coordinates are normalized
// TODO use texelFetch // TODO use texelFetch
texture_x1 /= ptex->width; texture_x1 /= (GLfloat)ptex->width;
texture_y1 /= ptex->height; texture_y1 /= (GLfloat)ptex->height;
texture_x2 /= ptex->width; texture_x2 /= (GLfloat)ptex->width;
texture_y2 /= ptex->height; texture_y2 /= (GLfloat)ptex->height;
// Vertex coordinates // Vertex coordinates
GLint vx1 = crect.x1; GLint vx1 = crect.x1;
@ -333,11 +335,11 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
// last pass, draw directly into the back buffer // last pass, draw directly into the back buffer
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK); glDrawBuffer(GL_BACK);
glUniform1f(p->unifm_opacity, opacity); glUniform1f(p->unifm_opacity, (float)opacity);
} }
glUniform1f(p->unifm_offset_x, 1.0 / gd->width); glUniform1f(p->unifm_offset_x, 1.0f / (GLfloat)gd->width);
glUniform1f(p->unifm_offset_y, 1.0 / gd->height); glUniform1f(p->unifm_offset_y, 1.0f / (GLfloat)gd->height);
// XXX use multiple draw calls is probably going to be slow than // XXX use multiple draw calls is probably going to be slow than
// just simply blur the whole area. // just simply blur the whole area.
@ -354,29 +356,29 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
crect.y2 = gd->height - crect.y2; crect.y2 = gd->height - crect.y2;
// Texture coordinates // Texture coordinates
GLfloat texture_x1 = (crect.x1 - extent->x1); auto texture_x1 = (GLfloat)(crect.x1 - extent->x1);
GLfloat texture_y1 = (crect.y2 - dst_y); auto texture_y1 = (GLfloat)(crect.y2 - dst_y);
GLfloat texture_x2 = texture_x1 + (crect.x2 - crect.x1); auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1);
GLfloat texture_y2 = texture_y1 + (crect.y1 - crect.y2); auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2);
texture_x1 /= gd->width; texture_x1 /= (GLfloat)gd->width;
texture_x2 /= gd->width; texture_x2 /= (GLfloat)gd->width;
texture_y1 /= gd->height; texture_y1 /= (GLfloat)gd->height;
texture_y2 /= gd->height; texture_y2 /= (GLfloat)gd->height;
// Vertex coordinates // Vertex coordinates
// For passes before the last one, we are drawing into a buffer, // For passes before the last one, we are drawing into a buffer,
// so (dx, dy) from source maps to (0, 0) // so (dx, dy) from source maps to (0, 0)
GLfloat vx1 = crect.x1 - extent->x1; GLint vx1 = crect.x1 - extent->x1;
GLfloat vy1 = crect.y2 - dst_y; GLint vy1 = crect.y2 - dst_y;
if (i == gd->npasses - 1) { if (i == gd->npasses - 1) {
// For last pass, we are drawing back to source, so we // For last pass, we are drawing back to source, so we
// don't need to map // don't need to map
vx1 = crect.x1; vx1 = crect.x1;
vy1 = crect.y2; vy1 = crect.y2;
} }
GLfloat vx2 = vx1 + (crect.x2 - crect.x1); GLint vx2 = vx1 + (crect.x2 - crect.x1);
GLfloat vy2 = vy1 + (crect.y1 - crect.y2); GLint vy2 = vy1 + (crect.y1 - crect.y2);
GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1}; GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1};
GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2}; GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2};
@ -406,7 +408,7 @@ end:
return ret; return ret;
} }
static GLuint glGetUniformLocationChecked(GLuint p, const char *name) { static GLint glGetUniformLocationChecked(GLuint p, const char *name) {
auto ret = glGetUniformLocation(p, name); auto ret = glGetUniformLocation(p, name);
if (ret < 0) { if (ret < 0) {
log_error("Failed to get location of uniform '%s'. compton might not " log_error("Failed to get location of uniform '%s'. compton might not "
@ -470,13 +472,13 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi
int nrects; int nrects;
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects); const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
struct gl_data *gd = (void *)base; struct gl_data *gd = (void *)base;
glColor4f(r, g, b, a); glColor4d(r, g, b, a);
glBegin(GL_QUADS); glBegin(GL_QUADS);
for (int i = 0; i < nrects; i++) { for (int i = 0; i < nrects; i++) {
glVertex2f(rect[i].x1, gd->height - rect[i].y2); glVertex2i(rect[i].x1, gd->height - rect[i].y2);
glVertex2f(rect[i].x2, gd->height - rect[i].y2); glVertex2i(rect[i].x2, gd->height - rect[i].y2);
glVertex2f(rect[i].x2, gd->height - rect[i].y1); glVertex2i(rect[i].x2, gd->height - rect[i].y1);
glVertex2f(rect[i].x1, gd->height - rect[i].y1); glVertex2i(rect[i].x1, gd->height - rect[i].y1);
} }
glEnd(); glEnd();
} }
@ -524,7 +526,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
// Build shader // Build shader
int width = kern->w, height = kern->h; int width = kern->w, height = kern->h;
int nele = width * height - 1; int nele = width * height - 1;
size_t body_len = (strlen(shader_add) + 42) * nele; size_t body_len = (strlen(shader_add) + 42) * (uint)nele;
char *shader_body = ccalloc(body_len, char); char *shader_body = ccalloc(body_len, char);
char *pc = shader_body; char *pc = shader_body;
@ -541,7 +543,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
continue; continue;
} }
sum += val; sum += val;
pc += snprintf(pc, body_len - (pc - shader_body), pc += snprintf(pc, body_len - (ulong)(pc - shader_body),
FRAG_SHADER_BLUR_ADD, val, k - width / 2, FRAG_SHADER_BLUR_ADD, val, k - width / 2,
j - height / 2); j - height / 2);
assert(pc < shader_body + body_len); assert(pc < shader_body + body_len);
@ -553,9 +555,10 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
strlen(shader_body) + 10 /* sum */ + strlen(shader_body) + 10 /* sum */ +
1 /* null terminator */; 1 /* null terminator */;
char *shader_str = ccalloc(shader_len, char); char *shader_str = ccalloc(shader_len, char);
size_t real_shader_len = snprintf( auto real_shader_len = snprintf(
shader_str, shader_len, FRAG_SHADER_BLUR, extension, shader_body, sum); shader_str, shader_len, FRAG_SHADER_BLUR, extension, shader_body, sum);
assert(real_shader_len < shader_len); assert(real_shader_len >= 0);
assert((size_t)real_shader_len < shader_len);
free(shader_body); free(shader_body);
// Build program // Build program

View File

@ -162,7 +162,7 @@ static inline bool gl_has_extension(const char *ext) {
} }
for (int i = 0; i < nexts; i++) { for (int i = 0; i < nexts; i++) {
const char *exti = (const char *)glGetStringi(GL_EXTENSIONS, i); const char *exti = (const char *)glGetStringi(GL_EXTENSIONS, (GLuint)i);
if (strcmp(ext, exti) == 0) if (strcmp(ext, exti) == 0)
return true; return true;
} }

View File

@ -44,7 +44,7 @@ struct _glx_data {
struct gl_data gl; struct gl_data gl;
Display *display; Display *display;
int screen; int screen;
int target_win; xcb_window_t target_win;
int glx_event; int glx_event;
int glx_error; int glx_error;
GLXContext ctx; GLXContext ctx;
@ -70,7 +70,7 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_X_RENDERABLE, true, GLX_X_RENDERABLE, true,
GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, GLX_DONT_CARE, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, (GLint)GLX_DONT_CARE,
GLX_BUFFER_SIZE, m.red_size + m.green_size + GLX_BUFFER_SIZE, m.red_size + m.green_size +
m.blue_size + m.alpha_size, m.blue_size + m.alpha_size,
GLX_RED_SIZE, m.red_size, GLX_RED_SIZE, m.red_size,
@ -117,7 +117,8 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
int visual; int visual;
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual); glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual);
if (m.visual_depth != -1 && if (m.visual_depth != -1 &&
x_get_visual_depth(XGetXCBConnection(dpy), visual) != m.visual_depth) { x_get_visual_depth(XGetXCBConnection(dpy), (xcb_visualid_t)visual) !=
m.visual_depth) {
// Some driver might attach fbconfig to a GLX visual with a // Some driver might attach fbconfig to a GLX visual with a
// different depth. // different depth.
// //
@ -347,6 +348,11 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
return false; return false;
} }
if (fmt.visual_depth < 0) {
log_error("Pixmap %#010x with invalid depth %d", pixmap, fmt.visual_depth);
return false;
}
auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL); auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL);
if (!r) { if (!r) {
log_error("Invalid pixmap %#010x", pixmap); log_error("Invalid pixmap %#010x", pixmap);
@ -400,7 +406,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
// Create texture // Create texture
wd->texture.texture = gl_new_texture(GL_TEXTURE_2D); wd->texture.texture = gl_new_texture(GL_TEXTURE_2D);
wd->texture.opacity = 1; wd->texture.opacity = 1;
wd->texture.depth = fmt.visual_depth; wd->texture.depth = (unsigned int)fmt.visual_depth;
wd->texture.color_inverted = false; wd->texture.color_inverted = false;
wd->texture.dim = 0; wd->texture.dim = 0;
wd->texture.has_alpha = fmt.alpha_size != 0; wd->texture.has_alpha = fmt.alpha_size != 0;
@ -475,7 +481,7 @@ static inline bool glx_has_extension(Display *dpy, int screen, const char *ext)
return false; return false;
} }
long inlen = strlen(ext); auto inlen = strlen(ext);
const char *curr = glx_exts; const char *curr = glx_exts;
bool match = false; bool match = false;
while (curr && !match) { while (curr && !match) {
@ -483,9 +489,9 @@ static inline bool glx_has_extension(Display *dpy, int screen, const char *ext)
if (!end) { if (!end) {
// Last extension string // Last extension string
match = strcmp(ext, curr) == 0; match = strcmp(ext, curr) == 0;
} else if (end - curr == inlen) { } else if (curr + inlen == end) {
// Length match, do match string // Length match, do match string
match = strncmp(ext, curr, end - curr) == 0; match = strncmp(ext, curr, (unsigned long)(end - curr)) == 0;
} }
curr = end ? end + 1 : NULL; curr = end ? end + 1 : NULL;
} }

View File

@ -64,7 +64,7 @@ typedef struct _xrender_data {
/// Blur kernels converted to X format /// Blur kernels converted to X format
xcb_render_fixed_t *x_blur_kern[MAX_BLUR_PASS]; xcb_render_fixed_t *x_blur_kern[MAX_BLUR_PASS];
/// Number of elements in each blur kernel /// Number of elements in each blur kernel
size_t x_blur_kern_size[MAX_BLUR_PASS]; int x_blur_kern_size[MAX_BLUR_PASS];
xcb_special_event_t *present_event; xcb_special_event_t *present_event;
} xrender_data; } xrender_data;
@ -75,9 +75,9 @@ struct _xrender_image_data {
xcb_pixmap_t pixmap; xcb_pixmap_t pixmap;
// A Picture links to the Pixmap // A Picture links to the Pixmap
xcb_render_picture_t pict; xcb_render_picture_t pict;
long width, height; int width, height;
// The effective size of the image // The effective size of the image
long ewidth, eheight; int ewidth, eheight;
bool has_alpha; bool has_alpha;
double opacity; double opacity;
xcb_visualid_t visual; xcb_visualid_t visual;
@ -89,7 +89,7 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
const region_t *reg_paint, const region_t *reg_visible) { const region_t *reg_paint, const region_t *reg_visible) {
struct _xrender_data *xd = (void *)base; struct _xrender_data *xd = (void *)base;
struct _xrender_image_data *img = img_data; struct _xrender_image_data *img = img_data;
int op = (img->has_alpha ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC); uint8_t op = (img->has_alpha ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC);
auto alpha_pict = xd->alpha_pict[(int)(img->opacity * 255.0)]; auto alpha_pict = xd->alpha_pict[(int)(img->opacity * 255.0)];
region_t reg; region_t reg;
pixman_region32_init(&reg); pixman_region32_init(&reg);
@ -101,7 +101,8 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, &reg); x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, &reg);
xcb_render_composite(base->c, op, img->pict, alpha_pict, xd->back[xd->curr_back], xcb_render_composite(base->c, op, img->pict, alpha_pict, xd->back[xd->curr_back],
0, 0, 0, 0, dst_x, dst_y, img->ewidth, img->eheight); 0, 0, 0, 0, to_i16_checked(dst_x), to_i16_checked(dst_y),
to_u16_checked(img->ewidth), to_u16_checked(img->eheight));
pixman_region32_fini(&reg); pixman_region32_fini(&reg);
} }
@ -113,13 +114,15 @@ fill(backend_t *base, double r, double g, double b, double a, const region_t *cl
// color is in X fixed point representation // color is in X fixed point representation
xcb_render_fill_rectangles( xcb_render_fill_rectangles(
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back], base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
(xcb_render_color_t){ (xcb_render_color_t){.red = (uint16_t)(r * 0xffff),
.red = r * 0xffff, .green = g * 0xffff, .blue = b * 0xffff, .alpha = a * 0xffff}, .green = (uint16_t)(g * 0xffff),
.blue = (uint16_t)(b * 0xffff),
.alpha = (uint16_t)(a * 0xffff)},
1, 1,
(xcb_rectangle_t[]){{.x = extent->x1, (xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1),
.y = extent->y1, .y = to_i16_checked(extent->y1),
.width = extent->x2 - extent->x1, .width = to_u16_checked(extent->x2 - extent->x1),
.height = extent->y2 - extent->y1}}); .height = to_u16_checked(extent->y2 - extent->y1)}});
} }
static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur, static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur,
@ -135,9 +138,10 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
} }
const pixman_box32_t *extent = pixman_region32_extents(&reg_op); const pixman_box32_t *extent = pixman_region32_extents(&reg_op);
const int height = extent->y2 - extent->y1; const auto height = to_u16_checked(extent->y2 - extent->y1);
const int width = extent->x2 - extent->x1; const auto width = to_u16_checked(extent->x2 - extent->x1);
int src_x = extent->x1, src_y = extent->y1; auto src_x = to_i16_checked(extent->x1);
auto src_y = to_i16_checked(extent->y1);
static const char *filter0 = "Nearest"; // The "null" filter static const char *filter0 = "Nearest"; // The "null" filter
static const char *filter = "convolution"; static const char *filter = "convolution";
@ -183,8 +187,9 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
// be applied on source picture, to get the nearby pixels outside the // be applied on source picture, to get the nearby pixels outside the
// window. // window.
// TODO cache converted blur_kerns // TODO cache converted blur_kerns
xcb_render_set_picture_filter(c, src_pict, strlen(filter), filter, xcb_render_set_picture_filter(
xd->x_blur_kern_size[i], xd->x_blur_kern[i]); c, src_pict, to_u16_checked(strlen(filter)), filter,
to_u32_checked(xd->x_blur_kern_size[i]), xd->x_blur_kern[i]);
if (xd->x_blur_kern[i + 1] || i == 0) { if (xd->x_blur_kern[i + 1] || i == 0) {
// This is not the last pass, or this is the first pass // This is not the last pass, or this is the first pass
@ -199,7 +204,8 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
} }
// reset filter // reset filter
xcb_render_set_picture_filter(c, src_pict, strlen(filter0), filter0, 0, NULL); xcb_render_set_picture_filter(
c, src_pict, to_u16_checked(strlen(filter0)), filter0, 0, NULL);
src_pict = tmp_picture[current]; src_pict = tmp_picture[current];
dst_pict = tmp_picture[!current]; dst_pict = tmp_picture[!current];
@ -211,8 +217,9 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
// There is only 1 pass // There is only 1 pass
if (i == 1) { if (i == 1) {
xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict, xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict,
xd->back[xd->curr_back], 0, 0, 0, 0, extent->x1, xd->back[xd->curr_back], 0, 0, 0, 0,
extent->y1, width, height); to_i16_checked(extent->x1),
to_i16_checked(extent->y1), width, height);
} }
xcb_render_free_picture(c, tmp_picture[0]); xcb_render_free_picture(c, tmp_picture[0]);
@ -232,7 +239,7 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool
} }
auto img = ccalloc(1, struct _xrender_image_data); auto img = ccalloc(1, struct _xrender_image_data);
img->depth = fmt.visual_depth; img->depth = (uint8_t)fmt.visual_depth;
img->width = img->ewidth = r->width; img->width = img->ewidth = r->width;
img->height = img->eheight = r->height; img->height = img->eheight = r->height;
img->pixmap = pixmap; img->pixmap = pixmap;
@ -328,7 +335,8 @@ static void present(backend_t *base) {
// but that will require a different backend API // but that will require a different backend API
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC,
xd->back[xd->curr_back], XCB_NONE, xd->target, 0, 0, xd->back[xd->curr_back], XCB_NONE, xd->target, 0, 0,
0, 0, 0, 0, xd->target_width, xd->target_height); 0, 0, 0, 0, to_u16_checked(xd->target_width),
to_u16_checked(xd->target_height));
xd->buffer_age[xd->curr_back] = 1; xd->buffer_age[xd->curr_back] = 1;
} }
} }
@ -358,6 +366,8 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
pixman_region32_init(&reg); pixman_region32_init(&reg);
const auto tmpw = to_u16_checked(img->width);
const auto tmph = to_u16_checked(img->height);
switch (op) { switch (op) {
case IMAGE_OP_INVERT_COLOR_ALL: case IMAGE_OP_INVERT_COLOR_ALL:
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible); x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
@ -366,36 +376,35 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
x_create_picture_with_visual(base->c, base->root, img->width, x_create_picture_with_visual(base->c, base->root, img->width,
img->height, img->visual, 0, NULL); img->height, img->visual, 0, NULL);
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict,
XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
img->width, img->height);
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE,
xd->white_pixel, XCB_NONE, tmp_pict, 0, 0, 0, xd->white_pixel, XCB_NONE, tmp_pict, 0, 0, 0,
0, 0, 0, img->width, img->height); 0, 0, 0, tmpw, tmph);
// We use an extra PictOpInReverse operation to get correct pixel // We use an extra PictOpInReverse operation to get correct pixel
// alpha. There could be a better solution. // alpha. There could be a better solution.
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN_REVERSE, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN_REVERSE,
tmp_pict, XCB_NONE, img->pict, 0, 0, 0, 0, 0, tmp_pict, XCB_NONE, img->pict, 0, 0, 0, 0, 0,
0, img->width, img->height); 0, tmpw, tmph);
xcb_render_free_picture(base->c, tmp_pict); xcb_render_free_picture(base->c, tmp_pict);
} else { } else {
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE,
xd->white_pixel, XCB_NONE, img->pict, 0, 0, xd->white_pixel, XCB_NONE, img->pict, 0, 0,
0, 0, 0, 0, img->width, img->height); 0, 0, 0, 0, tmpw, tmph);
} }
break; break;
case IMAGE_OP_DIM_ALL: case IMAGE_OP_DIM_ALL:
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible); x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
xcb_render_color_t color = { xcb_render_color_t color = {
.red = 0, .green = 0, .blue = 0, .alpha = 0xffff * dargs[0]}; .red = 0, .green = 0, .blue = 0, .alpha = (uint16_t)(0xffff * dargs[0])};
// Dim the actually content of window // Dim the actually content of window
xcb_rectangle_t rect = { xcb_rectangle_t rect = {
.x = 0, .x = 0,
.y = 0, .y = 0,
.width = img->width, .width = tmpw,
.height = img->height, .height = tmph,
}; };
xcb_render_fill_rectangles(base->c, XCB_RENDER_PICT_OP_OVER, img->pict, xcb_render_fill_rectangles(base->c, XCB_RENDER_PICT_OP_OVER, img->pict,
@ -415,7 +424,7 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
auto alpha_pict = xd->alpha_pict[(int)(dargs[0] * 255)]; auto alpha_pict = xd->alpha_pict[(int)(dargs[0] * 255)];
x_set_picture_clip_region(base->c, img->pict, 0, 0, &reg); x_set_picture_clip_region(base->c, img->pict, 0, 0, &reg);
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN, img->pict, XCB_NONE, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN, img->pict, XCB_NONE,
alpha_pict, 0, 0, 0, 0, 0, 0, img->width, img->height); alpha_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
img->has_alpha = true; img->has_alpha = true;
break; break;
case IMAGE_OP_RESIZE_TILE: case IMAGE_OP_RESIZE_TILE:
@ -454,10 +463,11 @@ static void *copy(backend_t *base, const void *image, const region_t *reg) {
return NULL; return NULL;
} }
auto alpha_pict = xcb_render_picture_t alpha_pict =
img->opacity == 1 ? XCB_NONE : xd->alpha_pict[(int)(img->opacity * 255)]; img->opacity == 1 ? XCB_NONE : xd->alpha_pict[(int)(img->opacity * 255)];
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict, alpha_pict, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict, alpha_pict,
new_img->pict, 0, 0, 0, 0, 0, 0, img->width, img->height); new_img->pict, 0, 0, 0, 0, 0, 0, to_u16_checked(img->width),
to_u16_checked(img->height));
return new_img; return new_img;
} }
@ -526,7 +536,8 @@ backend_t *backend_xrender_init(session_t *ps) {
int pixmap_needed = xd->vsync ? 2 : 1; int pixmap_needed = xd->vsync ? 2 : 1;
for (int i = 0; i < pixmap_needed; i++) { for (int i = 0; i < pixmap_needed; i++) {
xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root, xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root,
ps->root_width, ps->root_height); to_u16_checked(ps->root_width),
to_u16_checked(ps->root_height));
xd->back[i] = x_create_picture_with_pictfmt_and_pixmap( xd->back[i] = x_create_picture_with_pictfmt_and_pixmap(
ps->c, pictfmt, xd->back_pixmap[i], 0, NULL); ps->c, pictfmt, xd->back_pixmap[i], 0, NULL);
xd->buffer_age[i] = -1; xd->buffer_age[i] = -1;

220
src/c2.c
View File

@ -106,8 +106,8 @@ struct _c2_l {
xcb_atom_t tgtatom; xcb_atom_t tgtatom;
bool tgt_onframe; bool tgt_onframe;
int index; int index;
enum { C2_L_PUNDEFINED, enum { C2_L_PUNDEFINED = -1,
C2_L_PID, C2_L_PID = 0,
C2_L_PX, C2_L_PX,
C2_L_PY, C2_L_PY,
C2_L_PX2, C2_L_PX2,
@ -554,17 +554,19 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
} }
// Copy target name out // Copy target name out
unsigned tgtlen = 0; int tgtlen = 0;
for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]); for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]);
++offset) { ++offset) {
++tgtlen; ++tgtlen;
} }
if (!tgtlen) if (!tgtlen) {
c2_error("Empty target."); c2_error("Empty target.");
pleaf->tgt = strndup(&pattern[offset - tgtlen], tgtlen); }
pleaf->tgt = strndup(&pattern[offset - tgtlen], (size_t)tgtlen);
// Check for predefined targets // Check for predefined targets
for (unsigned i = 1; i < sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]); ++i) { static const int npredefs = (int)(sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]));
for (int i = 0; i < npredefs; ++i) {
if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) { if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) {
pleaf->predef = i; pleaf->predef = i;
pleaf->type = C2_PREDEFS[i].type; pleaf->type = C2_PREDEFS[i].type;
@ -573,25 +575,6 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
} }
} }
// Alias for predefined targets
if (!pleaf->predef) {
#define TGTFILL(pdefid) \
(pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \
pleaf->format = C2_PREDEFS[pdefid].format)
// if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt))
// TGTFILL(C2_L_PNAME);
#undef TGTFILL
// Alias for custom properties
#define TGTFILL(target, type, format) \
(pleaf->target = strdup(target), pleaf->type = type, pleaf->format = format)
// if (!strcmp("SOME_ALIAS"))
// TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32);
#undef TGTFILL
}
C2H_SKIP_SPACES(); C2H_SKIP_SPACES();
// Parse target-on-frame flag // Parse target-on-frame flag
@ -607,27 +590,29 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
C2H_SKIP_SPACES(); C2H_SKIP_SPACES();
int index = -1; long index = -1;
char *endptr = NULL; char *endptr = NULL;
index = strtol(pattern + offset, &endptr, 0); index = strtol(pattern + offset, &endptr, 0);
if (!endptr || pattern + offset == endptr) if (!endptr || pattern + offset == endptr) {
c2_error("No index number found after bracket."); c2_error("No index number found after bracket.");
}
if (index < 0) if (index < 0) {
c2_error("Index number invalid."); c2_error("Index number invalid.");
}
if (pleaf->predef) if (pleaf->predef != C2_L_PUNDEFINED) {
c2_error("Predefined targets can't have index."); c2_error("Predefined targets can't have index.");
}
pleaf->index = index; pleaf->index = to_int_checked(index);
offset = endptr - pattern; offset = to_int_checked(endptr - pattern);
C2H_SKIP_SPACES(); C2H_SKIP_SPACES();
if (']' != pattern[offset]) if (pattern[offset] != ']') {
c2_error("Index end marker not found."); c2_error("Index end marker not found.");
}
++offset; ++offset;
@ -641,44 +626,43 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
// Look for format // Look for format
bool hasformat = false; bool hasformat = false;
int format = 0; long format = 0;
{ {
char *endptr = NULL; char *endptr = NULL;
format = strtol(pattern + offset, &endptr, 0); format = strtol(pattern + offset, &endptr, 0);
assert(endptr); assert(endptr);
if ((hasformat = (endptr && endptr != pattern + offset))) if ((hasformat = (endptr && endptr != pattern + offset))) {
offset = endptr - pattern; offset = to_int_checked(endptr - pattern);
}
C2H_SKIP_SPACES(); C2H_SKIP_SPACES();
} }
// Look for type // Look for type
enum c2_l_type type = C2_L_TUNDEFINED; enum c2_l_type type = C2_L_TUNDEFINED;
{ switch (pattern[offset]) {
switch (pattern[offset]) { case 'w': type = C2_L_TWINDOW; break;
case 'w': type = C2_L_TWINDOW; break; case 'd': type = C2_L_TDRAWABLE; break;
case 'd': type = C2_L_TDRAWABLE; break; case 'c': type = C2_L_TCARDINAL; break;
case 'c': type = C2_L_TCARDINAL; break; case 's': type = C2_L_TSTRING; break;
case 's': type = C2_L_TSTRING; break; case 'a': type = C2_L_TATOM; break;
case 'a': type = C2_L_TATOM; break; default: c2_error("Invalid type character.");
default: c2_error("Invalid type character.");
}
if (type) {
if (pleaf->predef) {
log_warn("Type specified for a default target "
"will be ignored.");
} else {
if (pleaf->type && type != pleaf->type)
log_warn("Default type overridden on "
"target.");
pleaf->type = type;
}
}
offset++;
C2H_SKIP_SPACES();
} }
if (type) {
if (pleaf->predef != C2_L_PUNDEFINED) {
log_warn("Type specified for a default target "
"will be ignored.");
} else {
if (pleaf->type && type != pleaf->type)
log_warn("Default type overridden on "
"target.");
pleaf->type = type;
}
}
offset++;
C2H_SKIP_SPACES();
// Default format // Default format
if (!pleaf->format) { if (!pleaf->format) {
switch (pleaf->type) { switch (pleaf->type) {
@ -692,20 +676,20 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
// Write format // Write format
if (hasformat) { if (hasformat) {
if (pleaf->predef) if (pleaf->predef != C2_L_PUNDEFINED) {
log_warn("Format \"%d\" specified on a default target " log_warn("Format \"%ld\" specified on a default target "
"will be ignored.", "will be ignored.",
format); format);
else if (C2_L_TSTRING == pleaf->type) } else if (pleaf->type == C2_L_TSTRING) {
log_warn("Format \"%d\" specified on a string target " log_warn("Format \"%ld\" specified on a string target "
"will be ignored.", "will be ignored.",
format); format);
else { } else {
if (pleaf->format && pleaf->format != format) if (pleaf->format && pleaf->format != format)
log_warn("Default format %d overridden on " log_warn("Default format %d overridden on "
"target.", "target.",
pleaf->format); pleaf->format);
pleaf->format = format; pleaf->format = to_int_checked(format);
} }
} }
} }
@ -798,52 +782,51 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
c2_l_t *const pleaf = presult->l; c2_l_t *const pleaf = presult->l;
// Exists operator cannot have pattern // Exists operator cannot have pattern
if (!pleaf->op) if (!pleaf->op) {
return offset; return offset;
}
C2H_SKIP_SPACES(); C2H_SKIP_SPACES();
char *endptr = NULL; char *endptr = NULL;
// Check for boolean patterns
if (!strcmp_wd("true", &pattern[offset])) { if (!strcmp_wd("true", &pattern[offset])) {
pleaf->ptntype = C2_L_PTINT; pleaf->ptntype = C2_L_PTINT;
pleaf->ptnint = true; pleaf->ptnint = true;
offset += strlen("true"); offset += 4; // length of "true";
} else if (!strcmp_wd("false", &pattern[offset])) { } else if (!strcmp_wd("false", &pattern[offset])) {
pleaf->ptntype = C2_L_PTINT; pleaf->ptntype = C2_L_PTINT;
pleaf->ptnint = false; pleaf->ptnint = false;
offset += strlen("false"); offset += 5; // length of "false";
} } else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0),
// Check for integer patterns pattern + offset != endptr) {
else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0),
pattern + offset != endptr) {
pleaf->ptntype = C2_L_PTINT; pleaf->ptntype = C2_L_PTINT;
offset = endptr - pattern; offset = to_int_checked(endptr - pattern);
// Make sure we are stopping at the end of a word // Make sure we are stopping at the end of a word
if (isalnum(pattern[offset])) if (isalnum(pattern[offset])) {
c2_error("Trailing characters after a numeric pattern."); c2_error("Trailing characters after a numeric pattern.");
} }
// Check for string patterns } else {
else { // Parse string patterns
bool raw = false; bool raw = false;
char delim = '\0'; char delim = '\0';
// String flags // String flags
if ('r' == tolower(pattern[offset])) { if (tolower(pattern[offset]) == 'r') {
raw = true; raw = true;
++offset; ++offset;
C2H_SKIP_SPACES(); C2H_SKIP_SPACES();
} }
// Check for delimiters // Check for delimiters
if ('\"' == pattern[offset] || '\'' == pattern[offset]) { if (pattern[offset] == '\"' || pattern[offset] == '\'') {
pleaf->ptntype = C2_L_PTSTRING; pleaf->ptntype = C2_L_PTSTRING;
delim = pattern[offset]; delim = pattern[offset];
++offset; ++offset;
} }
if (C2_L_PTSTRING != pleaf->ptntype) if (pleaf->ptntype != C2_L_PTSTRING) {
c2_error("Invalid pattern type."); c2_error("Invalid pattern type.");
}
// Parse the string now // Parse the string now
// We can't determine the length of the pattern, so we use the length // We can't determine the length of the pattern, so we use the length
@ -876,8 +859,7 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
if (pstr != &tstr[2] || val <= 0) if (pstr != &tstr[2] || val <= 0)
c2_error("Invalid octal/hex escape " c2_error("Invalid octal/hex escape "
"sequence."); "sequence.");
assert(val < 256 && val >= 0); *(ptptnstr++) = to_char_checked(val);
*(ptptnstr++) = val;
offset += 2; offset += 2;
break; break;
} }
@ -929,10 +911,10 @@ fail:
* Parse a condition with legacy syntax. * Parse a condition with legacy syntax.
*/ */
static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) { static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
unsigned plen = strlen(pattern + offset); if (strlen(pattern + offset) < 4 || pattern[offset + 1] != ':' ||
!strchr(pattern + offset + 2, ':')) {
if (plen < 4 || ':' != pattern[offset + 1] || !strchr(pattern + offset + 2, ':'))
c2_error("Legacy parser: Invalid format."); c2_error("Legacy parser: Invalid format.");
}
// Allocate memory for new leaf // Allocate memory for new leaf
auto pleaf = cmalloc(c2_l_t); auto pleaf = cmalloc(c2_l_t);
@ -1000,7 +982,7 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
} }
// Get target atom if it's not a predefined one // Get target atom if it's not a predefined one
if (!pleaf->predef) { if (pleaf->predef == C2_L_PUNDEFINED) {
pleaf->tgtatom = get_atom(ps, pleaf->tgt); pleaf->tgtatom = get_atom(ps, pleaf->tgt);
if (!pleaf->tgtatom) { if (!pleaf->tgtatom) {
log_error("Failed to get atom for target \"%s\".", pleaf->tgt); log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
@ -1027,20 +1009,18 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
// Enable specific tracking options in compton if needed by the condition // Enable specific tracking options in compton if needed by the condition
// TODO: Add track_leader // TODO: Add track_leader
if (pleaf->predef) { switch (pleaf->predef) {
switch (pleaf->predef) { case C2_L_PFOCUSED: ps->o.track_focus = true; break;
case C2_L_PFOCUSED: ps->o.track_focus = true; break; // case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break;
// case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break; case C2_L_PNAME:
case C2_L_PNAME: case C2_L_PCLASSG:
case C2_L_PCLASSG: case C2_L_PCLASSI:
case C2_L_PCLASSI: case C2_L_PROLE: ps->o.track_wdata = true; break;
case C2_L_PROLE: ps->o.track_wdata = true; break; default: break;
default: break;
}
} }
// Warn about lower case characters in target name // Warn about lower case characters in target name
if (!pleaf->predef) { if (pleaf->predef == C2_L_PUNDEFINED) {
for (const char *pc = pleaf->tgt; *pc; ++pc) { for (const char *pc = pleaf->tgt; *pc; ++pc) {
if (islower(*pc)) { if (islower(*pc)) {
log_warn("Lowercase character in target name \"%s\".", log_warn("Lowercase character in target name \"%s\".",
@ -1160,10 +1140,11 @@ c2_lptr_t *c2_free_lptr(c2_lptr_t *lp) {
* Get a string representation of a rule target. * Get a string representation of a rule target.
*/ */
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) { static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) {
if (pleaf->predef) if (pleaf->predef != C2_L_PUNDEFINED) {
return C2_PREDEFS[pleaf->predef].name; return C2_PREDEFS[pleaf->predef].name;
else } else {
return pleaf->tgt; return pleaf->tgt;
}
} }
/** /**
@ -1298,8 +1279,9 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id); const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
// Return if wid is missing // Return if wid is missing
if (!pleaf->predef && !wid) if (pleaf->predef == C2_L_PUNDEFINED && !wid) {
return; return;
}
const int idx = (pleaf->index < 0 ? 0 : pleaf->index); const int idx = (pleaf->index < 0 ? 0 : pleaf->index);
@ -1310,7 +1292,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
// Get the value // Get the value
// A predefined target // A predefined target
if (pleaf->predef) { if (pleaf->predef != C2_L_PUNDEFINED) {
*perr = false; *perr = false;
switch (pleaf->predef) { switch (pleaf->predef) {
case C2_L_PID: tgt = wid; break; case C2_L_PID: tgt = wid; break;
@ -1355,7 +1337,9 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
// Do comparison // Do comparison
switch (pleaf->op) { switch (pleaf->op) {
case C2_L_OEXISTS: *pres = (pleaf->predef ? tgt : true); break; case C2_L_OEXISTS:
*pres = (pleaf->predef != C2_L_PUNDEFINED ? tgt : true);
break;
case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break; case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break;
case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break; case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break;
case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break; case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break;
@ -1373,7 +1357,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
char *tgt_free = NULL; char *tgt_free = NULL;
// A predefined target // A predefined target
if (pleaf->predef) { if (pleaf->predef != C2_L_PUNDEFINED) {
switch (pleaf->predef) { switch (pleaf->predef) {
case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break; case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break;
case C2_L_PNAME: tgt = w->name; break; case C2_L_PNAME: tgt = w->name; break;
@ -1382,20 +1366,19 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
case C2_L_PROLE: tgt = w->role; break; case C2_L_PROLE: tgt = w->role; break;
default: assert(0); break; default: assert(0); break;
} }
} } else if (pleaf->type == C2_L_TATOM) {
// If it's an atom type property, convert atom to string // An atom type property, convert it to string
else if (C2_L_TATOM == pleaf->type) {
winprop_t prop = winprop_t prop =
wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L, wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L,
c2_get_atom_type(pleaf), pleaf->format); c2_get_atom_type(pleaf), pleaf->format);
xcb_atom_t atom = winprop_get_int(prop); xcb_atom_t atom = (xcb_atom_t)winprop_get_int(prop);
if (atom) { if (atom) {
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply( xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
ps->c, xcb_get_atom_name(ps->c, atom), NULL); ps->c, xcb_get_atom_name(ps->c, atom), NULL);
if (reply) { if (reply) {
tgt_free = tgt_free = strndup(
strndup(xcb_get_atom_name_name(reply), xcb_get_atom_name_name(reply),
xcb_get_atom_name_name_length(reply)); (size_t)xcb_get_atom_name_name_length(reply));
free(reply); free(reply);
} }
} }
@ -1403,9 +1386,8 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
tgt = tgt_free; tgt = tgt_free;
} }
free_winprop(&prop); free_winprop(&prop);
} } else {
// Otherwise, just fetch the string list // Not an atom type, just fetch the string list
else {
char **strlst = NULL; char **strlst = NULL;
int nstr; int nstr;
if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) && if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) &&
@ -1456,8 +1438,10 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
} break; } break;
case C2_L_MPCRE: case C2_L_MPCRE:
#ifdef CONFIG_REGEX_PCRE #ifdef CONFIG_REGEX_PCRE
*pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra, assert(strlen(tgt) <= INT_MAX);
tgt, strlen(tgt), 0, 0, NULL, 0) >= 0); *pres =
(pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra,
tgt, (int)strlen(tgt), 0, 0, NULL, 0) >= 0);
#else #else
assert(0); assert(0);
#endif #endif

View File

@ -186,8 +186,8 @@ struct _glx_texture {
GLXPixmap glpixmap; GLXPixmap glpixmap;
xcb_pixmap_t pixmap; xcb_pixmap_t pixmap;
GLenum target; GLenum target;
unsigned width; int width;
unsigned height; int height;
bool y_inverted; bool y_inverted;
}; };
@ -366,7 +366,7 @@ typedef struct session {
/// Pre-generated alpha pictures. /// Pre-generated alpha pictures.
xcb_render_picture_t *alpha_picts; xcb_render_picture_t *alpha_picts;
/// Time of last fading. In milliseconds. /// Time of last fading. In milliseconds.
unsigned long fade_time; long fade_time;
/// Head pointer of the error ignore linked list. /// Head pointer of the error ignore linked list.
ignore_t *ignore_head; ignore_t *ignore_head;
/// Pointer to the <code>next</code> member of tail element of the error /// Pointer to the <code>next</code> member of tail element of the error
@ -416,7 +416,7 @@ typedef struct session {
// === Software-optimization-related === // === Software-optimization-related ===
/// Currently used refresh rate. /// Currently used refresh rate.
short refresh_rate; int refresh_rate;
/// Interval between refresh in nanoseconds. /// Interval between refresh in nanoseconds.
long refresh_intv; long refresh_intv;
/// Nanosecond offset of the first painting. /// Nanosecond offset of the first painting.
@ -566,20 +566,20 @@ static inline int timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
// We use those if statement instead of a - expression because of possible // We use those if statement instead of a - expression because of possible
// truncation problem from long to int. // truncation problem from long to int.
{ auto sec = (long)(ms / MS_PER_SEC);
long sec = ms / MS_PER_SEC; if (ptv->tv_sec > sec) {
if (ptv->tv_sec > sec) return 1;
return 1; }
if (ptv->tv_sec < sec) if (ptv->tv_sec < sec) {
return -1; return -1;
} }
{ auto usec = (long)(ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC));
long usec = ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC); if (ptv->tv_usec > usec) {
if (ptv->tv_usec > usec) return 1;
return 1; }
if (ptv->tv_usec < usec) if (ptv->tv_usec < usec) {
return -1; return -1;
} }
return 0; return 0;
@ -712,7 +712,8 @@ _Noreturn static inline void die(const char *msg) {
*/ */
static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) { static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) {
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply( xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(
ps->c, xcb_intern_atom(ps->c, 0, strlen(atom_name), atom_name), NULL); ps->c,
xcb_intern_atom(ps->c, 0, to_u16_checked(strlen(atom_name)), atom_name), NULL);
xcb_atom_t atom = XCB_NONE; xcb_atom_t atom = XCB_NONE;
if (reply) { if (reply) {

View File

@ -95,3 +95,6 @@
#else #else
# define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__ # define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__
#endif #endif
typedef unsigned long ulong;
typedef unsigned int uint;

View File

@ -108,10 +108,10 @@ static inline void free_xinerama_info(session_t *ps) {
/** /**
* Get current system clock in milliseconds. * Get current system clock in milliseconds.
*/ */
static inline uint64_t get_time_ms(void) { static inline int64_t get_time_ms(void) {
struct timespec tp; struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp); clock_gettime(CLOCK_MONOTONIC, &tp);
return tp.tv_sec * ((uint64_t)1000ul) + tp.tv_nsec / 1000000; return (int64_t)tp.tv_sec * 1000 + (int64_t)tp.tv_nsec / 1000000;
} }
// XXX Move to x.c // XXX Move to x.c
@ -202,11 +202,11 @@ static double fade_timeout(session_t *ps) {
if (ps->o.fade_delta + ps->fade_time < now) if (ps->o.fade_delta + ps->fade_time < now)
return 0; return 0;
int diff = ps->o.fade_delta + ps->fade_time - now; auto diff = ps->o.fade_delta + ps->fade_time - now;
diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2); diff = clamp(diff, 0, ps->o.fade_delta * 2);
return diff / 1000.0; return (double)diff / 1000.0;
} }
/** /**
@ -215,7 +215,7 @@ static double fade_timeout(session_t *ps) {
* @param steps steps of fading * @param steps steps of fading
* @return whether we are still in fading mode * @return whether we are still in fading mode
*/ */
static bool run_fade(session_t *ps, win **_w, unsigned steps) { static bool run_fade(session_t *ps, win **_w, long steps) {
win *w = *_w; win *w = *_w;
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
// We are not fading // We are not fading
@ -237,11 +237,11 @@ static bool run_fade(session_t *ps, win **_w, unsigned steps) {
if (steps) { if (steps) {
if (w->opacity < w->opacity_tgt) { if (w->opacity < w->opacity_tgt) {
w->opacity = normalize_d_range( w->opacity = clamp(w->opacity + ps->o.fade_in_step * (double)steps,
w->opacity + ps->o.fade_in_step * steps, 0.0, w->opacity_tgt); 0.0, w->opacity_tgt);
} else { } else {
w->opacity = normalize_d_range( w->opacity = clamp(w->opacity - ps->o.fade_out_step * (double)steps,
w->opacity - ps->o.fade_out_step * steps, w->opacity_tgt, 1); w->opacity_tgt, 1);
} }
} }
@ -277,8 +277,8 @@ static int should_ignore(session_t *ps, unsigned long sequence) {
/** /**
* Determine the event mask for a window. * Determine the event mask for a window.
*/ */
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
long evmask = 0; uint32_t evmask = 0;
win *w = NULL; win *w = NULL;
// Check if it's a mapped frame window // Check if it's a mapped frame window
@ -292,7 +292,7 @@ long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
// Check if it's a mapped client window // Check if it's a mapped client window
if (WIN_EVMODE_CLIENT == mode || if (WIN_EVMODE_CLIENT == mode ||
((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) { ((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst || if (ps->o.frame_opacity > 0 || ps->o.track_wdata || ps->track_atom_lst ||
ps->o.detect_client_opacity) ps->o.detect_client_opacity)
evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
} }
@ -412,7 +412,7 @@ static void handle_root_flags(session_t *ps) {
"temporarily disabled"); "temporarily disabled");
} }
} }
ps->root_flags &= ~ROOT_FLAGS_SCREEN_CHANGE; ps->root_flags &= ~(uint64_t)ROOT_FLAGS_SCREEN_CHANGE;
} }
} }
@ -423,7 +423,7 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
*fade_running = false; *fade_running = false;
// Fading step calculation // Fading step calculation
unsigned long steps = 0L; long steps = 0L;
auto now = get_time_ms(); auto now = get_time_ms();
if (ps->fade_time) { if (ps->fade_time) {
assert(now >= ps->fade_time); assert(now >= ps->fade_time);
@ -616,8 +616,9 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit) if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit)
redir_stop(ps); redir_stop(ps);
else if (!ev_is_active(&ps->unredir_timer)) { else if (!ev_is_active(&ps->unredir_timer)) {
ev_timer_set(&ps->unredir_timer, ev_timer_set(
ps->o.unredir_if_possible_delay / 1000.0, 0); &ps->unredir_timer,
(double)ps->o.unredir_if_possible_delay / 1000.0, 0);
ev_timer_start(ps->loop, &ps->unredir_timer); ev_timer_start(ps->loop, &ps->unredir_timer);
} }
} }
@ -1066,11 +1067,14 @@ void update_ewmh_active_win(session_t *ps) {
static bool register_cm(session_t *ps) { static bool register_cm(session_t *ps) {
assert(!ps->reg_win); assert(!ps->reg_win);
ps->reg_win = ps->reg_win = xcb_generate_id(ps->c);
XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, XCB_NONE, XCB_NONE); auto e = xcb_request_check(
ps->c, xcb_create_window_checked(ps->c, XCB_COPY_FROM_PARENT, ps->reg_win, ps->root,
0, 0, 1, 1, 0, XCB_NONE, ps->vis, 0, NULL));
if (!ps->reg_win) { if (e) {
log_fatal("Failed to create window."); log_fatal("Failed to create window.");
free(e);
return false; return false;
} }
@ -1092,7 +1096,7 @@ static bool register_cm(session_t *ps) {
// Set _NET_WM_PID // Set _NET_WM_PID
{ {
uint32_t pid = getpid(); auto pid = getpid();
xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1,
&pid); &pid);
@ -1108,7 +1112,7 @@ static bool register_cm(session_t *ps) {
if (!ps->o.no_x_selection) { if (!ps->o.no_x_selection) {
unsigned len = strlen(REGISTER_PROP) + 2; unsigned len = strlen(REGISTER_PROP) + 2;
int s = ps->scr; int s = ps->scr;
Atom atom; xcb_atom_t atom;
while (s >= 10) { while (s >= 10) {
++len; ++len;
@ -1260,7 +1264,7 @@ static double swopti_handle_timeout(session_t *ps) {
return 0; return 0;
// Add an offset so we wait until the next refresh after timeout // Add an offset so we wait until the next refresh after timeout
return (ps->refresh_intv - offset) / 1e6; return (double)(ps->refresh_intv - offset) / 1e6;
} }
/** /**
@ -1768,10 +1772,13 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
XSetErrorHandler(xerror); XSetErrorHandler(xerror);
ps->scr = DefaultScreen(ps->dpy); ps->scr = DefaultScreen(ps->dpy);
ps->root = RootWindow(ps->dpy, ps->scr);
ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr)); auto screen = x_screen_of_display(ps->c, ps->scr);
ps->depth = DefaultDepth(ps->dpy, ps->scr); ps->vis = screen->root_visual;
ps->depth = screen->root_depth;
ps->root = screen->root;
ps->root_width = screen->width_in_pixels;
ps->root_height = screen->height_in_pixels;
// Start listening to events on root earlier to catch all possible // Start listening to events on root earlier to catch all possible
// root geometry changes // root geometry changes
@ -1786,9 +1793,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
free(e); free(e);
} }
ps->root_width = DisplayWidth(ps->dpy, ps->scr);
ps->root_height = DisplayHeight(ps->dpy, ps->scr);
xcb_prefetch_extension_data(ps->c, &xcb_render_id); xcb_prefetch_extension_data(ps->c, &xcb_render_id);
xcb_prefetch_extension_data(ps->c, &xcb_composite_id); xcb_prefetch_extension_data(ps->c, &xcb_composite_id);
xcb_prefetch_extension_data(ps->c, &xcb_damage_id); xcb_prefetch_extension_data(ps->c, &xcb_damage_id);

View File

@ -38,7 +38,7 @@ enum root_flags {
void add_damage(session_t *ps, const region_t *damage); void add_damage(session_t *ps, const region_t *damage);
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode); uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
xcb_window_t find_client_win(session_t *ps, xcb_window_t w); xcb_window_t find_client_win(session_t *ps, xcb_window_t w);

View File

@ -3,6 +3,7 @@
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com> // Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
@ -42,6 +43,22 @@ bool parse_long(const char *s, long *dest) {
return true; return true;
} }
/**
* Parse an int number.
*/
bool parse_int(const char *s, int *dest) {
long val;
if (!parse_long(s, &val)) {
return false;
}
if (val > INT_MAX || val < INT_MIN) {
log_error("Number exceeded int limits: %ld", val);
return false;
}
*dest = (int)val;
return true;
}
/** /**
* Parse a floating-point number in from a string, * Parse a floating-point number in from a string,
* also strips the trailing space and comma after the number. * also strips the trailing space and comma after the number.
@ -82,11 +99,11 @@ conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
if (src == (pc = parse_readnum(src, &val))) if (src == (pc = parse_readnum(src, &val)))
goto err1; goto err1;
src = pc; src = pc;
width = val; width = (int)val;
if (src == (pc = parse_readnum(src, &val))) if (src == (pc = parse_readnum(src, &val)))
goto err1; goto err1;
src = pc; src = pc;
height = val; height = (int)val;
// Validate matrix width and height // Validate matrix width and height
if (width <= 0 || height <= 0) { if (width <= 0 || height <= 0) {
@ -102,7 +119,7 @@ conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
"rendering, and/or consume lots of memory"); "rendering, and/or consume lots of memory");
// Allocate memory // Allocate memory
conv *matrix = cvalloc(sizeof(conv) + width * height * sizeof(double)); conv *matrix = cvalloc(sizeof(conv) + (size_t)(width * height) * sizeof(double));
// Read elements // Read elements
int skip = height / 2 * width + width / 2; int skip = height / 2 * width + width / 2;
@ -276,70 +293,76 @@ bool parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
*/ */
bool parse_geometry(session_t *ps, const char *src, region_t *dest) { bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
pixman_region32_clear(dest); pixman_region32_clear(dest);
if (!src) if (!src) {
return true; return true;
if (!ps->root_width || !ps->root_height) }
if (!ps->root_width || !ps->root_height) {
return true; return true;
}
geometry_t geom = {.wid = ps->root_width, .hei = ps->root_height, .x = 0, .y = 0}; long x = 0, y = 0;
long width = ps->root_width, height = ps->root_height;
long val = 0L; long val = 0L;
char *endptr = NULL; char *endptr = NULL;
src = skip_space(src); src = skip_space(src);
if (!*src) if (!*src) {
goto parse_geometry_end; goto parse_geometry_end;
}
// Parse width // Parse width
// Must be base 10, because "0x0..." may appear // Must be base 10, because "0x0..." may appear
if (!('+' == *src || '-' == *src)) { if (*src != '+' && *src != '-') {
val = strtol(src, &endptr, 10); val = strtol(src, &endptr, 10);
assert(endptr); assert(endptr);
if (src != endptr) { if (src != endptr) {
geom.wid = val; if (val < 0) {
if (geom.wid < 0) {
log_error("Invalid width: %s", src); log_error("Invalid width: %s", src);
return false; return false;
} }
width = val;
src = endptr; src = endptr;
} }
src = skip_space(src); src = skip_space(src);
} }
// Parse height // Parse height
if ('x' == *src) { if (*src == 'x') {
++src; ++src;
val = strtol(src, &endptr, 10); val = strtol(src, &endptr, 10);
assert(endptr); assert(endptr);
if (src != endptr) { if (src != endptr) {
geom.hei = val; if (val < 0) {
if (geom.hei < 0) {
log_error("Invalid height: %s", src); log_error("Invalid height: %s", src);
return false; return false;
} }
height = val;
src = endptr; src = endptr;
} }
src = skip_space(src); src = skip_space(src);
} }
// Parse x // Parse x
if ('+' == *src || '-' == *src) { if (*src == '+' || *src == '-') {
val = strtol(src, &endptr, 10); val = strtol(src, &endptr, 10);
if (endptr && src != endptr) { if (endptr && src != endptr) {
geom.x = val; x = val;
if (*src == '-') if (*src == '-') {
geom.x += ps->root_width - geom.wid; x += ps->root_width - width;
}
src = endptr; src = endptr;
} }
src = skip_space(src); src = skip_space(src);
} }
// Parse y // Parse y
if ('+' == *src || '-' == *src) { if (*src == '+' || *src == '-') {
val = strtol(src, &endptr, 10); val = strtol(src, &endptr, 10);
if (endptr && src != endptr) { if (endptr && src != endptr) {
geom.y = val; y = val;
if (*src == '-') if (*src == '-') {
geom.y += ps->root_height - geom.hei; y += ps->root_height - height;
}
src = endptr; src = endptr;
} }
src = skip_space(src); src = skip_space(src);
@ -351,7 +374,16 @@ bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
} }
parse_geometry_end: parse_geometry_end:
pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei); if (x < INT_MIN || x > INT_MAX || y < INT_MIN || y > INT_MAX) {
log_error("Geometry coordinates exceeded limits: %s", src);
return false;
}
if (width > UINT_MAX || height > UINT_MAX) {
// less than 0 is checked for earlier
log_error("Geometry size exceeded limits: %s", src);
return false;
}
pixman_region32_union_rect(dest, dest, (int)x, (int)y, (uint)width, (uint)height);
return true; return true;
} }

View File

@ -97,7 +97,7 @@ typedef struct options_t {
/// when determining if a window could be unredirected. /// when determining if a window could be unredirected.
c2_lptr_t *unredir_if_possible_blacklist; c2_lptr_t *unredir_if_possible_blacklist;
/// Delay before unredirecting screen, in milliseconds. /// Delay before unredirecting screen, in milliseconds.
unsigned long unredir_if_possible_delay; long unredir_if_possible_delay;
/// Forced redirection setting through D-Bus. /// Forced redirection setting through D-Bus.
switch_t redirected_force; switch_t redirected_force;
/// Whether to stop painting. Controlled through D-Bus. /// Whether to stop painting. Controlled through D-Bus.
@ -155,7 +155,7 @@ typedef struct options_t {
/// How much to fade out in a single fading step. /// How much to fade out in a single fading step.
double fade_out_step; double fade_out_step;
/// Fading time delta. In milliseconds. /// Fading time delta. In milliseconds.
unsigned long fade_delta; int fade_delta;
/// Whether to disable fading on window open/close. /// Whether to disable fading on window open/close.
bool no_fading_openclose; bool no_fading_openclose;
/// Whether to disable fading on ARGB managed destroyed windows. /// Whether to disable fading on ARGB managed destroyed windows.
@ -227,10 +227,11 @@ typedef struct options_t {
extern const char *const BACKEND_STRS[NUM_BKEND + 1]; extern const char *const BACKEND_STRS[NUM_BKEND + 1];
attr_warn_unused_result bool parse_long(const char *, long *); bool must_use parse_long(const char *, long *);
attr_warn_unused_result bool parse_blur_kern_lst(const char *, conv **, int, bool *hasneg); bool must_use parse_int(const char *, int *);
attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *); bool must_use parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *); bool must_use parse_geometry(session_t *, const char *, region_t *);
bool must_use parse_rule_opacity(c2_lptr_t **, const char *);
/** /**
* Add a pattern to a condition linked list. * Add a pattern to a condition linked list.

View File

@ -295,7 +295,12 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
// --detect-client-opacity // --detect-client-opacity
lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity); lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity);
// --refresh-rate // --refresh-rate
config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate); if (config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate)) {
if (opt->refresh_rate < 0) {
log_warn("Invalid refresh rate %d, fallback to 0", opt->refresh_rate);
opt->refresh_rate = 0;
}
}
// --vsync // --vsync
if (config_lookup_string(&cfg, "vsync", &sval)) { if (config_lookup_string(&cfg, "vsync", &sval)) {
opt->vsync = parse_vsync(sval); opt->vsync = parse_vsync(sval);
@ -337,8 +342,13 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
// --unredir-if-possible // --unredir-if-possible
lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible); lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible);
// --unredir-if-possible-delay // --unredir-if-possible-delay
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) {
opt->unredir_if_possible_delay = ival; if (ival < 0) {
log_warn("Invalid unredir-if-possible-delay %d", ival);
} else {
opt->unredir_if_possible_delay = ival;
}
}
// --inactive-dim-fixed // --inactive-dim-fixed
lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed); lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed);
// --detect-transient // --detect-transient

View File

@ -41,9 +41,9 @@ typedef uint32_t cdbus_window_t;
#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32 #define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32
#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING #define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING
typedef uint16_t cdbus_enum_t; typedef uint32_t cdbus_enum_t;
#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16 #define CDBUS_TYPE_ENUM DBUS_TYPE_UINT32
#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING #define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT32_AS_STRING
#define CDBUS_SERVICE_NAME "com.github.chjj.compton" #define CDBUS_SERVICE_NAME "com.github.chjj.compton"
#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME #define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME
@ -610,6 +610,14 @@ static inline bool cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val); return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
} }
/**
* Send a reply with an int32 argument, cast from a long.
*/
static inline bool cdbus_reply_int32l(session_t *ps, DBusMessage *srcmsg, long val) {
int32_t tmp = (int32_t)val;
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &tmp);
}
/** /**
* Send a reply with an uint32 argument. * Send a reply with an uint32 argument.
*/ */
@ -786,12 +794,12 @@ static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
cdbus_m_win_get_do(class_general, cdbus_reply_string); cdbus_m_win_get_do(class_general, cdbus_reply_string);
cdbus_m_win_get_do(role, cdbus_reply_string); cdbus_m_win_get_do(role, cdbus_reply_string);
cdbus_m_win_get_do(opacity, cdbus_reply_uint32); cdbus_m_win_get_do(opacity, cdbus_reply_double);
cdbus_m_win_get_do(opacity_tgt, cdbus_reply_uint32); cdbus_m_win_get_do(opacity_tgt, cdbus_reply_double);
cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool); cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool);
cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32); cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32);
cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool); cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool);
cdbus_m_win_get_do(opacity_set, cdbus_reply_uint32); cdbus_m_win_get_do(opacity_set, cdbus_reply_double);
cdbus_m_win_get_do(frame_opacity, cdbus_reply_double); cdbus_m_win_get_do(frame_opacity, cdbus_reply_double);
if (!strcmp("left_width", target)) { if (!strcmp("left_width", target)) {
@ -986,7 +994,7 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
return true; return true;
} }
cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool); cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool);
cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32); cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32l);
cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum); cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum);
cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum); cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum);
cdbus_m_opts_get_do(logpath, cdbus_reply_string); cdbus_m_opts_get_do(logpath, cdbus_reply_string);
@ -1010,8 +1018,8 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool); cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool);
cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32); cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32);
cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32); cdbus_m_opts_get_do(fade_in_step, cdbus_reply_double);
cdbus_m_opts_get_do(fade_out_step, cdbus_reply_int32); cdbus_m_opts_get_do(fade_out_step, cdbus_reply_double);
cdbus_m_opts_get_do(no_fading_openclose, cdbus_reply_bool); cdbus_m_opts_get_do(no_fading_openclose, cdbus_reply_bool);
cdbus_m_opts_get_do(blur_background, cdbus_reply_bool); cdbus_m_opts_get_do(blur_background, cdbus_reply_bool);
@ -1066,10 +1074,14 @@ static bool cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
// fade_delta // fade_delta
if (!strcmp("fade_delta", target)) { if (!strcmp("fade_delta", target)) {
int32_t val = 0.0; int32_t val = 0;
if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) {
return false; return false;
ps->o.fade_delta = max_i(val, 1); }
if (val <= 0) {
return false;
}
ps->o.fade_delta = max2(val, 1);
goto cdbus_process_opts_set_success; goto cdbus_process_opts_set_success;
} }

View File

@ -4,8 +4,8 @@
#include <X11/Xlibint.h> #include <X11/Xlibint.h>
#include <X11/extensions/sync.h> #include <X11/extensions/sync.h>
#include "compiler.h"
#include "common.h" #include "common.h"
#include "compiler.h"
#include "compton.h" #include "compton.h"
#include "event.h" #include "event.h"
#include "utils.h" #include "utils.h"
@ -93,7 +93,7 @@ static inline xcb_window_t attr_pure ev_window(session_t *ps, xcb_generic_event_
} }
} }
static inline const char * ev_name(session_t *ps, xcb_generic_event_t *ev) { static inline const char *ev_name(session_t *ps, xcb_generic_event_t *ev) {
static char buf[128]; static char buf[128];
switch (ev->response_type & 0x7f) { switch (ev->response_type & 0x7f) {
CASESTRRET(FocusIn); CASESTRRET(FocusIn);
@ -363,7 +363,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
} }
// If frame extents property changes // If frame extents property changes
if (ps->o.frame_opacity && ev->atom == ps->atom_frame_extents) { if (ps->o.frame_opacity > 0 && ev->atom == ps->atom_frame_extents) {
win *w = find_toplevel(ps, ev->window); win *w = find_toplevel(ps, ev->window);
if (w) { if (w) {
win_update_frame_extents(ps, w, ev->window); win_update_frame_extents(ps, w, ev->window);
@ -441,10 +441,10 @@ static inline void repair_win(session_t *ps, win *w) {
xcb_xfixes_region_t tmp = xcb_generate_id(ps->c); xcb_xfixes_region_t tmp = xcb_generate_id(ps->c);
xcb_xfixes_create_region(ps->c, tmp, 0, NULL); xcb_xfixes_create_region(ps->c, tmp, 0, NULL);
set_ignore_cookie(ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp)); set_ignore_cookie(ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp));
xcb_xfixes_translate_region(ps->c, tmp, w->g.x + w->g.border_width,
w->g.y + w->g.border_width);
x_fetch_region(ps->c, tmp, &parts); x_fetch_region(ps->c, tmp, &parts);
xcb_xfixes_destroy_region(ps->c, tmp); xcb_xfixes_destroy_region(ps->c, tmp);
pixman_region32_translate(&parts, w->g.x + w->g.border_width,
w->g.y + w->g.border_width);
} }
w->ever_damaged = true; w->ever_damaged = true;

View File

@ -14,20 +14,10 @@ double sum_kernel(const conv *map, int x, int y, int width, int height) {
double ret = 0; double ret = 0;
// Compute sum of values which are "in range" // Compute sum of values which are "in range"
int xstart = x, xend = width + x; int xstart = normalize_i_range(x, 0, map->w),
if (xstart < 0) { xend = normalize_i_range(width + x, 0, map->w);
xstart = 0; int ystart = normalize_i_range(y, 0, map->h),
} yend = normalize_i_range(height + y, 0, map->h);
if (xend > map->w) {
xend = map->w;
}
int ystart = y, yend = height + y;
if (ystart < 0) {
ystart = 0;
}
if (yend > map->h) {
yend = map->h;
}
assert(yend >= ystart && xend >= xstart); assert(yend >= ystart && xend >= xstart);
int d = map->w; int d = map->w;
@ -70,11 +60,11 @@ static double attr_const gaussian(double r, double x, double y) {
conv *gaussian_kernel(double r) { conv *gaussian_kernel(double r) {
conv *c; conv *c;
int size = r * 2 + 1; int size = (int)r * 2 + 1;
int center = size / 2; int center = size / 2;
double t; double t;
c = cvalloc(sizeof(conv) + size * size * sizeof(double)); c = cvalloc(sizeof(conv) + (size_t)(size * size) * sizeof(double));
c->w = c->h = size; c->w = c->h = size;
c->rsum = NULL; c->rsum = NULL;
t = 0.0; t = 0.0;

View File

@ -150,11 +150,13 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
size_t blen = vasprintf(&buf, fmt, args); int blen = vasprintf(&buf, fmt, args);
va_end(args); va_end(args);
if (!buf) if (blen < 0 || !buf) {
free(buf);
return; return;
}
struct timespec ts; struct timespec ts;
timespec_get(&ts, TIME_UTC); timespec_get(&ts, TIME_UTC);
@ -163,9 +165,10 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
strftime(time_buf, sizeof time_buf, "%x %T", tm); strftime(time_buf, sizeof time_buf, "%x %T", tm);
char *time = NULL; char *time = NULL;
size_t tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000); int tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000);
if (!time) { if (tlen < 0 || !time) {
free(buf); free(buf);
free(time);
return; return;
} }
@ -190,7 +193,7 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
head->ops->writev( head->ops->writev(
head, head,
(struct iovec[]){{.iov_base = "[ ", .iov_len = 2}, (struct iovec[]){{.iov_base = "[ ", .iov_len = 2},
{.iov_base = time, .iov_len = tlen}, {.iov_base = time, .iov_len = (size_t)tlen},
{.iov_base = " ", .iov_len = 1}, {.iov_base = " ", .iov_len = 1},
{.iov_base = (void *)func, .iov_len = flen}, {.iov_base = (void *)func, .iov_len = flen},
{.iov_base = " ", .iov_len = 1}, {.iov_base = " ", .iov_len = 1},
@ -198,7 +201,7 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
{.iov_base = (void *)log_level_str, .iov_len = llen}, {.iov_base = (void *)log_level_str, .iov_len = llen},
{.iov_base = (void *)s, .iov_len = slen}, {.iov_base = (void *)s, .iov_len = slen},
{.iov_base = " ] ", .iov_len = 3}, {.iov_base = " ] ", .iov_len = 3},
{.iov_base = buf, .iov_len = blen}, {.iov_base = buf, .iov_len = (size_t)blen},
{.iov_base = "\n", .iov_len = 1}}, {.iov_base = "\n", .iov_len = 1}},
11); 11);
head = head->next; head = head->next;
@ -329,12 +332,12 @@ struct log_target *stderr_logger_new(void) {
/// such as apitrace /// such as apitrace
struct gl_string_marker_logger { struct gl_string_marker_logger {
struct log_target tgt; struct log_target tgt;
void (*gl_string_marker)(GLsizei len, const char *); PFNGLSTRINGMARKERGREMEDYPROC gl_string_marker;
}; };
void gl_string_marker_logger_write(struct log_target *tgt, const char *str, size_t len) { void gl_string_marker_logger_write(struct log_target *tgt, const char *str, size_t len) {
auto g = (struct gl_string_marker_logger *)tgt; auto g = (struct gl_string_marker_logger *)tgt;
g->gl_string_marker(len, str); g->gl_string_marker((GLsizei)len, str);
} }
static const struct log_ops gl_string_marker_logger_ops = { static const struct log_ops gl_string_marker_logger_ops = {

View File

@ -323,45 +323,42 @@ bool glx_init_blur(session_t *ps) {
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
// Build shader // Build shader
{ int width = kern->w, height = kern->h;
int width = kern->w, height = kern->h; int nele = width * height - 1;
int nele = width * height - 1; assert(nele >= 0);
unsigned int len = auto len =
strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) +
strlen(sampler_type) + strlen(extension) + strlen(extension) +
(strlen(shader_add) + strlen(texture_func) + 42) * nele + (strlen(shader_add) + strlen(texture_func) + 42) * (uint)nele +
strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1;
strlen(texture_func) + 12 + 1; char *shader_str = ccalloc(len, char);
char *shader_str = ccalloc(len, char); char *pc = shader_str;
char *pc = shader_str; sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type);
sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type); pc += strlen(pc);
pc += strlen(pc); assert(strlen(shader_str) < len);
assert(strlen(shader_str) < len);
double sum = 0.0; double sum = 0.0;
for (int j = 0; j < height; ++j) { for (int j = 0; j < height; ++j) {
for (int k = 0; k < width; ++k) { for (int k = 0; k < width; ++k) {
if (height / 2 == j && width / 2 == k) if (height / 2 == j && width / 2 == k)
continue; continue;
double val = kern->data[j * width + k]; double val = kern->data[j * width + k];
if (val == 0) { if (val == 0) {
continue; continue;
}
sum += val;
sprintf(pc, shader_add, val, texture_func,
k - width / 2, j - height / 2);
pc += strlen(pc);
assert(strlen(shader_str) < len);
} }
sum += val;
sprintf(pc, shader_add, val, texture_func,
k - width / 2, j - height / 2);
pc += strlen(pc);
assert(strlen(shader_str) < len);
} }
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
assert(strlen(shader_str) < len);
ppass->frag_shader =
gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
free(shader_str);
} }
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
assert(strlen(shader_str) < len);
ppass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
free(shader_str);
if (!ppass->frag_shader) { if (!ppass->frag_shader) {
log_error("Failed to create fragment shader %d.", i); log_error("Failed to create fragment shader %d.", i);
free(extension); free(extension);
@ -443,8 +440,8 @@ bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fsha
/** /**
* Bind a X pixmap to an OpenGL texture. * Bind a X pixmap to an OpenGL texture.
*/ */
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width, bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, int width,
unsigned height, bool repeat, const struct glx_fbconfig_info *fbcfg) { int height, bool repeat, const struct glx_fbconfig_info *fbcfg) {
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID) if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
return true; return true;
@ -480,25 +477,27 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
} }
// Create GLX pixmap // Create GLX pixmap
unsigned depth = 0; int depth = 0;
if (!ptex->glpixmap) { if (!ptex->glpixmap) {
need_release = false; need_release = false;
// Retrieve pixmap parameters, if they aren't provided // Retrieve pixmap parameters, if they aren't provided
if (!(width && height)) { if (!width || !height) {
Window rroot = None; auto r = xcb_get_geometry_reply(
int rx = 0, ry = 0; ps->c, xcb_get_geometry(ps->c, pixmap), NULL);
unsigned rbdwid = 0; if (!r) {
if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, &width,
&height, &rbdwid, &depth)) {
log_error("Failed to query info of pixmap %#010x.", pixmap); log_error("Failed to query info of pixmap %#010x.", pixmap);
return false; return false;
} }
if (depth > OPENGL_MAX_DEPTH) { if (r->depth > OPENGL_MAX_DEPTH) {
log_error("Requested depth %d higher than %d.", depth, log_error("Requested depth %d higher than %d.", depth,
OPENGL_MAX_DEPTH); OPENGL_MAX_DEPTH);
return false; return false;
} }
depth = r->depth;
width = r->width;
height = r->height;
free(r);
} }
// Determine texture target, copied from compiz // Determine texture target, copied from compiz
@ -522,7 +521,7 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_EXT,
fbcfg->texture_fmt, fbcfg->texture_fmt,
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_TARGET_EXT,
tex_tgt, (GLint)tex_tgt,
0, 0,
}; };
@ -636,7 +635,8 @@ void glx_set_clip(session_t *ps, const region_t *reg) {
region_t reg_new; \ region_t reg_new; \
int nrects; \ int nrects; \
const rect_t *rects; \ const rect_t *rects; \
pixman_region32_init_rect(&reg_new, dx, dy, width, height); \ assert(width >= 0 && height >= 0); \
pixman_region32_init_rect(&reg_new, dx, dy, (uint)width, (uint)height); \
pixman_region32_intersect(&reg_new, &reg_new, (region_t *)reg_tgt); \ pixman_region32_intersect(&reg_new, &reg_new, (region_t *)reg_tgt); \
rects = pixman_region32_rectangles(&reg_new, &nrects); \ rects = pixman_region32_rectangles(&reg_new, &nrects); \
glBegin(GL_QUADS); \ glBegin(GL_QUADS); \
@ -704,13 +704,13 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2; inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2;
inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2; inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2;
} }
inc_x = min_i(ps->o.resize_damage, inc_x); inc_x = min2(ps->o.resize_damage, inc_x);
inc_y = min_i(ps->o.resize_damage, inc_y); inc_y = min2(ps->o.resize_damage, inc_y);
mdx = max_i(dx - inc_x, 0); mdx = max2(dx - inc_x, 0);
mdy = max_i(dy - inc_y, 0); mdy = max2(dy - inc_y, 0);
int mdx2 = min_i(dx + width + inc_x, ps->root_width), int mdx2 = min2(dx + width + inc_x, ps->root_width),
mdy2 = min_i(dy + height + inc_y, ps->root_height); mdy2 = min2(dy + height + inc_y, ps->root_height);
mwidth = mdx2 - mdx; mwidth = mdx2 - mdx;
mheight = mdy2 - mdy; mheight = mdy2 - mdy;
} }
@ -763,9 +763,9 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
// Texture scaling factor // Texture scaling factor
GLfloat texfac_x = 1.0f, texfac_y = 1.0f; GLfloat texfac_x = 1.0f, texfac_y = 1.0f;
if (GL_TEXTURE_2D == tex_tgt) { if (tex_tgt == GL_TEXTURE_2D) {
texfac_x /= mwidth; texfac_x /= (GLfloat)mwidth;
texfac_y /= mheight; texfac_y /= (GLfloat)mheight;
} }
// Paint it back // Paint it back
@ -816,39 +816,37 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
if (ppass->unifm_factor_center >= 0) if (ppass->unifm_factor_center >= 0)
glUniform1f(ppass->unifm_factor_center, factor_center); glUniform1f(ppass->unifm_factor_center, factor_center);
{ P_PAINTREG_START(crect) {
P_PAINTREG_START(crect) { auto rx = (GLfloat)(crect.x1 - mdx) * texfac_x;
const GLfloat rx = (crect.x1 - mdx) * texfac_x; auto ry = (GLfloat)(mheight - (crect.y1 - mdy)) * texfac_y;
const GLfloat ry = (mheight - (crect.y1 - mdy)) * texfac_y; auto rxe = rx + (GLfloat)(crect.x2 - crect.x1) * texfac_x;
const GLfloat rxe = rx + (crect.x2 - crect.x1) * texfac_x; auto rye = ry - (GLfloat)(crect.y2 - crect.y1) * texfac_y;
const GLfloat rye = ry - (crect.y2 - crect.y1) * texfac_y; auto rdx = (GLfloat)(crect.x1 - mdx);
GLfloat rdx = crect.x1 - mdx; auto rdy = (GLfloat)(mheight - crect.y1 + mdy);
GLfloat rdy = mheight - crect.y1 + mdy; if (last_pass) {
if (last_pass) { rdx = (GLfloat)crect.x1;
rdx = crect.x1; rdy = (GLfloat)(ps->root_height - crect.y1);
rdy = ps->root_height - crect.y1;
}
GLfloat rdxe = rdx + (crect.x2 - crect.x1);
GLfloat rdye = rdy - (crect.y2 - crect.y1);
// log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry,
// rxe, rye, rdx,
// rdy, rdxe, rdye);
glTexCoord2f(rx, ry);
glVertex3f(rdx, rdy, z);
glTexCoord2f(rxe, ry);
glVertex3f(rdxe, rdy, z);
glTexCoord2f(rxe, rye);
glVertex3f(rdxe, rdye, z);
glTexCoord2f(rx, rye);
glVertex3f(rdx, rdye, z);
} }
P_PAINTREG_END(); auto rdxe = rdx + (GLfloat)(crect.x2 - crect.x1);
auto rdye = rdy - (GLfloat)(crect.y2 - crect.y1);
// log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry,
// rxe, rye, rdx,
// rdy, rdxe, rdye);
glTexCoord2f(rx, ry);
glVertex3f(rdx, rdy, z);
glTexCoord2f(rxe, ry);
glVertex3f(rdxe, rdy, z);
glTexCoord2f(rxe, rye);
glVertex3f(rdxe, rdye, z);
glTexCoord2f(rx, rye);
glVertex3f(rdx, rdye, z);
} }
P_PAINTREG_END();
glUseProgram(0); glUseProgram(0);
@ -880,7 +878,7 @@ glx_blur_dst_end:
return ret; return ret;
} }
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, int z,
GLfloat factor, const region_t *reg_tgt) { GLfloat factor, const region_t *reg_tgt) {
// It's possible to dim in glx_render(), but it would be over-complicated // It's possible to dim in glx_render(), but it would be over-complicated
// considering all those mess in color negation and modulation // considering all those mess in color negation and modulation
@ -888,21 +886,19 @@ bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.0f, 0.0f, 0.0f, factor); glColor4f(0.0f, 0.0f, 0.0f, factor);
{ P_PAINTREG_START(crect) {
P_PAINTREG_START(crect) { // XXX what does all of these variables mean?
// XXX what does all of these variables mean? GLint rdx = crect.x1;
GLint rdx = crect.x1; GLint rdy = ps->root_height - crect.y1;
GLint rdy = ps->root_height - crect.y1; GLint rdxe = rdx + (crect.x2 - crect.x1);
GLint rdxe = rdx + (crect.x2 - crect.x1); GLint rdye = rdy - (crect.y2 - crect.y1);
GLint rdye = rdy - (crect.y2 - crect.y1);
glVertex3i(rdx, rdy, z); glVertex3i(rdx, rdy, z);
glVertex3i(rdxe, rdy, z); glVertex3i(rdxe, rdy, z);
glVertex3i(rdxe, rdye, z); glVertex3i(rdxe, rdye, z);
glVertex3i(rdx, rdye, z); glVertex3i(rdx, rdye, z);
}
P_PAINTREG_END();
} }
P_PAINTREG_END();
glColor4f(0.0f, 0.0f, 0.0f, 0.0f); glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glDisable(GL_BLEND); glDisable(GL_BLEND);
@ -941,7 +937,7 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
// This is all weird, but X Render is using premultiplied ARGB format, and // This is all weird, but X Render is using premultiplied ARGB format, and
// we need to use those things to correct it. Thanks to derhass for help. // we need to use those things to correct it. Thanks to derhass for help.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(opacity, opacity, opacity, opacity); glColor4d(opacity, opacity, opacity, opacity);
} }
if (!has_prog) { if (!has_prog) {
@ -1023,7 +1019,7 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
assert(pprogram->prog); assert(pprogram->prog);
glUseProgram(pprogram->prog); glUseProgram(pprogram->prog);
if (pprogram->unifm_opacity >= 0) if (pprogram->unifm_opacity >= 0)
glUniform1f(pprogram->unifm_opacity, opacity); glUniform1f(pprogram->unifm_opacity, (float)opacity);
if (pprogram->unifm_invert_color >= 0) if (pprogram->unifm_invert_color >= 0)
glUniform1i(pprogram->unifm_invert_color, neg); glUniform1i(pprogram->unifm_invert_color, neg);
if (pprogram->unifm_tex >= 0) if (pprogram->unifm_tex >= 0)
@ -1045,17 +1041,17 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
{ {
P_PAINTREG_START(crect) { P_PAINTREG_START(crect) {
// XXX explain these variables // XXX explain these variables
GLfloat rx = (double)(crect.x1 - dx + x); auto rx = (GLfloat)(crect.x1 - dx + x);
GLfloat ry = (double)(crect.y1 - dy + y); auto ry = (GLfloat)(crect.y1 - dy + y);
GLfloat rxe = rx + (double)(crect.x2 - crect.x1); auto rxe = rx + (GLfloat)(crect.x2 - crect.x1);
GLfloat rye = ry + (double)(crect.y2 - crect.y1); auto rye = ry + (GLfloat)(crect.y2 - crect.y1);
// Rectangle textures have [0-w] [0-h] while 2D texture has [0-1] // Rectangle textures have [0-w] [0-h] while 2D texture has [0-1]
// [0-1] Thanks to amonakov for pointing out! // [0-1] Thanks to amonakov for pointing out!
if (GL_TEXTURE_2D == ptex->target) { if (GL_TEXTURE_2D == ptex->target) {
rx = rx / ptex->width; rx = rx / (GLfloat)ptex->width;
ry = ry / ptex->height; ry = ry / (GLfloat)ptex->height;
rxe = rxe / ptex->width; rxe = rxe / (GLfloat)ptex->width;
rye = rye / ptex->height; rye = rye / (GLfloat)ptex->height;
} }
GLint rdx = crect.x1; GLint rdx = crect.x1;
GLint rdy = ps->root_height - crect.y1; GLint rdy = ps->root_height - crect.y1;
@ -1065,8 +1061,8 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
// Invert Y if needed, this may not work as expected, though. I // Invert Y if needed, this may not work as expected, though. I
// don't have such a FBConfig to test with. // don't have such a FBConfig to test with.
if (!ptex->y_inverted) { if (!ptex->y_inverted) {
ry = 1.0 - ry; ry = 1.0f - ry;
rye = 1.0 - rye; rye = 1.0f - rye;
} }
// log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx, // log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx,

View File

@ -26,7 +26,7 @@
#include <xcb/render.h> #include <xcb/render.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, int z,
GLfloat factor, const region_t *reg_tgt); GLfloat factor, const region_t *reg_tgt);
bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy, bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy,
@ -46,8 +46,8 @@ bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fsha
glx_prog_main_t *pprogram); glx_prog_main_t *pprogram);
#endif #endif
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width, bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, int width,
unsigned height, bool repeat, const struct glx_fbconfig_info *); int height, bool repeat, const struct glx_fbconfig_info *);
void glx_release_pixmap(session_t *ps, glx_texture_t *ptex); void glx_release_pixmap(session_t *ps, glx_texture_t *ptex);

View File

@ -483,7 +483,6 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
"open a bug report."; "open a bug report.";
optind = 1; optind = 1;
while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) { while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
long val = 0;
switch (o) { switch (o) {
#define P_CASEBOOL(idx, option) \ #define P_CASEBOOL(idx, option) \
case idx: \ case idx: \
@ -491,9 +490,15 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
break break
#define P_CASELONG(idx, option) \ #define P_CASELONG(idx, option) \
case idx: \ case idx: \
if (!parse_long(optarg, &val)) \ if (!parse_long(optarg, &opt->option)) { \
exit(1); \ exit(1); \
opt->option = val; \ } \
break
#define P_CASEINT(idx, option) \
case idx: \
if (!parse_int(optarg, &opt->option)) { \
exit(1); \
} \
break break
// clang-format off // clang-format off
@ -511,7 +516,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
case 320: case 320:
// These options are handled by get_early_config() // These options are handled by get_early_config()
break; break;
P_CASELONG('D', fade_delta); P_CASEINT('D', fade_delta);
case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break; case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break;
case 'O': opt->fade_out_step = normalize_d(atof(optarg)); break; case 'O': opt->fade_out_step = normalize_d(atof(optarg)); break;
case 'c': shadow_enable = true; break; case 'c': shadow_enable = true; break;
@ -535,12 +540,12 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
case 'F': case 'F':
fading_enable = true; fading_enable = true;
break; break;
P_CASELONG('r', shadow_radius); P_CASEINT('r', shadow_radius);
case 'o': case 'o':
opt->shadow_opacity = atof(optarg); opt->shadow_opacity = atof(optarg);
break; break;
P_CASELONG('l', shadow_offset_x); P_CASEINT('l', shadow_offset_x);
P_CASELONG('t', shadow_offset_y); P_CASEINT('t', shadow_offset_y);
case 'i': case 'i':
opt->inactive_opacity = normalize_d(atof(optarg)); opt->inactive_opacity = normalize_d(atof(optarg));
break; break;
@ -587,7 +592,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
P_CASEBOOL(266, shadow_ignore_shaped); P_CASEBOOL(266, shadow_ignore_shaped);
P_CASEBOOL(267, detect_rounded_corners); P_CASEBOOL(267, detect_rounded_corners);
P_CASEBOOL(268, detect_client_opacity); P_CASEBOOL(268, detect_client_opacity);
P_CASELONG(269, refresh_rate); P_CASEINT(269, refresh_rate);
case 270: case 270:
if (optarg) { if (optarg) {
opt->vsync = parse_vsync(optarg); opt->vsync = parse_vsync(optarg);
@ -656,10 +661,10 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
log_error("--glx-copy-from-front %s", deprecation_message); log_error("--glx-copy-from-front %s", deprecation_message);
exit(1); exit(1);
break; break;
P_CASELONG(293, benchmark); P_CASEINT(293, benchmark);
case 294: case 294:
// --benchmark-wid // --benchmark-wid
opt->benchmark_wid = strtol(optarg, NULL, 0); opt->benchmark_wid = (xcb_window_t)strtol(optarg, NULL, 0);
break; break;
case 295: case 295:
log_error("--glx-use-copysubbuffermesa %s", deprecation_message); log_error("--glx-use-copysubbuffermesa %s", deprecation_message);
@ -706,7 +711,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
MAX_BLUR_PASS, &conv_kern_hasneg)) MAX_BLUR_PASS, &conv_kern_hasneg))
exit(1); exit(1);
break; break;
P_CASELONG(302, resize_damage); P_CASEINT(302, resize_damage);
case 303: case 303:
// --glx-use-gpushader4 // --glx-use-gpushader4
log_warn("--glx-use-gpushader4 is deprecated since v6." log_warn("--glx-use-gpushader4 is deprecated since v6."
@ -782,8 +787,8 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
} }
// Range checking and option assignments // Range checking and option assignments
opt->fade_delta = max_i(opt->fade_delta, 1); opt->fade_delta = max2(opt->fade_delta, 1);
opt->shadow_radius = max_i(opt->shadow_radius, 0); opt->shadow_radius = max2(opt->shadow_radius, 0);
opt->shadow_red = normalize_d(opt->shadow_red); opt->shadow_red = normalize_d(opt->shadow_red);
opt->shadow_green = normalize_d(opt->shadow_green); opt->shadow_green = normalize_d(opt->shadow_green);
opt->shadow_blue = normalize_d(opt->shadow_blue); opt->shadow_blue = normalize_d(opt->shadow_blue);
@ -802,7 +807,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
// Other variables determined by options // Other variables determined by options
// Determine whether we need to track focus changes // Determine whether we need to track focus changes
if (opt->inactive_opacity != opt->active_opacity || opt->inactive_dim) { if (opt->inactive_opacity != opt->active_opacity || opt->inactive_dim > 0) {
opt->track_focus = true; opt->track_focus = true;
} }

View File

@ -42,7 +42,8 @@ static inline rect_t from_x_rect(const xcb_rectangle_t *rect) {
/// Returning an array that needs to be freed /// Returning an array that needs to be freed
static inline rect_t *from_x_rects(int nrects, const xcb_rectangle_t *rects) { static inline rect_t *from_x_rects(int nrects, const xcb_rectangle_t *rects) {
rect_t *ret = ccalloc(nrects, rect_t); rect_t *ret = ccalloc(nrects, rect_t);
for (int i = 0; i < nrects; i++) for (int i = 0; i < nrects; i++) {
ret[i] = from_x_rect(rects + i); ret[i] = from_x_rect(rects + i);
}
return ret; return ret;
} }

View File

@ -34,9 +34,8 @@
/** /**
* Bind texture in paint_t if we are using GLX backend. * Bind texture in paint_t if we are using GLX backend.
*/ */
static inline bool static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int hei,
paint_bind_tex(session_t *ps, paint_t *ppaint, unsigned wid, unsigned hei, bool repeat, bool repeat, int depth, xcb_visualid_t visual, bool force) {
int depth, xcb_visualid_t visual, bool force) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
// XXX This is a mess. But this will go away after the backend refactor. // XXX This is a mess. But this will go away after the backend refactor.
static thread_local struct glx_fbconfig_info *argb_fbconfig = NULL; static thread_local struct glx_fbconfig_info *argb_fbconfig = NULL;
@ -174,13 +173,15 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, doubl
switch (ps->o.backend) { switch (ps->o.backend) {
case BKEND_XRENDER: case BKEND_XRENDER:
case BKEND_XR_GLX_HYBRID: { case BKEND_XR_GLX_HYBRID: {
int alpha_step = opacity * MAX_ALPHA; auto alpha_step = (int)(opacity * MAX_ALPHA);
xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step]; xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step];
if (alpha_step != 0) { if (alpha_step != 0) {
int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC uint8_t op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC
: XCB_RENDER_PICT_OP_OVER); : XCB_RENDER_PICT_OP_OVER);
xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict, xcb_render_composite(
x, y, 0, 0, dx, dy, wid, hei); ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
to_i16_checked(x), to_i16_checked(y), 0, 0, to_i16_checked(dx),
to_i16_checked(dy), to_u16_checked(wid), to_u16_checked(hei));
} }
break; break;
} }
@ -279,8 +280,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
const int x = w->g.x; const int x = w->g.x;
const int y = w->g.y; const int y = w->g.y;
const int wid = w->widthb; const uint16_t wid = to_u16_checked(w->widthb);
const int hei = w->heightb; const uint16_t hei = to_u16_checked(w->heightb);
xcb_render_picture_t pict = w->paint.pict; xcb_render_picture_t pict = w->paint.pict;
@ -320,10 +321,10 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
} else { } else {
// Painting parameters // Painting parameters
const margin_t extents = win_calc_frame_extents(w); const margin_t extents = win_calc_frame_extents(w);
const int t = extents.top; const auto t = (int)extents.top;
const int l = extents.left; const auto l = (int)extents.left;
const int b = extents.bottom; const auto b = (int)extents.bottom;
const int r = extents.right; const auto r = (int)extents.right;
#define COMP_BDR(cx, cy, cwid, chei) \ #define COMP_BDR(cx, cy, cwid, chei) \
paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * w->opacity, \ paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * w->opacity, \
@ -337,7 +338,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
int body_height = hei; int body_height = hei;
// ctop = checked top // ctop = checked top
// Make sure top margin is smaller than height // Make sure top margin is smaller than height
int ctop = min_i(body_height, t); int ctop = min2(body_height, t);
if (ctop > 0) if (ctop > 0)
COMP_BDR(0, 0, wid, ctop); COMP_BDR(0, 0, wid, ctop);
@ -348,7 +349,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
// bottom // bottom
// cbot = checked bottom // cbot = checked bottom
// Make sure bottom margin is not too large // Make sure bottom margin is not too large
int cbot = min_i(body_height, b); int cbot = min2(body_height, b);
if (cbot > 0) if (cbot > 0)
COMP_BDR(0, hei - cbot, wid, cbot); COMP_BDR(0, hei - cbot, wid, cbot);
@ -359,7 +360,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
// left // left
int body_width = wid; int body_width = wid;
int cleft = min_i(body_width, l); int cleft = min2(body_width, l);
if (cleft > 0) if (cleft > 0)
COMP_BDR(0, ctop, cleft, body_height); COMP_BDR(0, ctop, cleft, body_height);
@ -368,7 +369,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
break; break;
// right // right
int cright = min_i(body_width, r); int cright = min2(body_width, r);
if (cright > 0) if (cright > 0)
COMP_BDR(wid - cright, ctop, cright, body_height); COMP_BDR(wid - cright, ctop, cright, body_height);
@ -396,7 +397,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
switch (ps->o.backend) { switch (ps->o.backend) {
case BKEND_XRENDER: case BKEND_XRENDER:
case BKEND_XR_GLX_HYBRID: { case BKEND_XR_GLX_HYBRID: {
unsigned short cval = 0xffff * dim_opacity; auto cval = (uint16_t)(0xffff * dim_opacity);
// Premultiply color // Premultiply color
xcb_render_color_t color = { xcb_render_color_t color = {
@ -407,8 +408,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
}; };
xcb_rectangle_t rect = { xcb_rectangle_t rect = {
.x = x, .x = to_i16_checked(x),
.y = y, .y = to_i16_checked(y),
.width = wid, .width = wid,
.height = hei, .height = hei,
}; };
@ -418,8 +419,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
} break; } break;
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
case BKEND_GLX: case BKEND_GLX:
glx_dim_dst(ps, x, y, wid, hei, ps->psglx->z - 0.7, dim_opacity, glx_dim_dst(ps, x, y, wid, hei, (int)(ps->psglx->z - 0.7),
reg_paint); (float)dim_opacity, reg_paint);
break; break;
#endif #endif
default: assert(false); default: assert(false);
@ -447,7 +448,7 @@ static bool get_root_tile(session_t *ps) {
// Create a pixmap if there isn't any // Create a pixmap if there isn't any
if (!pixmap) { if (!pixmap) {
pixmap = x_create_pixmap(ps->c, ps->depth, ps->root, 1, 1); pixmap = x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root, 1, 1);
if (pixmap == XCB_NONE) { if (pixmap == XCB_NONE) {
log_error("Failed to create pixmaps for root tile."); log_error("Failed to create pixmaps for root tile.");
return false; return false;
@ -605,8 +606,9 @@ static inline void win_paint_shadow(session_t *ps, win *w, region_t *reg_paint)
* *
* @return true if successful, false otherwise * @return true if successful, false otherwise
*/ */
static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wid, static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x,
int hei, xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) { int16_t y, uint16_t wid, uint16_t hei,
xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) {
assert(blur_kerns[0]); assert(blur_kerns[0]);
// Directly copying from tgt_buffer to it does not work, so we create a // Directly copying from tgt_buffer to it does not work, so we create a
@ -627,16 +629,16 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, i
assert(i < MAX_BLUR_PASS - 1); assert(i < MAX_BLUR_PASS - 1);
xcb_render_fixed_t *convolution_blur = blur_kerns[i]; xcb_render_fixed_t *convolution_blur = blur_kerns[i];
// `x / 65536.0` converts from X fixed point to double // `x / 65536.0` converts from X fixed point to double
int kwid = ((double)convolution_blur[0]) / 65536.0, int kwid = (int)((double)convolution_blur[0] / 65536.0),
khei = ((double)convolution_blur[1]) / 65536.0; khei = (int)((double)convolution_blur[1] / 65536.0);
bool rd_from_tgt = (tgt_buffer == src_pict); bool rd_from_tgt = (tgt_buffer == src_pict);
// Copy from source picture to destination. The filter must // Copy from source picture to destination. The filter must
// be applied on source picture, to get the nearby pixels outside the // be applied on source picture, to get the nearby pixels outside the
// window. // window.
xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), xcb_render_set_picture_filter(
XRFILTER_CONVOLUTION, kwid * khei + 2, ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
convolution_blur); (uint32_t)(kwid * khei + 2), convolution_blur);
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
dst_pict, (rd_from_tgt ? x : 0), dst_pict, (rd_from_tgt ? x : 0),
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x), (rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
@ -664,10 +666,10 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, i
*/ */
static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer, static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
const region_t *reg_paint) { const region_t *reg_paint) {
const int x = w->g.x; const int16_t x = w->g.x;
const int y = w->g.y; const int16_t y = w->g.y;
const int wid = w->widthb; const auto wid = to_u16_checked(w->widthb);
const int hei = w->heightb; const auto hei = to_u16_checked(w->heightb);
double factor_center = 1.0; double factor_center = 1.0;
// Adjust blur strength according to window opacity, to make it appear // Adjust blur strength according to window opacity, to make it appear
@ -702,7 +704,7 @@ static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture
// If kern_dst is allocated, it's always allocated to the right // If kern_dst is allocated, it's always allocated to the right
// size // size
size_t size = kern_dst ? kern_src->w * kern_src->h + 2 : 0; size_t size = kern_dst ? (size_t)(kern_src->w * kern_src->h + 2) : 0;
x_picture_filter_from_conv(kern_src, factor_center, &kern_dst, &size); x_picture_filter_from_conv(kern_src, factor_center, &kern_dst, &size);
ps->blur_kerns_cache[i] = kern_dst; ps->blur_kerns_cache[i] = kern_dst;
} }
@ -726,8 +728,8 @@ static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
case BKEND_GLX: case BKEND_GLX:
// TODO: Handle frame opacity // TODO: Handle frame opacity
glx_blur_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5, factor_center, glx_blur_dst(ps, x, y, wid, hei, (float)ps->psglx->z - 0.5f,
reg_paint, &w->glx_blur_cache); (float)factor_center, reg_paint, &w->glx_blur_cache);
break; break;
#endif #endif
default: assert(0); default: assert(0);
@ -786,7 +788,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
pixman_region32_copy(&region, &ps->screen_reg); pixman_region32_copy(&region, &ps->screen_reg);
} else { } else {
for (int i = 0; i < get_buffer_age(ps); i++) { for (int i = 0; i < get_buffer_age(ps); i++) {
const int curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage; auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
pixman_region32_union(&region, &region, &ps->damage_ring[curr]); pixman_region32_union(&region, &region, &ps->damage_ring[curr]);
} }
} }
@ -800,7 +802,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
#endif #endif
if (ps->o.resize_damage > 0) { if (ps->o.resize_damage > 0) {
resize_region(&region, ps->o.resize_damage); resize_region(&region, (short)ps->o.resize_damage);
} }
// Remove the damaged area out of screen // Remove the damaged area out of screen
@ -809,8 +811,9 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
if (!paint_isvalid(ps, &ps->tgt_buffer)) { if (!paint_isvalid(ps, &ps->tgt_buffer)) {
if (!ps->tgt_buffer.pixmap) { if (!ps->tgt_buffer.pixmap) {
free_paint(ps, &ps->tgt_buffer); free_paint(ps, &ps->tgt_buffer);
ps->tgt_buffer.pixmap = x_create_pixmap( ps->tgt_buffer.pixmap =
ps->c, ps->depth, ps->root, ps->root_width, ps->root_height); x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root,
ps->root_width, ps->root_height);
if (ps->tgt_buffer.pixmap == XCB_NONE) { if (ps->tgt_buffer.pixmap == XCB_NONE) {
log_fatal("Failed to allocate a screen-sized pixmap for" log_fatal("Failed to allocate a screen-sized pixmap for"
"painting"); "painting");
@ -874,9 +877,10 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
// Might be worth while to crop the region to shadow // Might be worth while to crop the region to shadow
// border // border
assert(w->shadow_width >= 0 && w->shadow_height >= 0);
pixman_region32_intersect_rect( pixman_region32_intersect_rect(
&reg_tmp, &reg_tmp, w->g.x + w->shadow_dx, &reg_tmp, &reg_tmp, w->g.x + w->shadow_dx, w->g.y + w->shadow_dy,
w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height); (uint)w->shadow_width, (uint)w->shadow_height);
// Mask out the body of the window from the shadow if // Mask out the body of the window from the shadow if
// needed Doing it here instead of in make_shadow() for // needed Doing it here instead of in make_shadow() for
@ -958,6 +962,8 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
ps->vsync_wait(ps); ps->vsync_wait(ps);
} }
auto rwidth = to_u16_checked(ps->root_width);
auto rheight = to_u16_checked(ps->root_height);
switch (ps->o.backend) { switch (ps->o.backend) {
case BKEND_XRENDER: case BKEND_XRENDER:
if (ps->o.monitor_repaint) { if (ps->o.monitor_repaint) {
@ -969,16 +975,16 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
// to it // to it
auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis); auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis);
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt( xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
ps->c, ps->root, ps->root_width, ps->root_height, pictfmt, 0, NULL); ps->c, ps->root, rwidth, rheight, pictfmt, 0, NULL);
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
ps->tgt_buffer.pict, XCB_NONE, new_pict, 0, 0, ps->tgt_buffer.pict, XCB_NONE, new_pict, 0,
0, 0, 0, 0, ps->root_width, ps->root_height); 0, 0, 0, 0, 0, rwidth, rheight);
// Next, we set the region of paint and highlight it // Next, we set the region of paint and highlight it
x_set_picture_clip_region(ps->c, new_pict, 0, 0, &region); x_set_picture_clip_region(ps->c, new_pict, 0, 0, &region);
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, 0, ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0,
0, 0, 0, 0, ps->root_width, ps->root_height); 0, 0, 0, 0, 0, rwidth, rheight);
// Finally, clear clip regions of new_pict and the screen, and put // Finally, clear clip regions of new_pict and the screen, and put
// the whole thing on screen // the whole thing on screen
@ -986,12 +992,12 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
x_set_picture_clip_region(ps->c, ps->tgt_picture, 0, 0, &ps->screen_reg); x_set_picture_clip_region(ps->c, ps->tgt_picture, 0, 0, &ps->screen_reg);
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict,
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0, XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
ps->root_width, ps->root_height); rwidth, rheight);
xcb_render_free_picture(ps->c, new_pict); xcb_render_free_picture(ps->c, new_pict);
} else } else
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0, ps->tgt_buffer.pict, XCB_NONE, ps->tgt_picture,
ps->root_width, ps->root_height); 0, 0, 0, 0, 0, 0, rwidth, rheight);
break; break;
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
case BKEND_XR_GLX_HYBRID: case BKEND_XR_GLX_HYBRID:
@ -1151,7 +1157,7 @@ bool init_render(session_t *ps) {
// Generates another Picture for shadows if the color is modified by // Generates another Picture for shadows if the color is modified by
// user // user
if (!ps->o.shadow_red && !ps->o.shadow_green && !ps->o.shadow_blue) { if (ps->o.shadow_red == 0 && ps->o.shadow_green == 0 && ps->o.shadow_blue == 0) {
ps->cshadow_picture = ps->black_picture; ps->cshadow_picture = ps->black_picture;
} else { } else {
ps->cshadow_picture = solid_picture(ps->c, ps->root, true, 1, ps->o.shadow_red, ps->cshadow_picture = solid_picture(ps->c, ps->root, true, 1, ps->o.shadow_red,

View File

@ -2,9 +2,9 @@
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com> // Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#pragma once #pragma once
#include <xcb/xcb.h>
#include <xcb/render.h>
#include <stdbool.h> #include <stdbool.h>
#include <xcb/render.h>
#include <xcb/xcb.h>
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
#include "backend/gl/glx.h" #include "backend/gl/glx.h"
#endif #endif
@ -16,24 +16,20 @@ typedef struct win win;
typedef struct session session_t; typedef struct session session_t;
typedef struct paint { typedef struct paint {
xcb_pixmap_t pixmap; xcb_pixmap_t pixmap;
xcb_render_picture_t pict; xcb_render_picture_t pict;
glx_texture_t *ptex; glx_texture_t *ptex;
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
struct glx_fbconfig_info *fbcfg; struct glx_fbconfig_info *fbcfg;
#endif #endif
} paint_t; } paint_t;
void void render(session_t *ps, int x, int y, int dx, int dy, int w, int h, double opacity,
render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex,
double opacity, bool argb, bool neg, const region_t *reg_paint, const glx_prog_main_t *pprogram);
xcb_render_picture_t pict, glx_texture_t *ptex, void paint_one(session_t *ps, win *w, const region_t *reg_paint);
const region_t *reg_paint, const glx_prog_main_t *pprogram);
void
paint_one(session_t *ps, win *w, const region_t *reg_paint);
void void paint_all(session_t *ps, win *const t, bool ignore_damage);
paint_all(session_t *ps, win * const t, bool ignore_damage);
void free_picture(xcb_connection_t *c, xcb_render_picture_t *p); void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);

View File

@ -4,6 +4,8 @@
#include <ctype.h> #include <ctype.h>
#include <stddef.h> #include <stddef.h>
#include "compiler.h"
#define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1)) #define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1))
char *mstrjoin(const char *src1, const char *src2); char *mstrjoin(const char *src1, const char *src2);
@ -26,7 +28,7 @@ static inline int uitostr(unsigned int n, char *buf) {
int pos = ret; int pos = ret;
while (pos--) { while (pos--) {
buf[pos] = n % 10 + '0'; buf[pos] = (char)(n % 10 + '0');
n /= 10; n /= 10;
} }
return ret; return ret;

View File

@ -14,14 +14,6 @@ typedef enum {
UNSET UNSET
} switch_t; } switch_t;
/// Structure representing a X geometry.
typedef struct {
int wid;
int hei;
int x;
int y;
} geometry_t;
/// A structure representing margins around a rectangle. /// A structure representing margins around a rectangle.
typedef struct { typedef struct {
unsigned int top; unsigned int top;

View File

@ -22,7 +22,7 @@ void report_allocation_failure(const char *func, const char *file, unsigned int
{.iov_base = "at ", .iov_len = 3}, {.iov_base = "at ", .iov_len = 3},
{.iov_base = (void *)file, .iov_len = strlen(file)}, {.iov_base = (void *)file, .iov_len = strlen(file)},
{.iov_base = ":", .iov_len = 1}, {.iov_base = ":", .iov_len = 1},
{.iov_base = buf, .iov_len = llen}, {.iov_base = buf, .iov_len = (size_t)llen},
{.iov_base = (void *)msg2, .iov_len = sizeof(msg2) - 1}, {.iov_base = (void *)msg2, .iov_len = sizeof(msg2) - 1},
}; };

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
@ -42,13 +43,51 @@ safe_isnan(double a) {
} while (0) } while (0)
/// Same as assert, but evaluates the expression even in release builds /// Same as assert, but evaluates the expression even in release builds
#define CHECK(expr) \ #define CHECK(expr) \
do { \ do { \
__auto_type __tmp = (expr); \ __auto_type __tmp = (expr); \
assert(__tmp); \ assert(__tmp); \
(void)__tmp; \ (void)__tmp; \
} while (0) } while (0)
// Some macros for checked cast
#define to_int_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= INT_MIN && tmp <= INT_MAX); \
(int)tmp; \
})
#define to_char_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= CHAR_MIN && tmp <= CHAR_MAX); \
(char)tmp; \
})
#define to_u16_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= 0 && tmp <= UINT16_MAX); \
(uint16_t) tmp; \
})
#define to_i16_checked(val) \
({ \
auto tmp = (val); \
assert(tmp >= INT16_MIN && tmp <= INT16_MAX); \
(int16_t) tmp; \
})
#define to_u32_checked(val) \
({ \
auto tmp = (val); \
int64_t max = UINT32_MAX; /* silence clang tautological comparison \
warning*/ \
assert(tmp >= 0 && tmp <= max); \
(uint32_t) tmp; \
})
/** /**
* Normalize an int value to a specific range. * Normalize an int value to a specific range.
* *
@ -65,33 +104,11 @@ static inline int attr_const normalize_i_range(int i, int min, int max) {
return i; return i;
} }
/** #define min2(a, b) ((a) > (b) ? (b) : (a))
* Select the larger integer of two. #define max2(a, b) ((a) > (b) ? (a) : (b))
*/
static inline int attr_const max_i(int a, int b) {
return (a > b ? a : b);
}
/** /// clamp `val` into interval [min, max]
* Select the smaller integer of two. #define clamp(val, min, max) max2(min2(val, max), min)
*/
static inline int attr_const min_i(int a, int b) {
return (a > b ? b : a);
}
/**
* Select the larger long integer of two.
*/
static inline long attr_const max_l(long a, long b) {
return (a > b ? a : b);
}
/**
* Select the smaller long integer of two.
*/
static inline long attr_const min_l(long a, long b) {
return (a > b ? b : a);
}
static inline int attr_const popcountl(unsigned long a) { static inline int attr_const popcountl(unsigned long a) {
return __builtin_popcountl(a); return __builtin_popcountl(a);
@ -147,11 +164,20 @@ allocchk_(const char *func_name, const char *file, unsigned int line, void *ptr)
#define cvalloc(size) allocchk(malloc(size)) #define cvalloc(size) allocchk(malloc(size))
/// @brief Wrapper of calloc(). /// @brief Wrapper of calloc().
#define ccalloc(nmemb, type) ((type *)allocchk(calloc((nmemb), sizeof(type)))) #define ccalloc(nmemb, type) \
({ \
auto tmp = (nmemb); \
assert(tmp >= 0); \
((type *)allocchk(calloc((size_t)tmp, sizeof(type)))); \
})
/// @brief Wrapper of ealloc(). /// @brief Wrapper of ealloc().
#define crealloc(ptr, nmemb) \ #define crealloc(ptr, nmemb) \
((__typeof__(ptr))allocchk(realloc((ptr), (nmemb) * sizeof(*(ptr))))) ({ \
auto tmp = (nmemb); \
assert(tmp >= 0); \
((__typeof__(ptr))allocchk(realloc((ptr), (size_t)tmp * sizeof(*(ptr))))); \
})
/// RC_TYPE generates a reference counted type from `type` /// RC_TYPE generates a reference counted type from `type`
/// ///

View File

@ -38,7 +38,7 @@ static int vsync_drm_wait(session_t *ps) {
do { do {
ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl); ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
vbl.request.type &= ~_DRM_VBLANK_RELATIVE; vbl.request.type &= ~(uint)_DRM_VBLANK_RELATIVE;
} while (ret && errno == EINTR); } while (ret && errno == EINTR);
if (ret) if (ret)
@ -90,9 +90,9 @@ static bool vsync_opengl_oml_init(session_t *ps) {
return glxext.has_GLX_OML_sync_control; return glxext.has_GLX_OML_sync_control;
} }
static inline bool vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) { static inline bool vsync_opengl_swc_swap_interval(session_t *ps, int interval) {
if (glxext.has_GLX_MESA_swap_control) if (glxext.has_GLX_MESA_swap_control)
return glXSwapIntervalMESA(interval) == 0; return glXSwapIntervalMESA((uint)interval) == 0;
else if (glxext.has_GLX_SGI_swap_control) else if (glxext.has_GLX_SGI_swap_control)
return glXSwapIntervalSGI(interval) == 0; return glXSwapIntervalSGI(interval) == 0;
else if (glxext.has_GLX_EXT_swap_control) { else if (glxext.has_GLX_EXT_swap_control) {

View File

@ -110,8 +110,9 @@ static inline bool group_is_focused(session_t *ps, xcb_window_t leader) {
* Get a rectangular region a window occupies, excluding shadow. * Get a rectangular region a window occupies, excluding shadow.
*/ */
static void win_get_region_local(const win *w, region_t *res) { static void win_get_region_local(const win *w, region_t *res) {
assert(w->widthb >= 0 && w->heightb >= 0);
pixman_region32_fini(res); pixman_region32_fini(res);
pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb); pixman_region32_init_rect(res, 0, 0, (uint)w->widthb, (uint)w->heightb);
} }
/** /**
@ -120,14 +121,15 @@ static void win_get_region_local(const win *w, region_t *res) {
void win_get_region_noframe_local(const win *w, region_t *res) { void win_get_region_noframe_local(const win *w, region_t *res) {
const margin_t extents = win_calc_frame_extents(w); const margin_t extents = win_calc_frame_extents(w);
int x = extents.left; int x = (int)extents.left;
int y = extents.top; int y = (int)extents.top;
int width = max_i(w->g.width - extents.left - extents.right, 0); int width = max2(w->g.width - (int)(extents.left + extents.right), 0);
int height = max_i(w->g.height - extents.top - extents.bottom, 0); int height = max2(w->g.height - (int)(extents.top + extents.bottom), 0);
pixman_region32_fini(res); pixman_region32_fini(res);
if (width > 0 && height > 0) if (width > 0 && height > 0) {
pixman_region32_init_rect(res, x, y, width, height); pixman_region32_init_rect(res, x, y, (uint)width, (uint)height);
}
} }
gen_by_val(win_get_region_noframe_local); gen_by_val(win_get_region_noframe_local);
@ -139,13 +141,13 @@ void win_get_region_frame_local(const win *w, region_t *res) {
res, res,
(rect_t[]){ (rect_t[]){
// top // top
{.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = extents.top}, {.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = (int)extents.top},
// bottom // bottom
{.x1 = 0, .y1 = w->g.height - extents.bottom, .x2 = w->g.width, .y2 = w->g.height}, {.x1 = 0, .y1 = (int)(w->g.height - extents.bottom), .x2 = w->g.width, .y2 = w->g.height},
// left // left
{.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height}, {.x1 = 0, .y1 = 0, .x2 = (int)extents.left, .y2 = w->g.height},
// right // right
{.x1 = w->g.width - extents.right, .y1 = 0, .x2 = w->g.width, .y2 = w->g.height}, {.x1 = (int)(w->g.width - extents.right), .y1 = 0, .x2 = w->g.width, .y2 = w->g.height},
}, },
4); 4);
@ -208,8 +210,9 @@ _win_bind_image(session_t *ps, win *w, void **win_image, void **shadow_image) {
} }
if (w->shadow) { if (w->shadow) {
*shadow_image = ps->backend_data->ops->render_shadow( *shadow_image = ps->backend_data->ops->render_shadow(
ps->backend_data, w->widthb, w->heightb, ps->gaussian_map, ps->o.shadow_red, ps->backend_data, w->widthb, w->heightb, ps->gaussian_map,
ps->o.shadow_green, ps->o.shadow_blue, ps->o.shadow_opacity); ps->o.shadow_red, ps->o.shadow_green, ps->o.shadow_blue,
ps->o.shadow_opacity);
if (!*shadow_image) { if (!*shadow_image) {
log_error("Failed to bind shadow image"); log_error("Failed to bind shadow image");
ps->backend_data->ops->release_image(ps->backend_data, *win_image); ps->backend_data->ops->release_image(ps->backend_data, *win_image);
@ -249,10 +252,10 @@ static bool attr_pure win_has_rounded_corners(const win *w) {
// Determine the minimum width/height of a rectangle that could mark // Determine the minimum width/height of a rectangle that could mark
// a window as having rounded corners // a window as having rounded corners
unsigned short minwidth = auto minwidth =
max_i(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS); (uint16_t)max2(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS);
unsigned short minheight = auto minheight =
max_i(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS); (uint16_t)max2(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS);
// Get the rectangles in the bounding region // Get the rectangles in the bounding region
int nrects = 0; int nrects = 0;
@ -461,7 +464,7 @@ bool win_should_dim(session_t *ps, const win *w) {
return false; return false;
} }
if (ps->o.inactive_dim && !(w->focused)) { if (ps->o.inactive_dim > 0 && !(w->focused)) {
return true; return true;
} else { } else {
return false; return false;
@ -644,7 +647,7 @@ void win_update_opacity_rule(session_t *ps, win *w) {
if (!is_set) if (!is_set)
wid_rm_opacity_prop(ps, w->id); wid_rm_opacity_prop(ps, w->id);
else else
wid_set_opacity_prop(ps, w->id, opacity * OPAQUE); wid_set_opacity_prop(ps, w->id, (opacity_t)(opacity * OPAQUE));
} }
/** /**
@ -1241,12 +1244,14 @@ void win_set_focused(session_t *ps, win *w, bool focused) {
*/ */
void win_extents(const win *w, region_t *res) { void win_extents(const win *w, region_t *res) {
pixman_region32_clear(res); pixman_region32_clear(res);
pixman_region32_union_rect(res, res, w->g.x, w->g.y, w->widthb, w->heightb); pixman_region32_union_rect(res, res, w->g.x, w->g.y, (uint)w->widthb, (uint)w->heightb);
if (w->shadow) if (w->shadow) {
assert(w->shadow_width >= 0 && w->shadow_height >= 0);
pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx, pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx,
w->g.y + w->shadow_dy, w->shadow_width, w->g.y + w->shadow_dy, (uint)w->shadow_width,
w->shadow_height); (uint)w->shadow_height);
}
} }
gen_by_val(win_extents); gen_by_val(win_extents);

View File

@ -425,10 +425,10 @@ static inline region_t win_get_bounding_shape_global_by_val(win *w) {
*/ */
static inline margin_t attr_pure win_calc_frame_extents(const win *w) { static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
margin_t result = w->frame_extents; margin_t result = w->frame_extents;
result.top = max_i(result.top, w->g.border_width); result.top = max2(result.top, w->g.border_width);
result.left = max_i(result.left, w->g.border_width); result.left = max2(result.left, w->g.border_width);
result.bottom = max_i(result.bottom, w->g.border_width); result.bottom = max2(result.bottom, w->g.border_width);
result.right = max_i(result.right, w->g.border_width); result.right = max2(result.right, w->g.border_width);
return result; return result;
} }

79
src/x.c
View File

@ -38,18 +38,21 @@
* and number of items. A blank one on failure. * and number of items. A blank one on failure.
*/ */
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
long offset, long length, xcb_atom_t rtype, int rformat) { int offset, int length, xcb_atom_t rtype, int rformat) {
xcb_get_property_reply_t *r = xcb_get_property_reply( xcb_get_property_reply_t *r = xcb_get_property_reply(
ps->c, xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL); ps->c,
xcb_get_property(ps->c, 0, w, atom, rtype, to_u32_checked(offset),
to_u32_checked(length)),
NULL);
if (r && xcb_get_property_value_length(r) && if (r && xcb_get_property_value_length(r) &&
(rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) && (rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) &&
(!rformat || r->format == rformat) && (!rformat || r->format == rformat) &&
(r->format == 8 || r->format == 16 || r->format == 32)) { (r->format == 8 || r->format == 16 || r->format == 32)) {
int len = xcb_get_property_value_length(r); auto len = xcb_get_property_value_length(r);
return (winprop_t){ return (winprop_t){
.ptr = xcb_get_property_value(r), .ptr = xcb_get_property_value(r),
.nitems = len / (r->format / 8), .nitems = (ulong)(len / (r->format / 8)),
.type = r->type, .type = r->type,
.format = r->format, .format = r->format,
.r = r, .r = r,
@ -73,7 +76,7 @@ xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t apr
// Return it // Return it
if (prop.nitems) { if (prop.nitems) {
p = *prop.p32; p = (xcb_window_t)*prop.p32;
} }
free_winprop(&prop); free_winprop(&prop);
@ -182,7 +185,7 @@ int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c, x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
const xcb_render_pictforminfo_t *pictfmt, const xcb_render_pictforminfo_t *pictfmt,
xcb_pixmap_t pixmap, unsigned long valuemask, xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) { const xcb_render_create_picture_value_list_t *attr) {
void *buf = NULL; void *buf = NULL;
if (attr) { if (attr) {
@ -208,7 +211,7 @@ x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual, x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual,
xcb_pixmap_t pixmap, unsigned long valuemask, xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) { const xcb_render_create_picture_value_list_t *attr) {
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual); const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr); return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
@ -216,7 +219,7 @@ x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visu
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard, x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard,
xcb_pixmap_t pixmap, unsigned long valuemask, xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) { const xcb_render_create_picture_value_list_t *attr) {
x_get_server_pictfmts(c); x_get_server_pictfmts(c);
@ -229,12 +232,12 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard
* Create an picture. * Create an picture.
*/ */
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, int hei, x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) { const xcb_render_create_picture_value_list_t *attr) {
int depth = pictfmt->depth; uint8_t depth = pictfmt->depth;
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, wid, hei); xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, w, h);
if (!tmp_pixmap) if (!tmp_pixmap)
return XCB_NONE; return XCB_NONE;
@ -248,7 +251,7 @@ x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, in
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h, x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
xcb_visualid_t visual, unsigned long valuemask, xcb_visualid_t visual, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) { const xcb_render_create_picture_value_list_t *attr) {
auto pictfmt = x_get_pictform_for_visual(c, visual); auto pictfmt = x_get_pictform_for_visual(c, visual);
return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr); return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
@ -279,21 +282,22 @@ bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_
} }
void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict, void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
int clip_x_origin, int clip_y_origin, const region_t *reg) { int16_t clip_x_origin, int16_t clip_y_origin,
const region_t *reg) {
int nrects; int nrects;
const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects);
auto xrects = ccalloc(nrects, xcb_rectangle_t); auto xrects = ccalloc(nrects, xcb_rectangle_t);
for (int i = 0; i < nrects; i++) for (int i = 0; i < nrects; i++)
xrects[i] = (xcb_rectangle_t){ xrects[i] = (xcb_rectangle_t){
.x = rects[i].x1, .x = to_i16_checked(rects[i].x1),
.y = rects[i].y1, .y = to_i16_checked(rects[i].y1),
.width = rects[i].x2 - rects[i].x1, .width = to_u16_checked(rects[i].x2 - rects[i].x1),
.height = rects[i].y2 - rects[i].y1, .height = to_u16_checked(rects[i].y2 - rects[i].y1),
}; };
xcb_generic_error_t *e = xcb_generic_error_t *e = xcb_request_check(
xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked( c, xcb_render_set_picture_clip_rectangles_checked(
c, pict, clip_x_origin, clip_y_origin, nrects, xrects)); c, pict, clip_x_origin, clip_y_origin, to_u32_checked(nrects), xrects));
if (e) if (e)
log_error("Failed to set clip region"); log_error("Failed to set clip region");
free(e); free(e);
@ -321,7 +325,7 @@ enum { XSyncBadCounter = 0,
* *
* XXX consider making this error to string * XXX consider making this error to string
*/ */
void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) { void x_print_error(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_code) {
session_t *const ps = ps_g; session_t *const ps = ps_g;
int o = 0; int o = 0;
@ -405,10 +409,10 @@ void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t e
* Create a pixmap and check that creation succeeded. * Create a pixmap and check that creation succeeded.
*/ */
xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable,
uint16_t width, uint16_t height) { int width, int height) {
xcb_pixmap_t pix = xcb_generate_id(c); xcb_pixmap_t pix = xcb_generate_id(c);
xcb_void_cookie_t cookie = xcb_void_cookie_t cookie = xcb_create_pixmap_checked(
xcb_create_pixmap_checked(c, depth, pix, drawable, width, height); c, depth, pix, drawable, to_u16_checked(width), to_u16_checked(height));
xcb_generic_error_t *err = xcb_request_check(c, cookie); xcb_generic_error_t *err = xcb_request_check(c, cookie);
if (err == NULL) if (err == NULL)
return pix; return pix;
@ -456,7 +460,7 @@ xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) {
winprop_t prop = winprop_t prop =
wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32); wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32);
if (prop.nitems) { if (prop.nitems) {
pixmap = *prop.p32; pixmap = (xcb_pixmap_t)*prop.p32;
free_winprop(&prop); free_winprop(&prop);
break; break;
} }
@ -523,10 +527,10 @@ bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) {
* @param[inout] size size of the array pointed to by `ret`, in number of elements * @param[inout] size size of the array pointed to by `ret`, in number of elements
* @return number of elements filled into `*ret` * @return number of elements filled into `*ret`
*/ */
size_t x_picture_filter_from_conv(const conv *kernel, double center, int x_picture_filter_from_conv(const conv *kernel, double center,
xcb_render_fixed_t **ret, size_t *size) { xcb_render_fixed_t **ret, size_t *size) {
if (*size < (size_t)(kernel->w * kernel->h + 2)) { if (*size < (size_t)(kernel->w * kernel->h + 2)) {
*size = kernel->w * kernel->h + 2; *size = (size_t)(kernel->w * kernel->h + 2);
*ret = crealloc(*ret, *size); *ret = crealloc(*ret, *size);
} }
auto buf = *ret; auto buf = *ret;
@ -550,18 +554,18 @@ size_t x_picture_filter_from_conv(const conv *kernel, double center,
} }
/// Generate a search criteria for fbconfig from a X visual. /// Generate a search criteria for fbconfig from a X visual.
/// Returns {-1, -1, -1, -1, -1, -1} on failure /// Returns {-1, -1, -1, -1, -1, 0} on failure
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) { struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
auto pictfmt = x_get_pictform_for_visual(c, visual); auto pictfmt = x_get_pictform_for_visual(c, visual);
auto depth = x_get_visual_depth(c, visual); auto depth = x_get_visual_depth(c, visual);
if (!pictfmt || depth == -1) { if (!pictfmt || depth == -1) {
log_error("Invalid visual %#03x", visual); log_error("Invalid visual %#03x", visual);
return (struct xvisual_info){-1, -1, -1, -1, -1, -1}; return (struct xvisual_info){-1, -1, -1, -1, -1, 0};
} }
if (pictfmt->type != XCB_RENDER_PICT_TYPE_DIRECT) { if (pictfmt->type != XCB_RENDER_PICT_TYPE_DIRECT) {
log_error("compton cannot handle non-DirectColor visuals. Report an " log_error("compton cannot handle non-DirectColor visuals. Report an "
"issue if you see this error message."); "issue if you see this error message.");
return (struct xvisual_info){-1, -1, -1, -1, -1, -1}; return (struct xvisual_info){-1, -1, -1, -1, -1, 0};
} }
int red_size = popcountl(pictfmt->direct.red_mask), int red_size = popcountl(pictfmt->direct.red_mask),
@ -578,3 +582,14 @@ struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual
.visual = visual, .visual = visual,
}; };
} }
xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) {
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator(xcb_get_setup(c));
for (; iter.rem; --screen, xcb_screen_next(&iter))
if (screen == 0)
return iter.data;
return NULL;
}

30
src/x.h
View File

@ -88,13 +88,13 @@ static inline void x_sync(xcb_connection_t *c) {
* and number of items. A blank one on failure. * and number of items. A blank one on failure.
*/ */
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
long offset, long length, xcb_atom_t rtype, int rformat); int offset, int length, xcb_atom_t rtype, int rformat);
/** /**
* Wrapper of wid_get_prop_adv(). * Wrapper of wid_get_prop_adv().
*/ */
static inline winprop_t wid_get_prop(const session_t *ps, xcb_window_t wid, xcb_atom_t atom, static inline winprop_t wid_get_prop(const session_t *ps, xcb_window_t wid, xcb_atom_t atom,
long length, xcb_atom_t rtype, int rformat) { int length, xcb_atom_t rtype, int rformat) {
return wid_get_prop_adv(ps, wid, atom, 0L, length, rtype, rformat); return wid_get_prop_adv(ps, wid, atom, 0L, length, rtype, rformat);
} }
@ -118,19 +118,19 @@ int x_get_visual_depth(xcb_connection_t *, xcb_visualid_t);
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *, x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *,
const xcb_render_pictforminfo_t *pictfmt, const xcb_render_pictforminfo_t *pictfmt,
xcb_pixmap_t pixmap, unsigned long valuemask, xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1, 2); attr_nonnull(1, 2);
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_visual_and_pixmap(xcb_connection_t *, xcb_visualid_t visual, x_create_picture_with_visual_and_pixmap(xcb_connection_t *, xcb_visualid_t visual,
xcb_pixmap_t pixmap, unsigned long valuemask, xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1); attr_nonnull(1);
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_t standard, x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_t standard,
xcb_pixmap_t pixmap, unsigned long valuemask, xcb_pixmap_t pixmap, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1); attr_nonnull(1);
@ -138,22 +138,22 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_
* Create an picture. * Create an picture.
*/ */
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei, x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int w, int h,
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1, 5); attr_nonnull(1, 5);
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h, x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h,
xcb_visualid_t visual, unsigned long valuemask, xcb_visualid_t visual, uint32_t valuemask,
const xcb_render_create_picture_value_list_t *attr) const xcb_render_create_picture_value_list_t *attr)
attr_nonnull(1); attr_nonnull(1);
/// Fetch a X region and store it in a pixman region /// Fetch a X region and store it in a pixman region
bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res); bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res);
void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t, void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t, int16_t clip_x_origin,
int clip_x_origin, int clip_y_origin, const region_t *); int16_t clip_y_origin, const region_t *);
void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict); void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict);
@ -162,10 +162,10 @@ void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict);
* *
* XXX consider making this error to string * XXX consider making this error to string
*/ */
void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code); void x_print_error(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_code);
xcb_pixmap_t x_create_pixmap(xcb_connection_t *, uint8_t depth, xcb_drawable_t drawable, xcb_pixmap_t x_create_pixmap(xcb_connection_t *, uint8_t depth, xcb_drawable_t drawable,
uint16_t width, uint16_t height); int width, int height);
bool x_validate_pixmap(xcb_connection_t *, xcb_pixmap_t pxmap); bool x_validate_pixmap(xcb_connection_t *, xcb_pixmap_t pxmap);
@ -202,11 +202,13 @@ bool x_fence_sync(xcb_connection_t *, xcb_sync_fence_t);
* will be allocated, and `*ret` will be updated. * will be allocated, and `*ret` will be updated.
* @param[inout] size size of the array pointed to by `ret`. * @param[inout] size size of the array pointed to by `ret`.
*/ */
size_t x_picture_filter_from_conv(const conv *kernel, double center, int x_picture_filter_from_conv(const conv *kernel, double center,
xcb_render_fixed_t **ret, size_t *size); xcb_render_fixed_t **ret, size_t *size);
/// Generate a search criteria for fbconfig from a X visual. /// Generate a search criteria for fbconfig from a X visual.
/// Returns {-1, -1, -1, -1, -1, -1} on failure /// Returns {-1, -1, -1, -1, -1, -1} on failure
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual); struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std); xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen);