diff --git a/.circleci/config.yml b/.circleci/config.yml index 1c859f72..dcd8f587 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,6 +3,8 @@ executors: docker: - image: yshui/comptonci working_directory: "/tmp/workspace" + environment: + UBSAN_OPTIONS: "halt_on_error=1" version: 2.1 commands: diff --git a/meson.build b/meson.build index 2251f40b..6fe5e1b0 100644 --- a/meson.build +++ b/meson.build @@ -46,8 +46,8 @@ endif add_global_arguments('-D_GNU_SOURCE', language: 'c') -warns = [ 'all', 'extra', 'no-unused-parameter', 'nonnull', 'shadow', - 'implicit-fallthrough', 'no-unknown-warning-option', 'no-missing-braces' ] +warns = [ 'all', 'extra', 'no-unused-parameter', 'nonnull', 'shadow', 'no-type-limits', + 'implicit-fallthrough', 'no-unknown-warning-option', 'no-missing-braces', 'conversion' ] foreach w : warns if cc.has_argument('-W'+w) add_global_arguments('-W'+w, language: 'c') diff --git a/src/backend/backend.c b/src/backend/backend.c index a2e612ac..ceba1704 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -39,8 +39,8 @@ region_t get_damage(session_t *ps, bool all_damage) { pixman_region32_copy(®ion, &ps->screen_reg); } else { for (int i = 0; i < buffer_age; i++) { - const int curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage; - log_trace("damage index: %d, damage ring offset: %d", i, curr); + auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage; + log_trace("damage index: %d, damage ring offset: %ld", i, curr); dump_region(&ps->damage_ring[curr]); pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]); } diff --git a/src/backend/backend_common.c b/src/backend/backend_common.c index 644dbe9d..5d7b7b1b 100644 --- a/src/backend/backend_common.c +++ b/src/backend/backend_common.c @@ -38,10 +38,10 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a return XCB_NONE; } - col.alpha = a * 0xffff; - col.red = r * 0xffff; - col.green = g * 0xffff; - col.blue = b * 0xffff; + col.alpha = (uint16_t)(a * 0xffff); + col.red = (uint16_t)(r * 0xffff); + col.green = (uint16_t)(g * 0xffff); + col.blue = (uint16_t)(b * 0xffff); rect.x = 0; rect.y = 0; @@ -74,21 +74,22 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, assert(shadow_sum); // We only support square kernels for shadow 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; assert(d % 2 == 1); assert(d > 0); - ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8, - 0, 0, NULL); + ximage = xcb_image_create_native(c, to_u16_checked(swidth), to_u16_checked(sheight), + XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL); if (!ximage) { log_error("failed to create an X image"); return 0; } 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 (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++) { double sum = sum_kernel_normalized( 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; } if (height < r * 2) { + // Implies width >= r * 2 // If the window height is smaller than the kernel, we divide // the window like this: // -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, d - y - 1, d, height) * 255.0; - data[y * sstride + x] = sum; - data[y * sstride + swidth - x - 1] = sum; + data[y * sstride + x] = (uint8_t)sum; + data[y * sstride + swidth - x - 1] = (uint8_t)sum; } } for (int y = 0; y < sheight; y++) { double sum = 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; } @@ -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, d - y - 1, width, d) * 255.0; - data[y * sstride + x] = sum; - data[(sheight - y - 1) * sstride + x] = sum; + data[y * sstride + x] = (uint8_t)sum; + data[(sheight - y - 1) * sstride + x] = (uint8_t)sum; } } for (int x = 0; x < swidth; x++) { double sum = sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0; for (int y = r * 2; y < height; y++) { - data[y * sstride + x] = sum; + data[y * sstride + x] = (uint8_t)sum; } } return ximage; } + // Implies: width >= r * 2 && height >= r * 2 + // Fill part 3 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 for (int y = 0; y < r * 2; y++) { for (int x = 0; x < r * 2; x++) { double tmpsum = shadow_sum[y * d + x] * opacity * 255.0; - data[y * sstride + x] = tmpsum; - data[(sheight - y - 1) * sstride + x] = tmpsum; - data[(sheight - y - 1) * sstride + (swidth - x - 1)] = tmpsum; - data[y * sstride + (swidth - x - 1)] = tmpsum; + data[y * sstride + x] = (uint8_t)tmpsum; + data[(sheight - y - 1) * sstride + x] = (uint8_t)tmpsum; + data[(sheight - y - 1) * sstride + (swidth - x - 1)] = (uint8_t)tmpsum; + data[y * sstride + (swidth - x - 1)] = (uint8_t)tmpsum; } } // Part 2, top/bottom for (int y = 0; y < r * 2; y++) { double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0; - memset(&data[y * sstride + r * 2], tmpsum, width - r * 2); - memset(&data[(sheight - y - 1) * 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], (uint8_t)tmpsum, + (size_t)(width - r * 2)); } // Part 2, left/right for (int x = 0; x < r * 2; x++) { double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0; for (int y = r * 2; y < height; y++) { - data[y * sstride + x] = tmpsum; - data[y * sstride + (swidth - x - 1)] = tmpsum; + data[y * sstride + x] = (uint8_t)tmpsum; + data[y * sstride + (swidth - x - 1)] = (uint8_t)tmpsum; } } @@ -256,8 +262,9 @@ shadow_picture_err: return false; } -void *default_backend_render_shadow(backend_t *backend_data, int width, int height, - const conv *kernel, double r, double g, double b, double a) { +void * +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, true, 1, r, g, b), shadow = XCB_NONE; diff --git a/src/backend/backend_common.h b/src/backend/backend_common.h index d0e9136e..40fdf488 100644 --- a/src/backend/backend_common.h +++ b/src/backend/backend_common.h @@ -12,16 +12,17 @@ typedef struct session session_t; typedef struct win win; typedef struct conv conv; +typedef struct backend_base backend_t; -bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, const int width, - const int height, const conv *kernel, xcb_render_picture_t shadow_pixel, +bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, int width, + int height, const conv *kernel, xcb_render_picture_t shadow_pixel, xcb_pixmap_t *pixmap, xcb_render_picture_t *pict); xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb, double a, double r, double g, double b); -xcb_image_t * -make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height); +xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, + int width, int height); /// 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 @@ -31,5 +32,6 @@ bool default_is_win_transparent(void *, win *, void *); /// caveat as `default_is_win_transparent` applies. bool default_is_frame_transparent(void *, win *, void *); -void *default_backend_render_shadow(backend_t *backend_data, int width, int height, - const conv *kernel, double r, double g, double b, double a); +void * +default_backend_render_shadow(backend_t *backend_data, int width, int height, + const conv *kernel, double r, double g, double b, double a); diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 6e8b788e..8cc91c89 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -119,14 +119,16 @@ GLuint gl_create_program_from_str(const char *vert_shader_str, const char *frag_ { GLuint shaders[2]; - unsigned int count = 0; - if (vert_shader) + int count = 0; + if (vert_shader) { shaders[count++] = vert_shader; - if (frag_shader) + } + if (frag_shader) { shaders[count++] = frag_shader; - assert(count <= sizeof(shaders) / sizeof(shaders[0])); - if (count) + } + if (count) { prog = gl_create_program(shaders, count); + } } 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) { glUseProgram(gd->win_shader.prog); 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) { 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); } 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 // (texture_x1, texture_y1), texture coord for the _bottom left_ corner - GLfloat texture_x1 = crect.x1 - dst_x; - GLfloat texture_y1 = crect.y2 - dst_y2; - GLfloat texture_x2 = texture_x1 + crect.x2 - crect.x1; - GLfloat texture_y2 = texture_y1 + crect.y1 - crect.y2; + auto texture_x1 = (GLfloat)(crect.x1 - dst_x); + auto texture_y1 = (GLfloat)(crect.y2 - dst_y2); + auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1); + auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2); // X pixmaps might be Y inverted, invert the texture coordinates if (ptex->y_inverted) { - texture_y1 = ptex->height - texture_y1; - texture_y2 = ptex->height - texture_y2; + texture_y1 = (GLfloat)ptex->height - texture_y1; + texture_y2 = (GLfloat)ptex->height - texture_y2; } // GL_TEXTURE_2D coordinates are normalized // TODO use texelFetch - texture_x1 /= ptex->width; - texture_y1 /= ptex->height; - texture_x2 /= ptex->width; - texture_y2 /= ptex->height; + texture_x1 /= (GLfloat)ptex->width; + texture_y1 /= (GLfloat)ptex->height; + texture_x2 /= (GLfloat)ptex->width; + texture_y2 /= (GLfloat)ptex->height; // Vertex coordinates 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 glBindFramebuffer(GL_FRAMEBUFFER, 0); 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_y, 1.0 / gd->height); + glUniform1f(p->unifm_offset_x, 1.0f / (GLfloat)gd->width); + glUniform1f(p->unifm_offset_y, 1.0f / (GLfloat)gd->height); // XXX use multiple draw calls is probably going to be slow than // 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; // Texture coordinates - GLfloat texture_x1 = (crect.x1 - extent->x1); - GLfloat texture_y1 = (crect.y2 - dst_y); - GLfloat texture_x2 = texture_x1 + (crect.x2 - crect.x1); - GLfloat texture_y2 = texture_y1 + (crect.y1 - crect.y2); + auto texture_x1 = (GLfloat)(crect.x1 - extent->x1); + auto texture_y1 = (GLfloat)(crect.y2 - dst_y); + auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1); + auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2); - texture_x1 /= gd->width; - texture_x2 /= gd->width; - texture_y1 /= gd->height; - texture_y2 /= gd->height; + texture_x1 /= (GLfloat)gd->width; + texture_x2 /= (GLfloat)gd->width; + texture_y1 /= (GLfloat)gd->height; + texture_y2 /= (GLfloat)gd->height; // Vertex coordinates // For passes before the last one, we are drawing into a buffer, // so (dx, dy) from source maps to (0, 0) - GLfloat vx1 = crect.x1 - extent->x1; - GLfloat vy1 = crect.y2 - dst_y; + GLint vx1 = crect.x1 - extent->x1; + GLint vy1 = crect.y2 - dst_y; if (i == gd->npasses - 1) { // For last pass, we are drawing back to source, so we // don't need to map vx1 = crect.x1; vy1 = crect.y2; } - GLfloat vx2 = vx1 + (crect.x2 - crect.x1); - GLfloat vy2 = vy1 + (crect.y1 - crect.y2); + GLint vx2 = vx1 + (crect.x2 - crect.x1); + GLint vy2 = vy1 + (crect.y1 - crect.y2); GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1}; GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2}; @@ -406,7 +408,7 @@ end: return ret; } -static GLuint glGetUniformLocationChecked(GLuint p, const char *name) { +static GLint glGetUniformLocationChecked(GLuint p, const char *name) { auto ret = glGetUniformLocation(p, name); if (ret < 0) { 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; const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects); struct gl_data *gd = (void *)base; - glColor4f(r, g, b, a); + glColor4d(r, g, b, a); glBegin(GL_QUADS); for (int i = 0; i < nrects; i++) { - glVertex2f(rect[i].x1, gd->height - rect[i].y2); - glVertex2f(rect[i].x2, gd->height - rect[i].y2); - glVertex2f(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].y2); + glVertex2i(rect[i].x2, gd->height - rect[i].y2); + glVertex2i(rect[i].x2, gd->height - rect[i].y1); + glVertex2i(rect[i].x1, gd->height - rect[i].y1); } glEnd(); } @@ -524,7 +526,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { // Build shader int width = kern->w, height = kern->h; 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 *pc = shader_body; @@ -541,7 +543,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { continue; } 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, j - height / 2); 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 */ + 1 /* null terminator */; 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); - assert(real_shader_len < shader_len); + assert(real_shader_len >= 0); + assert((size_t)real_shader_len < shader_len); free(shader_body); // Build program diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 03ad3535..2ada4dba 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -162,7 +162,7 @@ static inline bool gl_has_extension(const char *ext) { } 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) return true; } diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index 782fb4b9..ebcc73ca 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -44,7 +44,7 @@ struct _glx_data { struct gl_data gl; Display *display; int screen; - int target_win; + xcb_window_t target_win; int glx_event; int glx_error; 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_X_VISUAL_TYPE, GLX_TRUE_COLOR, 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 + m.blue_size + m.alpha_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; glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual); 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 // different depth. // @@ -347,6 +348,11 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b 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); if (!r) { 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 wd->texture.texture = gl_new_texture(GL_TEXTURE_2D); 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.dim = 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; } - long inlen = strlen(ext); + auto inlen = strlen(ext); const char *curr = glx_exts; bool match = false; while (curr && !match) { @@ -483,9 +489,9 @@ static inline bool glx_has_extension(Display *dpy, int screen, const char *ext) if (!end) { // Last extension string match = strcmp(ext, curr) == 0; - } else if (end - curr == inlen) { + } else if (curr + inlen == end) { // 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; } diff --git a/src/backend/xrender.c b/src/backend/xrender.c index 4b67aec6..193f26d3 100644 --- a/src/backend/xrender.c +++ b/src/backend/xrender.c @@ -64,7 +64,7 @@ typedef struct _xrender_data { /// Blur kernels converted to X format xcb_render_fixed_t *x_blur_kern[MAX_BLUR_PASS]; /// 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; } xrender_data; @@ -75,9 +75,9 @@ struct _xrender_image_data { xcb_pixmap_t pixmap; // A Picture links to the Pixmap xcb_render_picture_t pict; - long width, height; + int width, height; // The effective size of the image - long ewidth, eheight; + int ewidth, eheight; bool has_alpha; double opacity; 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) { struct _xrender_data *xd = (void *)base; 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)]; region_t reg; pixman_region32_init(®); @@ -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, ®); 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(®); } @@ -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 xcb_render_fill_rectangles( base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back], - (xcb_render_color_t){ - .red = r * 0xffff, .green = g * 0xffff, .blue = b * 0xffff, .alpha = a * 0xffff}, + (xcb_render_color_t){.red = (uint16_t)(r * 0xffff), + .green = (uint16_t)(g * 0xffff), + .blue = (uint16_t)(b * 0xffff), + .alpha = (uint16_t)(a * 0xffff)}, 1, - (xcb_rectangle_t[]){{.x = extent->x1, - .y = extent->y1, - .width = extent->x2 - extent->x1, - .height = extent->y2 - extent->y1}}); + (xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1), + .y = to_i16_checked(extent->y1), + .width = to_u16_checked(extent->x2 - extent->x1), + .height = to_u16_checked(extent->y2 - extent->y1)}}); } 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(®_op); - const int height = extent->y2 - extent->y1; - const int width = extent->x2 - extent->x1; - int src_x = extent->x1, src_y = extent->y1; + const auto height = to_u16_checked(extent->y2 - extent->y1); + const auto width = to_u16_checked(extent->x2 - extent->x1); + 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 *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 // window. // TODO cache converted blur_kerns - xcb_render_set_picture_filter(c, src_pict, strlen(filter), filter, - xd->x_blur_kern_size[i], xd->x_blur_kern[i]); + xcb_render_set_picture_filter( + 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) { // 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 - 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]; 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 if (i == 1) { xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict, - xd->back[xd->curr_back], 0, 0, 0, 0, extent->x1, - extent->y1, width, height); + xd->back[xd->curr_back], 0, 0, 0, 0, + to_i16_checked(extent->x1), + to_i16_checked(extent->y1), width, height); } 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); - img->depth = fmt.visual_depth; + img->depth = (uint8_t)fmt.visual_depth; img->width = img->ewidth = r->width; img->height = img->eheight = r->height; img->pixmap = pixmap; @@ -328,7 +335,8 @@ static void present(backend_t *base) { // but that will require a different backend API xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, 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; } } @@ -358,6 +366,8 @@ static bool image_op(backend_t *base, enum image_operations op, void *image, pixman_region32_init(®); + const auto tmpw = to_u16_checked(img->width); + const auto tmph = to_u16_checked(img->height); switch (op) { case IMAGE_OP_INVERT_COLOR_ALL: 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, img->height, img->visual, 0, NULL); xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict, - XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, - img->width, img->height); + XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph); xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE, 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 // alpha. There could be a better solution. xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN_REVERSE, 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); } else { xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE, xd->white_pixel, XCB_NONE, img->pict, 0, 0, - 0, 0, 0, 0, img->width, img->height); + 0, 0, 0, 0, tmpw, tmph); } break; case IMAGE_OP_DIM_ALL: x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible); 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 xcb_rectangle_t rect = { .x = 0, .y = 0, - .width = img->width, - .height = img->height, + .width = tmpw, + .height = tmph, }; 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)]; x_set_picture_clip_region(base->c, img->pict, 0, 0, ®); 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; break; case IMAGE_OP_RESIZE_TILE: @@ -454,10 +463,11 @@ static void *copy(backend_t *base, const void *image, const region_t *reg) { return NULL; } - auto alpha_pict = + xcb_render_picture_t alpha_pict = 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, - 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; } @@ -526,7 +536,8 @@ backend_t *backend_xrender_init(session_t *ps) { int pixmap_needed = xd->vsync ? 2 : 1; for (int i = 0; i < pixmap_needed; i++) { 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( ps->c, pictfmt, xd->back_pixmap[i], 0, NULL); xd->buffer_age[i] = -1; diff --git a/src/c2.c b/src/c2.c index fae0d26d..b51acf01 100644 --- a/src/c2.c +++ b/src/c2.c @@ -106,8 +106,8 @@ struct _c2_l { xcb_atom_t tgtatom; bool tgt_onframe; int index; - enum { C2_L_PUNDEFINED, - C2_L_PID, + enum { C2_L_PUNDEFINED = -1, + C2_L_PID = 0, C2_L_PX, C2_L_PY, 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 - unsigned tgtlen = 0; + int tgtlen = 0; for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]); ++offset) { ++tgtlen; } - if (!tgtlen) + if (!tgtlen) { c2_error("Empty target."); - pleaf->tgt = strndup(&pattern[offset - tgtlen], tgtlen); + } + pleaf->tgt = strndup(&pattern[offset - tgtlen], (size_t)tgtlen); // 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)) { pleaf->predef = i; 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(); // 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(); - int index = -1; + long index = -1; char *endptr = NULL; index = strtol(pattern + offset, &endptr, 0); - if (!endptr || pattern + offset == endptr) + if (!endptr || pattern + offset == endptr) { c2_error("No index number found after bracket."); - - if (index < 0) + } + if (index < 0) { c2_error("Index number invalid."); - - if (pleaf->predef) + } + if (pleaf->predef != C2_L_PUNDEFINED) { c2_error("Predefined targets can't have index."); + } - pleaf->index = index; - offset = endptr - pattern; + pleaf->index = to_int_checked(index); + offset = to_int_checked(endptr - pattern); C2H_SKIP_SPACES(); - if (']' != pattern[offset]) + if (pattern[offset] != ']') { c2_error("Index end marker not found."); + } ++offset; @@ -641,44 +626,43 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) { // Look for format bool hasformat = false; - int format = 0; + long format = 0; { char *endptr = NULL; format = strtol(pattern + offset, &endptr, 0); assert(endptr); - if ((hasformat = (endptr && endptr != pattern + offset))) - offset = endptr - pattern; + if ((hasformat = (endptr && endptr != pattern + offset))) { + offset = to_int_checked(endptr - pattern); + } C2H_SKIP_SPACES(); } // Look for type enum c2_l_type type = C2_L_TUNDEFINED; - { - switch (pattern[offset]) { - case 'w': type = C2_L_TWINDOW; break; - case 'd': type = C2_L_TDRAWABLE; break; - case 'c': type = C2_L_TCARDINAL; break; - case 's': type = C2_L_TSTRING; break; - case 'a': type = C2_L_TATOM; break; - 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(); + switch (pattern[offset]) { + case 'w': type = C2_L_TWINDOW; break; + case 'd': type = C2_L_TDRAWABLE; break; + case 'c': type = C2_L_TCARDINAL; break; + case 's': type = C2_L_TSTRING; break; + case 'a': type = C2_L_TATOM; break; + default: c2_error("Invalid type character."); } + 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 if (!pleaf->format) { switch (pleaf->type) { @@ -692,20 +676,20 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) { // Write format if (hasformat) { - if (pleaf->predef) - log_warn("Format \"%d\" specified on a default target " + if (pleaf->predef != C2_L_PUNDEFINED) { + log_warn("Format \"%ld\" specified on a default target " "will be ignored.", format); - else if (C2_L_TSTRING == pleaf->type) - log_warn("Format \"%d\" specified on a string target " + } else if (pleaf->type == C2_L_TSTRING) { + log_warn("Format \"%ld\" specified on a string target " "will be ignored.", format); - else { + } else { if (pleaf->format && pleaf->format != format) log_warn("Default format %d overridden on " "target.", 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; // Exists operator cannot have pattern - if (!pleaf->op) + if (!pleaf->op) { return offset; + } C2H_SKIP_SPACES(); char *endptr = NULL; - // Check for boolean patterns if (!strcmp_wd("true", &pattern[offset])) { pleaf->ptntype = C2_L_PTINT; pleaf->ptnint = true; - offset += strlen("true"); + offset += 4; // length of "true"; } else if (!strcmp_wd("false", &pattern[offset])) { pleaf->ptntype = C2_L_PTINT; pleaf->ptnint = false; - offset += strlen("false"); - } - // Check for integer patterns - else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0), - pattern + offset != endptr) { + offset += 5; // length of "false"; + } else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0), + pattern + offset != endptr) { 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 - if (isalnum(pattern[offset])) + if (isalnum(pattern[offset])) { c2_error("Trailing characters after a numeric pattern."); - } - // Check for string patterns - else { + } + } else { + // Parse string patterns bool raw = false; char delim = '\0'; // String flags - if ('r' == tolower(pattern[offset])) { + if (tolower(pattern[offset]) == 'r') { raw = true; ++offset; C2H_SKIP_SPACES(); } // Check for delimiters - if ('\"' == pattern[offset] || '\'' == pattern[offset]) { + if (pattern[offset] == '\"' || pattern[offset] == '\'') { pleaf->ptntype = C2_L_PTSTRING; delim = pattern[offset]; ++offset; } - if (C2_L_PTSTRING != pleaf->ptntype) + if (pleaf->ptntype != C2_L_PTSTRING) { c2_error("Invalid pattern type."); + } // Parse the string now // 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) c2_error("Invalid octal/hex escape " "sequence."); - assert(val < 256 && val >= 0); - *(ptptnstr++) = val; + *(ptptnstr++) = to_char_checked(val); offset += 2; break; } @@ -929,10 +911,10 @@ fail: * Parse a condition with legacy syntax. */ static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) { - unsigned plen = strlen(pattern + offset); - - if (plen < 4 || ':' != pattern[offset + 1] || !strchr(pattern + offset + 2, ':')) + if (strlen(pattern + offset) < 4 || pattern[offset + 1] != ':' || + !strchr(pattern + offset + 2, ':')) { c2_error("Legacy parser: Invalid format."); + } // Allocate memory for new leaf 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 - if (!pleaf->predef) { + if (pleaf->predef == C2_L_PUNDEFINED) { pleaf->tgtatom = get_atom(ps, pleaf->tgt); if (!pleaf->tgtatom) { 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 // TODO: Add track_leader - if (pleaf->predef) { - switch (pleaf->predef) { - case C2_L_PFOCUSED: ps->o.track_focus = true; break; - // case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break; - case C2_L_PNAME: - case C2_L_PCLASSG: - case C2_L_PCLASSI: - case C2_L_PROLE: ps->o.track_wdata = true; break; - default: break; - } + switch (pleaf->predef) { + case C2_L_PFOCUSED: ps->o.track_focus = true; break; + // case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break; + case C2_L_PNAME: + case C2_L_PCLASSG: + case C2_L_PCLASSI: + case C2_L_PROLE: ps->o.track_wdata = true; break; + default: break; } // 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) { if (islower(*pc)) { 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. */ 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; - else + } else { 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); // Return if wid is missing - if (!pleaf->predef && !wid) + if (pleaf->predef == C2_L_PUNDEFINED && !wid) { return; + } 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 // A predefined target - if (pleaf->predef) { + if (pleaf->predef != C2_L_PUNDEFINED) { *perr = false; switch (pleaf->predef) { 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 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_OGT: *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; // A predefined target - if (pleaf->predef) { + if (pleaf->predef != C2_L_PUNDEFINED) { switch (pleaf->predef) { case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; 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; default: assert(0); break; } - } - // If it's an atom type property, convert atom to string - else if (C2_L_TATOM == pleaf->type) { + } else if (pleaf->type == C2_L_TATOM) { + // An atom type property, convert it to string winprop_t prop = wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L, 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) { xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply( ps->c, xcb_get_atom_name(ps->c, atom), NULL); if (reply) { - tgt_free = - strndup(xcb_get_atom_name_name(reply), - xcb_get_atom_name_name_length(reply)); + tgt_free = strndup( + xcb_get_atom_name_name(reply), + (size_t)xcb_get_atom_name_name_length(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; } free_winprop(&prop); - } - // Otherwise, just fetch the string list - else { + } else { + // Not an atom type, just fetch the string list char **strlst = NULL; int 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; case C2_L_MPCRE: #ifdef CONFIG_REGEX_PCRE - *pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra, - tgt, strlen(tgt), 0, 0, NULL, 0) >= 0); + assert(strlen(tgt) <= INT_MAX); + *pres = + (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra, + tgt, (int)strlen(tgt), 0, 0, NULL, 0) >= 0); #else assert(0); #endif diff --git a/src/common.h b/src/common.h index 997f6379..407d0bb9 100644 --- a/src/common.h +++ b/src/common.h @@ -186,8 +186,8 @@ struct _glx_texture { GLXPixmap glpixmap; xcb_pixmap_t pixmap; GLenum target; - unsigned width; - unsigned height; + int width; + int height; bool y_inverted; }; @@ -366,7 +366,7 @@ typedef struct session { /// Pre-generated alpha pictures. xcb_render_picture_t *alpha_picts; /// Time of last fading. In milliseconds. - unsigned long fade_time; + long fade_time; /// Head pointer of the error ignore linked list. ignore_t *ignore_head; /// Pointer to the next member of tail element of the error @@ -416,7 +416,7 @@ typedef struct session { // === Software-optimization-related === /// Currently used refresh rate. - short refresh_rate; + int refresh_rate; /// Interval between refresh in nanoseconds. long refresh_intv; /// 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 // truncation problem from long to int. - { - long sec = ms / MS_PER_SEC; - if (ptv->tv_sec > sec) - return 1; - if (ptv->tv_sec < sec) - return -1; + auto sec = (long)(ms / MS_PER_SEC); + if (ptv->tv_sec > sec) { + return 1; + } + if (ptv->tv_sec < sec) { + return -1; } - { - long usec = ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC); - if (ptv->tv_usec > usec) - return 1; - if (ptv->tv_usec < usec) - return -1; + auto usec = (long)(ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC)); + if (ptv->tv_usec > usec) { + return 1; + } + if (ptv->tv_usec < usec) { + return -1; } 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) { 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; if (reply) { diff --git a/src/compiler.h b/src/compiler.h index b44562b2..e26736fb 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -95,3 +95,6 @@ #else # define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__ #endif + +typedef unsigned long ulong; +typedef unsigned int uint; diff --git a/src/compton.c b/src/compton.c index 3565284d..a4e3ce3a 100644 --- a/src/compton.c +++ b/src/compton.c @@ -108,10 +108,10 @@ static inline void free_xinerama_info(session_t *ps) { /** * 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; 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 @@ -202,11 +202,11 @@ static double fade_timeout(session_t *ps) { if (ps->o.fade_delta + ps->fade_time < now) 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 * @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; if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { // We are not fading @@ -237,11 +237,11 @@ static bool run_fade(session_t *ps, win **_w, unsigned steps) { if (steps) { if (w->opacity < w->opacity_tgt) { - w->opacity = normalize_d_range( - w->opacity + ps->o.fade_in_step * steps, 0.0, w->opacity_tgt); + w->opacity = clamp(w->opacity + ps->o.fade_in_step * (double)steps, + 0.0, w->opacity_tgt); } else { - w->opacity = normalize_d_range( - w->opacity - ps->o.fade_out_step * steps, w->opacity_tgt, 1); + w->opacity = clamp(w->opacity - ps->o.fade_out_step * (double)steps, + 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. */ -long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { - long evmask = 0; +uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { + uint32_t evmask = 0; win *w = NULL; // 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 if (WIN_EVMODE_CLIENT == mode || ((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) evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; } @@ -412,7 +412,7 @@ static void handle_root_flags(session_t *ps) { "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; // Fading step calculation - unsigned long steps = 0L; + long steps = 0L; auto now = get_time_ms(); if (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) redir_stop(ps); else if (!ev_is_active(&ps->unredir_timer)) { - ev_timer_set(&ps->unredir_timer, - ps->o.unredir_if_possible_delay / 1000.0, 0); + ev_timer_set( + &ps->unredir_timer, + (double)ps->o.unredir_if_possible_delay / 1000.0, 0); 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) { assert(!ps->reg_win); - ps->reg_win = - XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, XCB_NONE, XCB_NONE); + ps->reg_win = xcb_generate_id(ps->c); + 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."); + free(e); return false; } @@ -1092,7 +1096,7 @@ static bool register_cm(session_t *ps) { // Set _NET_WM_PID { - uint32_t pid = getpid(); + auto pid = getpid(); xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, &pid); @@ -1108,7 +1112,7 @@ static bool register_cm(session_t *ps) { if (!ps->o.no_x_selection) { unsigned len = strlen(REGISTER_PROP) + 2; int s = ps->scr; - Atom atom; + xcb_atom_t atom; while (s >= 10) { ++len; @@ -1260,7 +1264,7 @@ static double swopti_handle_timeout(session_t *ps) { return 0; // 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); ps->scr = DefaultScreen(ps->dpy); - ps->root = RootWindow(ps->dpy, ps->scr); - ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr)); - ps->depth = DefaultDepth(ps->dpy, ps->scr); + auto screen = x_screen_of_display(ps->c, 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 // root geometry changes @@ -1786,9 +1793,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy, 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_composite_id); xcb_prefetch_extension_data(ps->c, &xcb_damage_id); diff --git a/src/compton.h b/src/compton.h index 1e3e26aa..a6c47599 100644 --- a/src/compton.h +++ b/src/compton.h @@ -38,7 +38,7 @@ enum root_flags { 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); diff --git a/src/config.c b/src/config.c index fac6795c..89c70d91 100644 --- a/src/config.c +++ b/src/config.c @@ -3,6 +3,7 @@ // Copyright (c) 2013 Richard Grenville #include +#include #include #include #include @@ -42,6 +43,22 @@ bool parse_long(const char *s, long *dest) { 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, * 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))) goto err1; src = pc; - width = val; + width = (int)val; if (src == (pc = parse_readnum(src, &val))) goto err1; src = pc; - height = val; + height = (int)val; // Validate matrix width and height 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"); // Allocate memory - conv *matrix = cvalloc(sizeof(conv) + width * height * sizeof(double)); + conv *matrix = cvalloc(sizeof(conv) + (size_t)(width * height) * sizeof(double)); // Read elements 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) { pixman_region32_clear(dest); - if (!src) + if (!src) { return true; - if (!ps->root_width || !ps->root_height) + } + if (!ps->root_width || !ps->root_height) { 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; char *endptr = NULL; src = skip_space(src); - if (!*src) + if (!*src) { goto parse_geometry_end; + } // Parse width // Must be base 10, because "0x0..." may appear - if (!('+' == *src || '-' == *src)) { + if (*src != '+' && *src != '-') { val = strtol(src, &endptr, 10); assert(endptr); if (src != endptr) { - geom.wid = val; - if (geom.wid < 0) { + if (val < 0) { log_error("Invalid width: %s", src); return false; } + width = val; src = endptr; } src = skip_space(src); } // Parse height - if ('x' == *src) { + if (*src == 'x') { ++src; val = strtol(src, &endptr, 10); assert(endptr); if (src != endptr) { - geom.hei = val; - if (geom.hei < 0) { + if (val < 0) { log_error("Invalid height: %s", src); return false; } + height = val; src = endptr; } src = skip_space(src); } // Parse x - if ('+' == *src || '-' == *src) { + if (*src == '+' || *src == '-') { val = strtol(src, &endptr, 10); if (endptr && src != endptr) { - geom.x = val; - if (*src == '-') - geom.x += ps->root_width - geom.wid; + x = val; + if (*src == '-') { + x += ps->root_width - width; + } src = endptr; } src = skip_space(src); } // Parse y - if ('+' == *src || '-' == *src) { + if (*src == '+' || *src == '-') { val = strtol(src, &endptr, 10); if (endptr && src != endptr) { - geom.y = val; - if (*src == '-') - geom.y += ps->root_height - geom.hei; + y = val; + if (*src == '-') { + y += ps->root_height - height; + } src = endptr; } src = skip_space(src); @@ -351,7 +374,16 @@ bool parse_geometry(session_t *ps, const char *src, region_t *dest) { } 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; } diff --git a/src/config.h b/src/config.h index 4c88ad0b..685bfd9e 100644 --- a/src/config.h +++ b/src/config.h @@ -97,7 +97,7 @@ typedef struct options_t { /// when determining if a window could be unredirected. c2_lptr_t *unredir_if_possible_blacklist; /// Delay before unredirecting screen, in milliseconds. - unsigned long unredir_if_possible_delay; + long unredir_if_possible_delay; /// Forced redirection setting through D-Bus. switch_t redirected_force; /// 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. double fade_out_step; /// Fading time delta. In milliseconds. - unsigned long fade_delta; + int fade_delta; /// Whether to disable fading on window open/close. bool no_fading_openclose; /// 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]; -attr_warn_unused_result bool parse_long(const char *, long *); -attr_warn_unused_result bool parse_blur_kern_lst(const char *, conv **, int, bool *hasneg); -attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *); -attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *); +bool must_use parse_long(const char *, long *); +bool must_use parse_int(const char *, int *); +bool must_use parse_blur_kern_lst(const char *, conv **, int, bool *hasneg); +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. diff --git a/src/config_libconfig.c b/src/config_libconfig.c index 5cbcba7d..ed836357 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -295,7 +295,12 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad // --detect-client-opacity lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity); // --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 if (config_lookup_string(&cfg, "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 lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible); // --unredir-if-possible-delay - if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) - opt->unredir_if_possible_delay = ival; + if (config_lookup_int(&cfg, "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 lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed); // --detect-transient diff --git a/src/dbus.c b/src/dbus.c index 2cdf4659..dc54b3e4 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -41,9 +41,9 @@ typedef uint32_t cdbus_window_t; #define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32 #define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING -typedef uint16_t cdbus_enum_t; -#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16 -#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING +typedef uint32_t cdbus_enum_t; +#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT32 +#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT32_AS_STRING #define CDBUS_SERVICE_NAME "com.github.chjj.compton" #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); } +/** + * 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. */ @@ -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(role, cdbus_reply_string); - cdbus_m_win_get_do(opacity, cdbus_reply_uint32); - cdbus_m_win_get_do(opacity_tgt, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity, cdbus_reply_double); + 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(opacity_prop, cdbus_reply_uint32); 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); if (!strcmp("left_width", target)) { @@ -986,7 +994,7 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { return true; } 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(stoppaint_force, cdbus_reply_enum); 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(fade_delta, cdbus_reply_int32); - cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32); - cdbus_m_opts_get_do(fade_out_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_double); cdbus_m_opts_get_do(no_fading_openclose, 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 if (!strcmp("fade_delta", target)) { - int32_t val = 0.0; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) + int32_t val = 0; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) { 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; } diff --git a/src/event.c b/src/event.c index 417377d1..a196ea47 100644 --- a/src/event.c +++ b/src/event.c @@ -4,8 +4,8 @@ #include #include -#include "compiler.h" #include "common.h" +#include "compiler.h" #include "compton.h" #include "event.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]; switch (ev->response_type & 0x7f) { 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 (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); if (w) { 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_create_region(ps->c, tmp, 0, NULL); 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); 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; diff --git a/src/kernel.c b/src/kernel.c index 07d810c7..5b1e997a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -14,20 +14,10 @@ double sum_kernel(const conv *map, int x, int y, int width, int height) { double ret = 0; // Compute sum of values which are "in range" - int xstart = x, xend = width + x; - if (xstart < 0) { - xstart = 0; - } - 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; - } + int xstart = normalize_i_range(x, 0, map->w), + xend = normalize_i_range(width + x, 0, map->w); + int ystart = normalize_i_range(y, 0, map->h), + yend = normalize_i_range(height + y, 0, map->h); assert(yend >= ystart && xend >= xstart); 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 *c; - int size = r * 2 + 1; + int size = (int)r * 2 + 1; int center = size / 2; 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->rsum = NULL; t = 0.0; diff --git a/src/log.c b/src/log.c index 7a707212..7071d4c6 100644 --- a/src/log.c +++ b/src/log.c @@ -150,11 +150,13 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func, va_list args; va_start(args, fmt); - size_t blen = vasprintf(&buf, fmt, args); + int blen = vasprintf(&buf, fmt, args); va_end(args); - if (!buf) + if (blen < 0 || !buf) { + free(buf); return; + } struct timespec ts; 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); char *time = NULL; - size_t tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000); - if (!time) { + int tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000); + if (tlen < 0 || !time) { free(buf); + free(time); return; } @@ -190,7 +193,7 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func, head->ops->writev( head, (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 = (void *)func, .iov_len = flen}, {.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 *)s, .iov_len = slen}, {.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}}, 11); head = head->next; @@ -329,12 +332,12 @@ struct log_target *stderr_logger_new(void) { /// such as apitrace struct gl_string_marker_logger { 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) { 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 = { diff --git a/src/opengl.c b/src/opengl.c index b29ba72c..65f339d0 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -323,45 +323,42 @@ bool glx_init_blur(session_t *ps) { glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; // Build shader - { - int width = kern->w, height = kern->h; - int nele = width * height - 1; - unsigned int len = - strlen(FRAG_SHADER_BLUR_PREFIX) + - strlen(sampler_type) + strlen(extension) + - (strlen(shader_add) + strlen(texture_func) + 42) * nele + - strlen(FRAG_SHADER_BLUR_SUFFIX) + - strlen(texture_func) + 12 + 1; - char *shader_str = ccalloc(len, char); - char *pc = shader_str; - sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type); - pc += strlen(pc); - assert(strlen(shader_str) < len); + int width = kern->w, height = kern->h; + int nele = width * height - 1; + assert(nele >= 0); + auto len = + strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) + + strlen(extension) + + (strlen(shader_add) + strlen(texture_func) + 42) * (uint)nele + + strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1; + char *shader_str = ccalloc(len, char); + char *pc = shader_str; + sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type); + pc += strlen(pc); + assert(strlen(shader_str) < len); - double sum = 0.0; - for (int j = 0; j < height; ++j) { - for (int k = 0; k < width; ++k) { - if (height / 2 == j && width / 2 == k) - continue; - double val = kern->data[j * width + k]; - if (val == 0) { - continue; - } - sum += val; - sprintf(pc, shader_add, val, texture_func, - k - width / 2, j - height / 2); - pc += strlen(pc); - assert(strlen(shader_str) < len); + double sum = 0.0; + for (int j = 0; j < height; ++j) { + for (int k = 0; k < width; ++k) { + if (height / 2 == j && width / 2 == k) + continue; + double val = kern->data[j * width + k]; + if (val == 0) { + continue; } + 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) { log_error("Failed to create fragment shader %d.", i); 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. */ -bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width, - unsigned height, bool repeat, const struct glx_fbconfig_info *fbcfg) { +bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, int width, + int height, bool repeat, const struct glx_fbconfig_info *fbcfg) { if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID) return true; @@ -480,25 +477,27 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, } // Create GLX pixmap - unsigned depth = 0; + int depth = 0; if (!ptex->glpixmap) { need_release = false; // Retrieve pixmap parameters, if they aren't provided - if (!(width && height)) { - Window rroot = None; - int rx = 0, ry = 0; - unsigned rbdwid = 0; - if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, &width, - &height, &rbdwid, &depth)) { + if (!width || !height) { + auto r = xcb_get_geometry_reply( + ps->c, xcb_get_geometry(ps->c, pixmap), NULL); + if (!r) { log_error("Failed to query info of pixmap %#010x.", pixmap); return false; } - if (depth > OPENGL_MAX_DEPTH) { + if (r->depth > OPENGL_MAX_DEPTH) { log_error("Requested depth %d higher than %d.", depth, OPENGL_MAX_DEPTH); return false; } + depth = r->depth; + width = r->width; + height = r->height; + free(r); } // 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, fbcfg->texture_fmt, GLX_TEXTURE_TARGET_EXT, - tex_tgt, + (GLint)tex_tgt, 0, }; @@ -636,7 +635,8 @@ void glx_set_clip(session_t *ps, const region_t *reg) { region_t reg_new; \ int nrects; \ const rect_t *rects; \ - pixman_region32_init_rect(®_new, dx, dy, width, height); \ + assert(width >= 0 && height >= 0); \ + pixman_region32_init_rect(®_new, dx, dy, (uint)width, (uint)height); \ pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \ rects = pixman_region32_rectangles(®_new, &nrects); \ 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_y += XFIXED_TO_DOUBLE(kern[1]) / 2; } - inc_x = min_i(ps->o.resize_damage, inc_x); - inc_y = min_i(ps->o.resize_damage, inc_y); + inc_x = min2(ps->o.resize_damage, inc_x); + inc_y = min2(ps->o.resize_damage, inc_y); - mdx = max_i(dx - inc_x, 0); - mdy = max_i(dy - inc_y, 0); - int mdx2 = min_i(dx + width + inc_x, ps->root_width), - mdy2 = min_i(dy + height + inc_y, ps->root_height); + mdx = max2(dx - inc_x, 0); + mdy = max2(dy - inc_y, 0); + int mdx2 = min2(dx + width + inc_x, ps->root_width), + mdy2 = min2(dy + height + inc_y, ps->root_height); mwidth = mdx2 - mdx; 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 GLfloat texfac_x = 1.0f, texfac_y = 1.0f; - if (GL_TEXTURE_2D == tex_tgt) { - texfac_x /= mwidth; - texfac_y /= mheight; + if (tex_tgt == GL_TEXTURE_2D) { + texfac_x /= (GLfloat)mwidth; + texfac_y /= (GLfloat)mheight; } // 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) glUniform1f(ppass->unifm_factor_center, factor_center); - { - P_PAINTREG_START(crect) { - const GLfloat rx = (crect.x1 - mdx) * texfac_x; - const GLfloat ry = (mheight - (crect.y1 - mdy)) * texfac_y; - const GLfloat rxe = rx + (crect.x2 - crect.x1) * texfac_x; - const GLfloat rye = ry - (crect.y2 - crect.y1) * texfac_y; - GLfloat rdx = crect.x1 - mdx; - GLfloat rdy = mheight - crect.y1 + mdy; - if (last_pass) { - rdx = crect.x1; - 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_START(crect) { + auto rx = (GLfloat)(crect.x1 - mdx) * texfac_x; + auto ry = (GLfloat)(mheight - (crect.y1 - mdy)) * texfac_y; + auto rxe = rx + (GLfloat)(crect.x2 - crect.x1) * texfac_x; + auto rye = ry - (GLfloat)(crect.y2 - crect.y1) * texfac_y; + auto rdx = (GLfloat)(crect.x1 - mdx); + auto rdy = (GLfloat)(mheight - crect.y1 + mdy); + if (last_pass) { + rdx = (GLfloat)crect.x1; + rdy = (GLfloat)(ps->root_height - crect.y1); } - 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); @@ -880,7 +878,7 @@ glx_blur_dst_end: 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) { // It's possible to dim in glx_render(), but it would be over-complicated // 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); glColor4f(0.0f, 0.0f, 0.0f, factor); - { - P_PAINTREG_START(crect) { - // XXX what does all of these variables mean? - GLint rdx = crect.x1; - GLint rdy = ps->root_height - crect.y1; - GLint rdxe = rdx + (crect.x2 - crect.x1); - GLint rdye = rdy - (crect.y2 - crect.y1); + P_PAINTREG_START(crect) { + // XXX what does all of these variables mean? + GLint rdx = crect.x1; + GLint rdy = ps->root_height - crect.y1; + GLint rdxe = rdx + (crect.x2 - crect.x1); + GLint rdye = rdy - (crect.y2 - crect.y1); - glVertex3i(rdx, rdy, z); - glVertex3i(rdxe, rdy, z); - glVertex3i(rdxe, rdye, z); - glVertex3i(rdx, rdye, z); - } - P_PAINTREG_END(); + glVertex3i(rdx, rdy, z); + glVertex3i(rdxe, rdy, z); + glVertex3i(rdxe, rdye, z); + glVertex3i(rdx, rdye, z); } + P_PAINTREG_END(); glColor4f(0.0f, 0.0f, 0.0f, 0.0f); 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 // we need to use those things to correct it. Thanks to derhass for help. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(opacity, opacity, opacity, opacity); + glColor4d(opacity, opacity, opacity, opacity); } 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); glUseProgram(pprogram->prog); if (pprogram->unifm_opacity >= 0) - glUniform1f(pprogram->unifm_opacity, opacity); + glUniform1f(pprogram->unifm_opacity, (float)opacity); if (pprogram->unifm_invert_color >= 0) glUniform1i(pprogram->unifm_invert_color, neg); 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) { // XXX explain these variables - GLfloat rx = (double)(crect.x1 - dx + x); - GLfloat ry = (double)(crect.y1 - dy + y); - GLfloat rxe = rx + (double)(crect.x2 - crect.x1); - GLfloat rye = ry + (double)(crect.y2 - crect.y1); + auto rx = (GLfloat)(crect.x1 - dx + x); + auto ry = (GLfloat)(crect.y1 - dy + y); + auto rxe = rx + (GLfloat)(crect.x2 - crect.x1); + auto rye = ry + (GLfloat)(crect.y2 - crect.y1); // Rectangle textures have [0-w] [0-h] while 2D texture has [0-1] // [0-1] Thanks to amonakov for pointing out! if (GL_TEXTURE_2D == ptex->target) { - rx = rx / ptex->width; - ry = ry / ptex->height; - rxe = rxe / ptex->width; - rye = rye / ptex->height; + rx = rx / (GLfloat)ptex->width; + ry = ry / (GLfloat)ptex->height; + rxe = rxe / (GLfloat)ptex->width; + rye = rye / (GLfloat)ptex->height; } GLint rdx = crect.x1; 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 // don't have such a FBConfig to test with. if (!ptex->y_inverted) { - ry = 1.0 - ry; - rye = 1.0 - rye; + ry = 1.0f - ry; + rye = 1.0f - rye; } // log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx, diff --git a/src/opengl.h b/src/opengl.h index d01294c6..8c746d35 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -26,7 +26,7 @@ #include #include -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); 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); #endif -bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width, - unsigned height, bool repeat, const struct glx_fbconfig_info *); +bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, int width, + int height, bool repeat, const struct glx_fbconfig_info *); void glx_release_pixmap(session_t *ps, glx_texture_t *ptex); diff --git a/src/options.c b/src/options.c index bf84e802..d9969ef9 100644 --- a/src/options.c +++ b/src/options.c @@ -483,7 +483,6 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable, "open a bug report."; optind = 1; while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) { - long val = 0; switch (o) { #define P_CASEBOOL(idx, option) \ case idx: \ @@ -491,9 +490,15 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable, break #define P_CASELONG(idx, option) \ case idx: \ - if (!parse_long(optarg, &val)) \ + if (!parse_long(optarg, &opt->option)) { \ exit(1); \ - opt->option = val; \ + } \ + break +#define P_CASEINT(idx, option) \ + case idx: \ + if (!parse_int(optarg, &opt->option)) { \ + exit(1); \ + } \ break // clang-format off @@ -511,7 +516,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable, case 320: // These options are handled by get_early_config() break; - P_CASELONG('D', fade_delta); + P_CASEINT('D', fade_delta); case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break; case 'O': opt->fade_out_step = normalize_d(atof(optarg)); 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': fading_enable = true; break; - P_CASELONG('r', shadow_radius); + P_CASEINT('r', shadow_radius); case 'o': opt->shadow_opacity = atof(optarg); break; - P_CASELONG('l', shadow_offset_x); - P_CASELONG('t', shadow_offset_y); + P_CASEINT('l', shadow_offset_x); + P_CASEINT('t', shadow_offset_y); case 'i': opt->inactive_opacity = normalize_d(atof(optarg)); 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(267, detect_rounded_corners); P_CASEBOOL(268, detect_client_opacity); - P_CASELONG(269, refresh_rate); + P_CASEINT(269, refresh_rate); case 270: if (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); exit(1); break; - P_CASELONG(293, benchmark); + P_CASEINT(293, benchmark); case 294: // --benchmark-wid - opt->benchmark_wid = strtol(optarg, NULL, 0); + opt->benchmark_wid = (xcb_window_t)strtol(optarg, NULL, 0); break; case 295: 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)) exit(1); break; - P_CASELONG(302, resize_damage); + P_CASEINT(302, resize_damage); case 303: // --glx-use-gpushader4 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 - opt->fade_delta = max_i(opt->fade_delta, 1); - opt->shadow_radius = max_i(opt->shadow_radius, 0); + opt->fade_delta = max2(opt->fade_delta, 1); + opt->shadow_radius = max2(opt->shadow_radius, 0); opt->shadow_red = normalize_d(opt->shadow_red); opt->shadow_green = normalize_d(opt->shadow_green); 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 // 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; } diff --git a/src/region.h b/src/region.h index cb972d7d..a056c80b 100644 --- a/src/region.h +++ b/src/region.h @@ -42,7 +42,8 @@ static inline rect_t from_x_rect(const xcb_rectangle_t *rect) { /// Returning an array that needs to be freed static inline rect_t *from_x_rects(int nrects, const xcb_rectangle_t *rects) { 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); + } return ret; } diff --git a/src/render.c b/src/render.c index 337c931e..5ddbd686 100644 --- a/src/render.c +++ b/src/render.c @@ -34,9 +34,8 @@ /** * Bind texture in paint_t if we are using GLX backend. */ -static inline bool -paint_bind_tex(session_t *ps, paint_t *ppaint, unsigned wid, unsigned hei, bool repeat, - int depth, xcb_visualid_t visual, bool force) { +static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int hei, + bool repeat, int depth, xcb_visualid_t visual, bool force) { #ifdef CONFIG_OPENGL // XXX This is a mess. But this will go away after the backend refactor. 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) { case BKEND_XRENDER: 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]; if (alpha_step != 0) { - int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC - : XCB_RENDER_PICT_OP_OVER); - xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict, - x, y, 0, 0, dx, dy, wid, hei); + uint8_t op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC + : XCB_RENDER_PICT_OP_OVER); + xcb_render_composite( + 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; } @@ -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 y = w->g.y; - const int wid = w->widthb; - const int hei = w->heightb; + const uint16_t wid = to_u16_checked(w->widthb); + const uint16_t hei = to_u16_checked(w->heightb); 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 { // Painting parameters const margin_t extents = win_calc_frame_extents(w); - const int t = extents.top; - const int l = extents.left; - const int b = extents.bottom; - const int r = extents.right; + const auto t = (int)extents.top; + const auto l = (int)extents.left; + const auto b = (int)extents.bottom; + const auto r = (int)extents.right; #define COMP_BDR(cx, cy, cwid, chei) \ 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; // ctop = checked top // Make sure top margin is smaller than height - int ctop = min_i(body_height, t); + int ctop = min2(body_height, t); if (ctop > 0) COMP_BDR(0, 0, wid, ctop); @@ -348,7 +349,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) { // bottom // cbot = checked bottom // Make sure bottom margin is not too large - int cbot = min_i(body_height, b); + int cbot = min2(body_height, b); if (cbot > 0) 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 int body_width = wid; - int cleft = min_i(body_width, l); + int cleft = min2(body_width, l); if (cleft > 0) 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; // right - int cright = min_i(body_width, r); + int cright = min2(body_width, r); if (cright > 0) 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) { case BKEND_XRENDER: case BKEND_XR_GLX_HYBRID: { - unsigned short cval = 0xffff * dim_opacity; + auto cval = (uint16_t)(0xffff * dim_opacity); // Premultiply 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 = { - .x = x, - .y = y, + .x = to_i16_checked(x), + .y = to_i16_checked(y), .width = wid, .height = hei, }; @@ -418,8 +419,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) { } break; #ifdef CONFIG_OPENGL case BKEND_GLX: - glx_dim_dst(ps, x, y, wid, hei, ps->psglx->z - 0.7, dim_opacity, - reg_paint); + glx_dim_dst(ps, x, y, wid, hei, (int)(ps->psglx->z - 0.7), + (float)dim_opacity, reg_paint); break; #endif default: assert(false); @@ -447,7 +448,7 @@ static bool get_root_tile(session_t *ps) { // Create a pixmap if there isn't any 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) { log_error("Failed to create pixmaps for root tile."); 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 */ -static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wid, - int hei, xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) { +static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, + int16_t y, uint16_t wid, uint16_t hei, + xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) { assert(blur_kerns[0]); // 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); xcb_render_fixed_t *convolution_blur = blur_kerns[i]; // `x / 65536.0` converts from X fixed point to double - int kwid = ((double)convolution_blur[0]) / 65536.0, - khei = ((double)convolution_blur[1]) / 65536.0; + int kwid = (int)((double)convolution_blur[0] / 65536.0), + khei = (int)((double)convolution_blur[1] / 65536.0); bool rd_from_tgt = (tgt_buffer == src_pict); // Copy from source picture to destination. The filter must // be applied on source picture, to get the nearby pixels outside the // window. - xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), - XRFILTER_CONVOLUTION, kwid * khei + 2, - convolution_blur); + xcb_render_set_picture_filter( + ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION, + (uint32_t)(kwid * khei + 2), convolution_blur); xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE, dst_pict, (rd_from_tgt ? x : 0), (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, const region_t *reg_paint) { - const int x = w->g.x; - const int y = w->g.y; - const int wid = w->widthb; - const int hei = w->heightb; + const int16_t x = w->g.x; + const int16_t y = w->g.y; + const auto wid = to_u16_checked(w->widthb); + const auto hei = to_u16_checked(w->heightb); double factor_center = 1.0; // 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 // 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); 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 case BKEND_GLX: // TODO: Handle frame opacity - glx_blur_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5, factor_center, - reg_paint, &w->glx_blur_cache); + glx_blur_dst(ps, x, y, wid, hei, (float)ps->psglx->z - 0.5f, + (float)factor_center, reg_paint, &w->glx_blur_cache); break; #endif default: assert(0); @@ -786,7 +788,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) { pixman_region32_copy(®ion, &ps->screen_reg); } else { 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(®ion, ®ion, &ps->damage_ring[curr]); } } @@ -800,7 +802,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) { #endif if (ps->o.resize_damage > 0) { - resize_region(®ion, ps->o.resize_damage); + resize_region(®ion, (short)ps->o.resize_damage); } // 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 (!ps->tgt_buffer.pixmap) { free_paint(ps, &ps->tgt_buffer); - ps->tgt_buffer.pixmap = x_create_pixmap( - ps->c, ps->depth, ps->root, ps->root_width, ps->root_height); + ps->tgt_buffer.pixmap = + x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root, + ps->root_width, ps->root_height); if (ps->tgt_buffer.pixmap == XCB_NONE) { log_fatal("Failed to allocate a screen-sized pixmap for" "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 // border + assert(w->shadow_width >= 0 && w->shadow_height >= 0); pixman_region32_intersect_rect( - ®_tmp, ®_tmp, w->g.x + w->shadow_dx, - w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height); + ®_tmp, ®_tmp, w->g.x + w->shadow_dx, w->g.y + w->shadow_dy, + (uint)w->shadow_width, (uint)w->shadow_height); // Mask out the body of the window from the shadow if // 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); } + auto rwidth = to_u16_checked(ps->root_width); + auto rheight = to_u16_checked(ps->root_height); switch (ps->o.backend) { case BKEND_XRENDER: if (ps->o.monitor_repaint) { @@ -969,16 +975,16 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) { // to it auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis); 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, - ps->tgt_buffer.pict, XCB_NONE, new_pict, 0, 0, - 0, 0, 0, 0, ps->root_width, ps->root_height); + ps->tgt_buffer.pict, XCB_NONE, new_pict, 0, + 0, 0, 0, 0, 0, rwidth, rheight); // Next, we set the region of paint and highlight it x_set_picture_clip_region(ps->c, new_pict, 0, 0, ®ion); xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture, - ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, 0, - 0, 0, 0, 0, ps->root_width, ps->root_height); + ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, + 0, 0, 0, 0, 0, rwidth, rheight); // Finally, clear clip regions of new_pict and the screen, and put // 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); xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict, 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); } else - xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, - XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0, - ps->root_width, ps->root_height); + xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, + ps->tgt_buffer.pict, XCB_NONE, ps->tgt_picture, + 0, 0, 0, 0, 0, 0, rwidth, rheight); break; #ifdef CONFIG_OPENGL 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 // 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; } else { ps->cshadow_picture = solid_picture(ps->c, ps->root, true, 1, ps->o.shadow_red, diff --git a/src/render.h b/src/render.h index c05845de..430e670d 100644 --- a/src/render.h +++ b/src/render.h @@ -2,9 +2,9 @@ // Copyright (c) Yuxuan Shui #pragma once -#include -#include #include +#include +#include #ifdef CONFIG_OPENGL #include "backend/gl/glx.h" #endif @@ -16,24 +16,20 @@ typedef struct win win; typedef struct session session_t; typedef struct paint { - xcb_pixmap_t pixmap; - xcb_render_picture_t pict; - glx_texture_t *ptex; + xcb_pixmap_t pixmap; + xcb_render_picture_t pict; + glx_texture_t *ptex; #ifdef CONFIG_OPENGL - struct glx_fbconfig_info *fbcfg; + struct glx_fbconfig_info *fbcfg; #endif } paint_t; -void -render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, - double opacity, bool argb, bool neg, - xcb_render_picture_t pict, glx_texture_t *ptex, - 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 render(session_t *ps, int x, int y, int dx, int dy, int w, int h, double opacity, + bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex, + 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 -paint_all(session_t *ps, win * const t, bool ignore_damage); +void paint_all(session_t *ps, win *const t, bool ignore_damage); void free_picture(xcb_connection_t *c, xcb_render_picture_t *p); diff --git a/src/string_utils.h b/src/string_utils.h index 8f40bb12..d49158d2 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -4,6 +4,8 @@ #include #include +#include "compiler.h" + #define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1)) char *mstrjoin(const char *src1, const char *src2); @@ -26,7 +28,7 @@ static inline int uitostr(unsigned int n, char *buf) { int pos = ret; while (pos--) { - buf[pos] = n % 10 + '0'; + buf[pos] = (char)(n % 10 + '0'); n /= 10; } return ret; diff --git a/src/types.h b/src/types.h index eb749f66..f446833f 100644 --- a/src/types.h +++ b/src/types.h @@ -14,14 +14,6 @@ typedef enum { UNSET } 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. typedef struct { unsigned int top; diff --git a/src/utils.c b/src/utils.c index d7e6b6f0..d863c363 100644 --- a/src/utils.c +++ b/src/utils.c @@ -22,7 +22,7 @@ void report_allocation_failure(const char *func, const char *file, unsigned int {.iov_base = "at ", .iov_len = 3}, {.iov_base = (void *)file, .iov_len = strlen(file)}, {.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}, }; diff --git a/src/utils.h b/src/utils.h index 45f39116..1b29c472 100644 --- a/src/utils.h +++ b/src/utils.h @@ -3,6 +3,7 @@ #pragma once #include #include +#include #include #include #include @@ -27,7 +28,7 @@ __attribute__((optimize("-fno-fast-math"))) #endif static inline bool safe_isnan(double a) { - return isnan(a); + return __builtin_isnan(a); } #define CASESTRRET(s) \ @@ -42,13 +43,51 @@ safe_isnan(double a) { } while (0) /// Same as assert, but evaluates the expression even in release builds -#define CHECK(expr) \ +#define CHECK(expr) \ do { \ __auto_type __tmp = (expr); \ assert(__tmp); \ (void)__tmp; \ } 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. * @@ -65,33 +104,11 @@ static inline int attr_const normalize_i_range(int i, int min, int max) { return i; } -/** - * Select the larger integer of two. - */ -static inline int attr_const max_i(int a, int b) { - return (a > b ? a : b); -} +#define min2(a, b) ((a) > (b) ? (b) : (a)) +#define max2(a, b) ((a) > (b) ? (a) : (b)) -/** - * Select the smaller integer of two. - */ -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); -} +/// clamp `val` into interval [min, max] +#define clamp(val, min, max) max2(min2(val, max), min) static inline int attr_const popcountl(unsigned long 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)) /// @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(). -#define crealloc(ptr, nmemb) \ - ((__typeof__(ptr))allocchk(realloc((ptr), (nmemb) * sizeof(*(ptr))))) +#define crealloc(ptr, nmemb) \ + ({ \ + 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` /// diff --git a/src/vsync.c b/src/vsync.c index fba4ebf8..d5a5b8fb 100644 --- a/src/vsync.c +++ b/src/vsync.c @@ -38,7 +38,7 @@ static int vsync_drm_wait(session_t *ps) { do { 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); if (ret) @@ -90,9 +90,9 @@ static bool vsync_opengl_oml_init(session_t *ps) { 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) - return glXSwapIntervalMESA(interval) == 0; + return glXSwapIntervalMESA((uint)interval) == 0; else if (glxext.has_GLX_SGI_swap_control) return glXSwapIntervalSGI(interval) == 0; else if (glxext.has_GLX_EXT_swap_control) { diff --git a/src/win.c b/src/win.c index 14f55a89..c6eab854 100644 --- a/src/win.c +++ b/src/win.c @@ -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. */ 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_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) { const margin_t extents = win_calc_frame_extents(w); - int x = extents.left; - int y = extents.top; - int width = max_i(w->g.width - extents.left - extents.right, 0); - int height = max_i(w->g.height - extents.top - extents.bottom, 0); + int x = (int)extents.left; + int y = (int)extents.top; + int width = max2(w->g.width - (int)(extents.left + extents.right), 0); + int height = max2(w->g.height - (int)(extents.top + extents.bottom), 0); pixman_region32_fini(res); - if (width > 0 && height > 0) - pixman_region32_init_rect(res, x, y, width, height); + if (width > 0 && height > 0) { + pixman_region32_init_rect(res, x, y, (uint)width, (uint)height); + } } 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, (rect_t[]){ // 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 - {.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 - {.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height}, + {.x1 = 0, .y1 = 0, .x2 = (int)extents.left, .y2 = w->g.height}, // 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); @@ -208,8 +210,9 @@ _win_bind_image(session_t *ps, win *w, void **win_image, void **shadow_image) { } if (w->shadow) { *shadow_image = ps->backend_data->ops->render_shadow( - ps->backend_data, w->widthb, w->heightb, ps->gaussian_map, ps->o.shadow_red, - ps->o.shadow_green, ps->o.shadow_blue, ps->o.shadow_opacity); + ps->backend_data, w->widthb, w->heightb, ps->gaussian_map, + ps->o.shadow_red, ps->o.shadow_green, ps->o.shadow_blue, + ps->o.shadow_opacity); if (!*shadow_image) { log_error("Failed to bind shadow 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 // a window as having rounded corners - unsigned short minwidth = - max_i(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS); - unsigned short minheight = - max_i(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS); + auto minwidth = + (uint16_t)max2(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS); + auto minheight = + (uint16_t)max2(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS); // Get the rectangles in the bounding region int nrects = 0; @@ -461,7 +464,7 @@ bool win_should_dim(session_t *ps, const win *w) { return false; } - if (ps->o.inactive_dim && !(w->focused)) { + if (ps->o.inactive_dim > 0 && !(w->focused)) { return true; } else { return false; @@ -644,7 +647,7 @@ void win_update_opacity_rule(session_t *ps, win *w) { if (!is_set) wid_rm_opacity_prop(ps, w->id); 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) { 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, - w->g.y + w->shadow_dy, w->shadow_width, - w->shadow_height); + w->g.y + w->shadow_dy, (uint)w->shadow_width, + (uint)w->shadow_height); + } } gen_by_val(win_extents); diff --git a/src/win.h b/src/win.h index cdab3e60..e0e253d9 100644 --- a/src/win.h +++ b/src/win.h @@ -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) { margin_t result = w->frame_extents; - result.top = max_i(result.top, w->g.border_width); - result.left = max_i(result.left, w->g.border_width); - result.bottom = max_i(result.bottom, w->g.border_width); - result.right = max_i(result.right, w->g.border_width); + result.top = max2(result.top, w->g.border_width); + result.left = max2(result.left, w->g.border_width); + result.bottom = max2(result.bottom, w->g.border_width); + result.right = max2(result.right, w->g.border_width); return result; } diff --git a/src/x.c b/src/x.c index 857dd543..7e79262a 100644 --- a/src/x.c +++ b/src/x.c @@ -38,18 +38,21 @@ * 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, - 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( - 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) && (rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) && (!rformat || r->format == rformat) && (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){ .ptr = xcb_get_property_value(r), - .nitems = len / (r->format / 8), + .nitems = (ulong)(len / (r->format / 8)), .type = r->type, .format = r->format, .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 if (prop.nitems) { - p = *prop.p32; + p = (xcb_window_t)*prop.p32; } free_winprop(&prop); @@ -182,7 +185,7 @@ int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) { xcb_render_picture_t x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c, 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) { void *buf = NULL; if (attr) { @@ -208,7 +211,7 @@ x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c, xcb_render_picture_t 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_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual); 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 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) { 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. */ xcb_render_picture_t -x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, int hei, - const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, +x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int w, int h, + const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask, 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) 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 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) { auto pictfmt = x_get_pictform_for_visual(c, visual); 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, - 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; const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); auto xrects = ccalloc(nrects, xcb_rectangle_t); for (int i = 0; i < nrects; i++) xrects[i] = (xcb_rectangle_t){ - .x = rects[i].x1, - .y = rects[i].y1, - .width = rects[i].x2 - rects[i].x1, - .height = rects[i].y2 - rects[i].y1, + .x = to_i16_checked(rects[i].x1), + .y = to_i16_checked(rects[i].y1), + .width = to_u16_checked(rects[i].x2 - rects[i].x1), + .height = to_u16_checked(rects[i].y2 - rects[i].y1), }; - xcb_generic_error_t *e = - xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked( - c, pict, clip_x_origin, clip_y_origin, nrects, xrects)); + xcb_generic_error_t *e = xcb_request_check( + c, xcb_render_set_picture_clip_rectangles_checked( + c, pict, clip_x_origin, clip_y_origin, to_u32_checked(nrects), xrects)); if (e) log_error("Failed to set clip region"); free(e); @@ -321,7 +325,7 @@ enum { XSyncBadCounter = 0, * * 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; 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. */ 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_void_cookie_t cookie = - xcb_create_pixmap_checked(c, depth, pix, drawable, width, height); + xcb_void_cookie_t cookie = xcb_create_pixmap_checked( + c, depth, pix, drawable, to_u16_checked(width), to_u16_checked(height)); xcb_generic_error_t *err = xcb_request_check(c, cookie); if (err == NULL) return pix; @@ -456,7 +460,7 @@ xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) { winprop_t prop = wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32); if (prop.nitems) { - pixmap = *prop.p32; + pixmap = (xcb_pixmap_t)*prop.p32; free_winprop(&prop); 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 * @return number of elements filled into `*ret` */ -size_t x_picture_filter_from_conv(const conv *kernel, double center, - xcb_render_fixed_t **ret, size_t *size) { +int x_picture_filter_from_conv(const conv *kernel, double center, + xcb_render_fixed_t **ret, size_t *size) { 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); } 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. -/// 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) { auto pictfmt = x_get_pictform_for_visual(c, visual); auto depth = x_get_visual_depth(c, visual); if (!pictfmt || depth == -1) { 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) { log_error("compton cannot handle non-DirectColor visuals. Report an " "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), @@ -578,3 +582,14 @@ struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t 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; +} diff --git a/src/x.h b/src/x.h index 2797e814..275bc56d 100644 --- a/src/x.h +++ b/src/x.h @@ -88,13 +88,13 @@ static inline void x_sync(xcb_connection_t *c) { * 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, - 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(). */ 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); } @@ -118,19 +118,19 @@ int x_get_visual_depth(xcb_connection_t *, xcb_visualid_t); xcb_render_picture_t x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *, 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) attr_nonnull(1, 2); xcb_render_picture_t 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) attr_nonnull(1); xcb_render_picture_t 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) attr_nonnull(1); @@ -138,22 +138,22 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_ * Create an picture. */ xcb_render_picture_t -x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei, - const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, +x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int w, int h, + const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask, const xcb_render_create_picture_value_list_t *attr) attr_nonnull(1, 5); xcb_render_picture_t 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) attr_nonnull(1); /// 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); -void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t, - int clip_x_origin, int clip_y_origin, const region_t *); +void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t, int16_t clip_x_origin, + int16_t clip_y_origin, const region_t *); 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 */ -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, - uint16_t width, uint16_t height); + int width, int height); 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. * @param[inout] size size of the array pointed to by `ret`. */ -size_t x_picture_filter_from_conv(const conv *kernel, double center, - xcb_render_fixed_t **ret, size_t *size); +int x_picture_filter_from_conv(const conv *kernel, double center, + xcb_render_fixed_t **ret, size_t *size); /// Generate a search criteria for fbconfig from a X visual. /// Returns {-1, -1, -1, -1, -1, -1} on failure 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_screen_t *x_screen_of_display(xcb_connection_t *c, int screen);