Eliminate implicit conversions

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

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

View File

@ -46,8 +46,8 @@ endif
add_global_arguments('-D_GNU_SOURCE', language: 'c')
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')

View File

@ -39,8 +39,8 @@ region_t get_damage(session_t *ps, bool all_damage) {
pixman_region32_copy(&region, &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(&region, &region, &ps->damage_ring[curr]);
}

View File

@ -38,10 +38,10 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a
return XCB_NONE;
}
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;

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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(&reg);
@ -101,7 +101,8 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, &reg);
xcb_render_composite(base->c, op, img->pict, alpha_pict, xd->back[xd->curr_back],
0, 0, 0, 0, dst_x, dst_y, img->ewidth, img->eheight);
0, 0, 0, 0, to_i16_checked(dst_x), to_i16_checked(dst_y),
to_u16_checked(img->ewidth), to_u16_checked(img->eheight));
pixman_region32_fini(&reg);
}
@ -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(&reg_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(&reg);
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, &reg);
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;

220
src/c2.c
View File

@ -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

View File

@ -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 <code>next</code> 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) {

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -3,6 +3,7 @@
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
@ -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;
}

View File

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

View File

@ -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

View File

@ -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;
}

View File

@ -4,8 +4,8 @@
#include <X11/Xlibint.h>
#include <X11/extensions/sync.h>
#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;

View File

@ -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;

View File

@ -150,11 +150,13 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
va_list args;
va_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 = {

View File

@ -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(&reg_new, dx, dy, width, height); \
assert(width >= 0 && height >= 0); \
pixman_region32_init_rect(&reg_new, dx, dy, (uint)width, (uint)height); \
pixman_region32_intersect(&reg_new, &reg_new, (region_t *)reg_tgt); \
rects = pixman_region32_rectangles(&reg_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,

View File

@ -26,7 +26,7 @@
#include <xcb/render.h>
#include <xcb/xcb.h>
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, int z,
GLfloat factor, const region_t *reg_tgt);
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);

View File

@ -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;
}

View File

@ -42,7 +42,8 @@ static inline rect_t from_x_rect(const xcb_rectangle_t *rect) {
/// Returning an array that needs to be freed
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;
}

View File

@ -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(&region, &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(&region, &region, &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(&region, ps->o.resize_damage);
resize_region(&region, (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(
&reg_tmp, &reg_tmp, w->g.x + w->shadow_dx,
w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height);
&reg_tmp, &reg_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, &region);
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,

View File

@ -2,9 +2,9 @@
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#pragma once
#include <xcb/xcb.h>
#include <xcb/render.h>
#include <stdbool.h>
#include <xcb/render.h>
#include <xcb/xcb.h>
#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);

View File

@ -4,6 +4,8 @@
#include <ctype.h>
#include <stddef.h>
#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;

View File

@ -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;

View File

@ -22,7 +22,7 @@ void report_allocation_failure(const char *func, const char *file, unsigned int
{.iov_base = "at ", .iov_len = 3},
{.iov_base = (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},
};

View File

@ -3,6 +3,7 @@
#pragma once
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
@ -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`
///

View File

@ -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) {

View File

@ -110,8 +110,9 @@ static inline bool group_is_focused(session_t *ps, xcb_window_t leader) {
* Get a rectangular region a window occupies, excluding shadow.
*/
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);

View File

@ -425,10 +425,10 @@ static inline region_t win_get_bounding_shape_global_by_val(win *w) {
*/
static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
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;
}

79
src/x.c
View File

@ -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;
}

30
src/x.h
View File

@ -88,13 +88,13 @@ static inline void x_sync(xcb_connection_t *c) {
* and number of items. A blank one on failure.
*/
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);