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:
parent
532a90d573
commit
0037b7e5fb
|
@ -46,8 +46,8 @@ endif
|
||||||
|
|
||||||
add_global_arguments('-D_GNU_SOURCE', language: 'c')
|
add_global_arguments('-D_GNU_SOURCE', language: 'c')
|
||||||
|
|
||||||
warns = [ 'all', 'extra', 'no-unused-parameter', 'nonnull', 'shadow',
|
warns = [ 'all', 'extra', 'no-unused-parameter', 'nonnull', 'shadow', 'no-type-limits',
|
||||||
'implicit-fallthrough', 'no-unknown-warning-option', 'no-missing-braces' ]
|
'implicit-fallthrough', 'no-unknown-warning-option', 'no-missing-braces', 'conversion' ]
|
||||||
foreach w : warns
|
foreach w : warns
|
||||||
if cc.has_argument('-W'+w)
|
if cc.has_argument('-W'+w)
|
||||||
add_global_arguments('-W'+w, language: 'c')
|
add_global_arguments('-W'+w, language: 'c')
|
||||||
|
|
|
@ -39,8 +39,8 @@ region_t get_damage(session_t *ps, bool all_damage) {
|
||||||
pixman_region32_copy(®ion, &ps->screen_reg);
|
pixman_region32_copy(®ion, &ps->screen_reg);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < buffer_age; i++) {
|
for (int i = 0; i < buffer_age; i++) {
|
||||||
const int curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
||||||
log_trace("damage index: %d, damage ring offset: %d", i, curr);
|
log_trace("damage index: %d, damage ring offset: %ld", i, curr);
|
||||||
dump_region(&ps->damage_ring[curr]);
|
dump_region(&ps->damage_ring[curr]);
|
||||||
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,10 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
col.alpha = a * 0xffff;
|
col.alpha = (uint16_t)(a * 0xffff);
|
||||||
col.red = r * 0xffff;
|
col.red = (uint16_t)(r * 0xffff);
|
||||||
col.green = g * 0xffff;
|
col.green = (uint16_t)(g * 0xffff);
|
||||||
col.blue = b * 0xffff;
|
col.blue = (uint16_t)(b * 0xffff);
|
||||||
|
|
||||||
rect.x = 0;
|
rect.x = 0;
|
||||||
rect.y = 0;
|
rect.y = 0;
|
||||||
|
@ -74,21 +74,22 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
|
||||||
assert(shadow_sum);
|
assert(shadow_sum);
|
||||||
// We only support square kernels for shadow
|
// We only support square kernels for shadow
|
||||||
assert(kernel->w == kernel->h);
|
assert(kernel->w == kernel->h);
|
||||||
int d = kernel->w, r = d / 2;
|
int d = kernel->w;
|
||||||
|
int r = d / 2;
|
||||||
int swidth = width + r * 2, sheight = height + r * 2;
|
int swidth = width + r * 2, sheight = height + r * 2;
|
||||||
|
|
||||||
assert(d % 2 == 1);
|
assert(d % 2 == 1);
|
||||||
assert(d > 0);
|
assert(d > 0);
|
||||||
|
|
||||||
ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
|
ximage = xcb_image_create_native(c, to_u16_checked(swidth), to_u16_checked(sheight),
|
||||||
0, 0, NULL);
|
XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
|
||||||
if (!ximage) {
|
if (!ximage) {
|
||||||
log_error("failed to create an X image");
|
log_error("failed to create an X image");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *data = ximage->data;
|
unsigned char *data = ximage->data;
|
||||||
uint32_t sstride = ximage->stride;
|
long sstride = ximage->stride;
|
||||||
|
|
||||||
// If the window body is smaller than the kernel, we do convolution directly
|
// If the window body is smaller than the kernel, we do convolution directly
|
||||||
if (width < r * 2 && height < r * 2) {
|
if (width < r * 2 && height < r * 2) {
|
||||||
|
@ -96,13 +97,14 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
|
||||||
for (int x = 0; x < swidth; x++) {
|
for (int x = 0; x < swidth; x++) {
|
||||||
double sum = sum_kernel_normalized(
|
double sum = sum_kernel_normalized(
|
||||||
kernel, d - x - 1, d - y - 1, width, height);
|
kernel, d - x - 1, d - y - 1, width, height);
|
||||||
data[y * sstride + x] = sum * 255.0;
|
data[y * sstride + x] = (uint8_t)(sum * 255.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ximage;
|
return ximage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height < r * 2) {
|
if (height < r * 2) {
|
||||||
|
// Implies width >= r * 2
|
||||||
// If the window height is smaller than the kernel, we divide
|
// If the window height is smaller than the kernel, we divide
|
||||||
// the window like this:
|
// the window like this:
|
||||||
// -r r width-r width+r
|
// -r r width-r width+r
|
||||||
|
@ -114,14 +116,15 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
|
||||||
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
||||||
d - y - 1, d, height) *
|
d - y - 1, d, height) *
|
||||||
255.0;
|
255.0;
|
||||||
data[y * sstride + x] = sum;
|
data[y * sstride + x] = (uint8_t)sum;
|
||||||
data[y * sstride + swidth - x - 1] = sum;
|
data[y * sstride + swidth - x - 1] = (uint8_t)sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int y = 0; y < sheight; y++) {
|
for (int y = 0; y < sheight; y++) {
|
||||||
double sum =
|
double sum =
|
||||||
sum_kernel_normalized(kernel, 0, d - y - 1, d, height) * 255.0;
|
sum_kernel_normalized(kernel, 0, d - y - 1, d, height) * 255.0;
|
||||||
memset(&data[y * sstride + r * 2], sum, width - 2 * r);
|
memset(&data[y * sstride + r * 2], (uint8_t)sum,
|
||||||
|
(size_t)(width - 2 * r));
|
||||||
}
|
}
|
||||||
return ximage;
|
return ximage;
|
||||||
}
|
}
|
||||||
|
@ -132,49 +135,52 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
|
||||||
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
||||||
d - y - 1, width, d) *
|
d - y - 1, width, d) *
|
||||||
255.0;
|
255.0;
|
||||||
data[y * sstride + x] = sum;
|
data[y * sstride + x] = (uint8_t)sum;
|
||||||
data[(sheight - y - 1) * sstride + x] = sum;
|
data[(sheight - y - 1) * sstride + x] = (uint8_t)sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int x = 0; x < swidth; x++) {
|
for (int x = 0; x < swidth; x++) {
|
||||||
double sum =
|
double sum =
|
||||||
sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0;
|
sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0;
|
||||||
for (int y = r * 2; y < height; y++) {
|
for (int y = r * 2; y < height; y++) {
|
||||||
data[y * sstride + x] = sum;
|
data[y * sstride + x] = (uint8_t)sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ximage;
|
return ximage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Implies: width >= r * 2 && height >= r * 2
|
||||||
|
|
||||||
// Fill part 3
|
// Fill part 3
|
||||||
for (int y = r; y < height + r; y++) {
|
for (int y = r; y < height + r; y++) {
|
||||||
memset(data + sstride * y + r, 255 * opacity, width);
|
memset(data + sstride * y + r, (uint8_t)(255 * opacity), (size_t)width);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part 1
|
// Part 1
|
||||||
for (int y = 0; y < r * 2; y++) {
|
for (int y = 0; y < r * 2; y++) {
|
||||||
for (int x = 0; x < r * 2; x++) {
|
for (int x = 0; x < r * 2; x++) {
|
||||||
double tmpsum = shadow_sum[y * d + x] * opacity * 255.0;
|
double tmpsum = shadow_sum[y * d + x] * opacity * 255.0;
|
||||||
data[y * sstride + x] = tmpsum;
|
data[y * sstride + x] = (uint8_t)tmpsum;
|
||||||
data[(sheight - y - 1) * sstride + x] = tmpsum;
|
data[(sheight - y - 1) * sstride + x] = (uint8_t)tmpsum;
|
||||||
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = tmpsum;
|
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = (uint8_t)tmpsum;
|
||||||
data[y * sstride + (swidth - x - 1)] = tmpsum;
|
data[y * sstride + (swidth - x - 1)] = (uint8_t)tmpsum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part 2, top/bottom
|
// Part 2, top/bottom
|
||||||
for (int y = 0; y < r * 2; y++) {
|
for (int y = 0; y < r * 2; y++) {
|
||||||
double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0;
|
double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0;
|
||||||
memset(&data[y * sstride + r * 2], tmpsum, width - r * 2);
|
memset(&data[y * sstride + r * 2], (uint8_t)tmpsum, (size_t)(width - r * 2));
|
||||||
memset(&data[(sheight - y - 1) * sstride + r * 2], tmpsum, width - r * 2);
|
memset(&data[(sheight - y - 1) * sstride + r * 2], (uint8_t)tmpsum,
|
||||||
|
(size_t)(width - r * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part 2, left/right
|
// Part 2, left/right
|
||||||
for (int x = 0; x < r * 2; x++) {
|
for (int x = 0; x < r * 2; x++) {
|
||||||
double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0;
|
double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0;
|
||||||
for (int y = r * 2; y < height; y++) {
|
for (int y = r * 2; y < height; y++) {
|
||||||
data[y * sstride + x] = tmpsum;
|
data[y * sstride + x] = (uint8_t)tmpsum;
|
||||||
data[y * sstride + (swidth - x - 1)] = tmpsum;
|
data[y * sstride + (swidth - x - 1)] = (uint8_t)tmpsum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,8 +262,9 @@ shadow_picture_err:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *default_backend_render_shadow(backend_t *backend_data, int width, int height,
|
void *
|
||||||
const conv *kernel, double r, double g, double b, double a) {
|
default_backend_render_shadow(backend_t *backend_data, int width, int height,
|
||||||
|
const conv *kernel, double r, double g, double b, double a) {
|
||||||
xcb_pixmap_t shadow_pixel = solid_picture(backend_data->c, backend_data->root,
|
xcb_pixmap_t shadow_pixel = solid_picture(backend_data->c, backend_data->root,
|
||||||
true, 1, r, g, b),
|
true, 1, r, g, b),
|
||||||
shadow = XCB_NONE;
|
shadow = XCB_NONE;
|
||||||
|
|
|
@ -12,16 +12,17 @@
|
||||||
typedef struct session session_t;
|
typedef struct session session_t;
|
||||||
typedef struct win win;
|
typedef struct win win;
|
||||||
typedef struct conv conv;
|
typedef struct conv conv;
|
||||||
|
typedef struct backend_base backend_t;
|
||||||
|
|
||||||
bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, const int width,
|
bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, int width,
|
||||||
const int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
|
int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
|
||||||
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict);
|
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict);
|
||||||
|
|
||||||
xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb,
|
xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb,
|
||||||
double a, double r, double g, double b);
|
double a, double r, double g, double b);
|
||||||
|
|
||||||
xcb_image_t *
|
xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel, double opacity,
|
||||||
make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height);
|
int width, int height);
|
||||||
|
|
||||||
/// The default implementation of `is_win_transparent`, it simply looks at win::mode. So
|
/// The default implementation of `is_win_transparent`, it simply looks at win::mode. So
|
||||||
/// this is not suitable for backends that alter the content of windows
|
/// this is not suitable for backends that alter the content of windows
|
||||||
|
@ -31,5 +32,6 @@ bool default_is_win_transparent(void *, win *, void *);
|
||||||
/// caveat as `default_is_win_transparent` applies.
|
/// caveat as `default_is_win_transparent` applies.
|
||||||
bool default_is_frame_transparent(void *, win *, void *);
|
bool default_is_frame_transparent(void *, win *, void *);
|
||||||
|
|
||||||
void *default_backend_render_shadow(backend_t *backend_data, int width, int height,
|
void *
|
||||||
const conv *kernel, double r, double g, double b, double a);
|
default_backend_render_shadow(backend_t *backend_data, int width, int height,
|
||||||
|
const conv *kernel, double r, double g, double b, double a);
|
||||||
|
|
|
@ -119,14 +119,16 @@ GLuint gl_create_program_from_str(const char *vert_shader_str, const char *frag_
|
||||||
|
|
||||||
{
|
{
|
||||||
GLuint shaders[2];
|
GLuint shaders[2];
|
||||||
unsigned int count = 0;
|
int count = 0;
|
||||||
if (vert_shader)
|
if (vert_shader) {
|
||||||
shaders[count++] = vert_shader;
|
shaders[count++] = vert_shader;
|
||||||
if (frag_shader)
|
}
|
||||||
|
if (frag_shader) {
|
||||||
shaders[count++] = frag_shader;
|
shaders[count++] = frag_shader;
|
||||||
assert(count <= sizeof(shaders) / sizeof(shaders[0]));
|
}
|
||||||
if (count)
|
if (count) {
|
||||||
prog = gl_create_program(shaders, count);
|
prog = gl_create_program(shaders, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vert_shader)
|
if (vert_shader)
|
||||||
|
@ -185,7 +187,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
|
||||||
if (gd->win_shader.prog) {
|
if (gd->win_shader.prog) {
|
||||||
glUseProgram(gd->win_shader.prog);
|
glUseProgram(gd->win_shader.prog);
|
||||||
if (gd->win_shader.unifm_opacity >= 0) {
|
if (gd->win_shader.unifm_opacity >= 0) {
|
||||||
glUniform1f(gd->win_shader.unifm_opacity, ptex->opacity);
|
glUniform1f(gd->win_shader.unifm_opacity, (float)ptex->opacity);
|
||||||
}
|
}
|
||||||
if (gd->win_shader.unifm_invert_color >= 0) {
|
if (gd->win_shader.unifm_invert_color >= 0) {
|
||||||
glUniform1i(gd->win_shader.unifm_invert_color, ptex->color_inverted);
|
glUniform1i(gd->win_shader.unifm_invert_color, ptex->color_inverted);
|
||||||
|
@ -194,7 +196,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
|
||||||
glUniform1i(gd->win_shader.unifm_tex, 0);
|
glUniform1i(gd->win_shader.unifm_tex, 0);
|
||||||
}
|
}
|
||||||
if (gd->win_shader.unifm_dim >= 0) {
|
if (gd->win_shader.unifm_dim >= 0) {
|
||||||
glUniform1f(gd->win_shader.unifm_dim, ptex->dim);
|
glUniform1f(gd->win_shader.unifm_dim, (float)ptex->dim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,23 +226,23 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
|
||||||
|
|
||||||
// Calculate texture coordinates
|
// Calculate texture coordinates
|
||||||
// (texture_x1, texture_y1), texture coord for the _bottom left_ corner
|
// (texture_x1, texture_y1), texture coord for the _bottom left_ corner
|
||||||
GLfloat texture_x1 = crect.x1 - dst_x;
|
auto texture_x1 = (GLfloat)(crect.x1 - dst_x);
|
||||||
GLfloat texture_y1 = crect.y2 - dst_y2;
|
auto texture_y1 = (GLfloat)(crect.y2 - dst_y2);
|
||||||
GLfloat texture_x2 = texture_x1 + crect.x2 - crect.x1;
|
auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1);
|
||||||
GLfloat texture_y2 = texture_y1 + crect.y1 - crect.y2;
|
auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2);
|
||||||
|
|
||||||
// X pixmaps might be Y inverted, invert the texture coordinates
|
// X pixmaps might be Y inverted, invert the texture coordinates
|
||||||
if (ptex->y_inverted) {
|
if (ptex->y_inverted) {
|
||||||
texture_y1 = ptex->height - texture_y1;
|
texture_y1 = (GLfloat)ptex->height - texture_y1;
|
||||||
texture_y2 = ptex->height - texture_y2;
|
texture_y2 = (GLfloat)ptex->height - texture_y2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GL_TEXTURE_2D coordinates are normalized
|
// GL_TEXTURE_2D coordinates are normalized
|
||||||
// TODO use texelFetch
|
// TODO use texelFetch
|
||||||
texture_x1 /= ptex->width;
|
texture_x1 /= (GLfloat)ptex->width;
|
||||||
texture_y1 /= ptex->height;
|
texture_y1 /= (GLfloat)ptex->height;
|
||||||
texture_x2 /= ptex->width;
|
texture_x2 /= (GLfloat)ptex->width;
|
||||||
texture_y2 /= ptex->height;
|
texture_y2 /= (GLfloat)ptex->height;
|
||||||
|
|
||||||
// Vertex coordinates
|
// Vertex coordinates
|
||||||
GLint vx1 = crect.x1;
|
GLint vx1 = crect.x1;
|
||||||
|
@ -333,11 +335,11 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
|
||||||
// last pass, draw directly into the back buffer
|
// last pass, draw directly into the back buffer
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glDrawBuffer(GL_BACK);
|
glDrawBuffer(GL_BACK);
|
||||||
glUniform1f(p->unifm_opacity, opacity);
|
glUniform1f(p->unifm_opacity, (float)opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
glUniform1f(p->unifm_offset_x, 1.0 / gd->width);
|
glUniform1f(p->unifm_offset_x, 1.0f / (GLfloat)gd->width);
|
||||||
glUniform1f(p->unifm_offset_y, 1.0 / gd->height);
|
glUniform1f(p->unifm_offset_y, 1.0f / (GLfloat)gd->height);
|
||||||
|
|
||||||
// XXX use multiple draw calls is probably going to be slow than
|
// XXX use multiple draw calls is probably going to be slow than
|
||||||
// just simply blur the whole area.
|
// just simply blur the whole area.
|
||||||
|
@ -354,29 +356,29 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
|
||||||
crect.y2 = gd->height - crect.y2;
|
crect.y2 = gd->height - crect.y2;
|
||||||
|
|
||||||
// Texture coordinates
|
// Texture coordinates
|
||||||
GLfloat texture_x1 = (crect.x1 - extent->x1);
|
auto texture_x1 = (GLfloat)(crect.x1 - extent->x1);
|
||||||
GLfloat texture_y1 = (crect.y2 - dst_y);
|
auto texture_y1 = (GLfloat)(crect.y2 - dst_y);
|
||||||
GLfloat texture_x2 = texture_x1 + (crect.x2 - crect.x1);
|
auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1);
|
||||||
GLfloat texture_y2 = texture_y1 + (crect.y1 - crect.y2);
|
auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2);
|
||||||
|
|
||||||
texture_x1 /= gd->width;
|
texture_x1 /= (GLfloat)gd->width;
|
||||||
texture_x2 /= gd->width;
|
texture_x2 /= (GLfloat)gd->width;
|
||||||
texture_y1 /= gd->height;
|
texture_y1 /= (GLfloat)gd->height;
|
||||||
texture_y2 /= gd->height;
|
texture_y2 /= (GLfloat)gd->height;
|
||||||
|
|
||||||
// Vertex coordinates
|
// Vertex coordinates
|
||||||
// For passes before the last one, we are drawing into a buffer,
|
// For passes before the last one, we are drawing into a buffer,
|
||||||
// so (dx, dy) from source maps to (0, 0)
|
// so (dx, dy) from source maps to (0, 0)
|
||||||
GLfloat vx1 = crect.x1 - extent->x1;
|
GLint vx1 = crect.x1 - extent->x1;
|
||||||
GLfloat vy1 = crect.y2 - dst_y;
|
GLint vy1 = crect.y2 - dst_y;
|
||||||
if (i == gd->npasses - 1) {
|
if (i == gd->npasses - 1) {
|
||||||
// For last pass, we are drawing back to source, so we
|
// For last pass, we are drawing back to source, so we
|
||||||
// don't need to map
|
// don't need to map
|
||||||
vx1 = crect.x1;
|
vx1 = crect.x1;
|
||||||
vy1 = crect.y2;
|
vy1 = crect.y2;
|
||||||
}
|
}
|
||||||
GLfloat vx2 = vx1 + (crect.x2 - crect.x1);
|
GLint vx2 = vx1 + (crect.x2 - crect.x1);
|
||||||
GLfloat vy2 = vy1 + (crect.y1 - crect.y2);
|
GLint vy2 = vy1 + (crect.y1 - crect.y2);
|
||||||
|
|
||||||
GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1};
|
GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1};
|
||||||
GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2};
|
GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2};
|
||||||
|
@ -406,7 +408,7 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLuint glGetUniformLocationChecked(GLuint p, const char *name) {
|
static GLint glGetUniformLocationChecked(GLuint p, const char *name) {
|
||||||
auto ret = glGetUniformLocation(p, name);
|
auto ret = glGetUniformLocation(p, name);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
log_error("Failed to get location of uniform '%s'. compton might not "
|
log_error("Failed to get location of uniform '%s'. compton might not "
|
||||||
|
@ -470,13 +472,13 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi
|
||||||
int nrects;
|
int nrects;
|
||||||
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
|
const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects);
|
||||||
struct gl_data *gd = (void *)base;
|
struct gl_data *gd = (void *)base;
|
||||||
glColor4f(r, g, b, a);
|
glColor4d(r, g, b, a);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
for (int i = 0; i < nrects; i++) {
|
for (int i = 0; i < nrects; i++) {
|
||||||
glVertex2f(rect[i].x1, gd->height - rect[i].y2);
|
glVertex2i(rect[i].x1, gd->height - rect[i].y2);
|
||||||
glVertex2f(rect[i].x2, gd->height - rect[i].y2);
|
glVertex2i(rect[i].x2, gd->height - rect[i].y2);
|
||||||
glVertex2f(rect[i].x2, gd->height - rect[i].y1);
|
glVertex2i(rect[i].x2, gd->height - rect[i].y1);
|
||||||
glVertex2f(rect[i].x1, gd->height - rect[i].y1);
|
glVertex2i(rect[i].x1, gd->height - rect[i].y1);
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
@ -524,7 +526,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
|
||||||
// Build shader
|
// Build shader
|
||||||
int width = kern->w, height = kern->h;
|
int width = kern->w, height = kern->h;
|
||||||
int nele = width * height - 1;
|
int nele = width * height - 1;
|
||||||
size_t body_len = (strlen(shader_add) + 42) * nele;
|
size_t body_len = (strlen(shader_add) + 42) * (uint)nele;
|
||||||
char *shader_body = ccalloc(body_len, char);
|
char *shader_body = ccalloc(body_len, char);
|
||||||
char *pc = shader_body;
|
char *pc = shader_body;
|
||||||
|
|
||||||
|
@ -541,7 +543,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sum += val;
|
sum += val;
|
||||||
pc += snprintf(pc, body_len - (pc - shader_body),
|
pc += snprintf(pc, body_len - (ulong)(pc - shader_body),
|
||||||
FRAG_SHADER_BLUR_ADD, val, k - width / 2,
|
FRAG_SHADER_BLUR_ADD, val, k - width / 2,
|
||||||
j - height / 2);
|
j - height / 2);
|
||||||
assert(pc < shader_body + body_len);
|
assert(pc < shader_body + body_len);
|
||||||
|
@ -553,9 +555,10 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) {
|
||||||
strlen(shader_body) + 10 /* sum */ +
|
strlen(shader_body) + 10 /* sum */ +
|
||||||
1 /* null terminator */;
|
1 /* null terminator */;
|
||||||
char *shader_str = ccalloc(shader_len, char);
|
char *shader_str = ccalloc(shader_len, char);
|
||||||
size_t real_shader_len = snprintf(
|
auto real_shader_len = snprintf(
|
||||||
shader_str, shader_len, FRAG_SHADER_BLUR, extension, shader_body, sum);
|
shader_str, shader_len, FRAG_SHADER_BLUR, extension, shader_body, sum);
|
||||||
assert(real_shader_len < shader_len);
|
assert(real_shader_len >= 0);
|
||||||
|
assert((size_t)real_shader_len < shader_len);
|
||||||
free(shader_body);
|
free(shader_body);
|
||||||
|
|
||||||
// Build program
|
// Build program
|
||||||
|
|
|
@ -162,7 +162,7 @@ static inline bool gl_has_extension(const char *ext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nexts; i++) {
|
for (int i = 0; i < nexts; i++) {
|
||||||
const char *exti = (const char *)glGetStringi(GL_EXTENSIONS, i);
|
const char *exti = (const char *)glGetStringi(GL_EXTENSIONS, (GLuint)i);
|
||||||
if (strcmp(ext, exti) == 0)
|
if (strcmp(ext, exti) == 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct _glx_data {
|
||||||
struct gl_data gl;
|
struct gl_data gl;
|
||||||
Display *display;
|
Display *display;
|
||||||
int screen;
|
int screen;
|
||||||
int target_win;
|
xcb_window_t target_win;
|
||||||
int glx_event;
|
int glx_event;
|
||||||
int glx_error;
|
int glx_error;
|
||||||
GLXContext ctx;
|
GLXContext ctx;
|
||||||
|
@ -70,7 +70,7 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
|
||||||
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
||||||
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||||
GLX_X_RENDERABLE, true,
|
GLX_X_RENDERABLE, true,
|
||||||
GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, GLX_DONT_CARE,
|
GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, (GLint)GLX_DONT_CARE,
|
||||||
GLX_BUFFER_SIZE, m.red_size + m.green_size +
|
GLX_BUFFER_SIZE, m.red_size + m.green_size +
|
||||||
m.blue_size + m.alpha_size,
|
m.blue_size + m.alpha_size,
|
||||||
GLX_RED_SIZE, m.red_size,
|
GLX_RED_SIZE, m.red_size,
|
||||||
|
@ -117,7 +117,8 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
|
||||||
int visual;
|
int visual;
|
||||||
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual);
|
glXGetFBConfigAttribChecked(dpy, cfg[i], GLX_VISUAL_ID, &visual);
|
||||||
if (m.visual_depth != -1 &&
|
if (m.visual_depth != -1 &&
|
||||||
x_get_visual_depth(XGetXCBConnection(dpy), visual) != m.visual_depth) {
|
x_get_visual_depth(XGetXCBConnection(dpy), (xcb_visualid_t)visual) !=
|
||||||
|
m.visual_depth) {
|
||||||
// Some driver might attach fbconfig to a GLX visual with a
|
// Some driver might attach fbconfig to a GLX visual with a
|
||||||
// different depth.
|
// different depth.
|
||||||
//
|
//
|
||||||
|
@ -347,6 +348,11 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fmt.visual_depth < 0) {
|
||||||
|
log_error("Pixmap %#010x with invalid depth %d", pixmap, fmt.visual_depth);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL);
|
auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
log_error("Invalid pixmap %#010x", pixmap);
|
log_error("Invalid pixmap %#010x", pixmap);
|
||||||
|
@ -400,7 +406,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
|
||||||
// Create texture
|
// Create texture
|
||||||
wd->texture.texture = gl_new_texture(GL_TEXTURE_2D);
|
wd->texture.texture = gl_new_texture(GL_TEXTURE_2D);
|
||||||
wd->texture.opacity = 1;
|
wd->texture.opacity = 1;
|
||||||
wd->texture.depth = fmt.visual_depth;
|
wd->texture.depth = (unsigned int)fmt.visual_depth;
|
||||||
wd->texture.color_inverted = false;
|
wd->texture.color_inverted = false;
|
||||||
wd->texture.dim = 0;
|
wd->texture.dim = 0;
|
||||||
wd->texture.has_alpha = fmt.alpha_size != 0;
|
wd->texture.has_alpha = fmt.alpha_size != 0;
|
||||||
|
@ -475,7 +481,7 @@ static inline bool glx_has_extension(Display *dpy, int screen, const char *ext)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long inlen = strlen(ext);
|
auto inlen = strlen(ext);
|
||||||
const char *curr = glx_exts;
|
const char *curr = glx_exts;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
while (curr && !match) {
|
while (curr && !match) {
|
||||||
|
@ -483,9 +489,9 @@ static inline bool glx_has_extension(Display *dpy, int screen, const char *ext)
|
||||||
if (!end) {
|
if (!end) {
|
||||||
// Last extension string
|
// Last extension string
|
||||||
match = strcmp(ext, curr) == 0;
|
match = strcmp(ext, curr) == 0;
|
||||||
} else if (end - curr == inlen) {
|
} else if (curr + inlen == end) {
|
||||||
// Length match, do match string
|
// Length match, do match string
|
||||||
match = strncmp(ext, curr, end - curr) == 0;
|
match = strncmp(ext, curr, (unsigned long)(end - curr)) == 0;
|
||||||
}
|
}
|
||||||
curr = end ? end + 1 : NULL;
|
curr = end ? end + 1 : NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ typedef struct _xrender_data {
|
||||||
/// Blur kernels converted to X format
|
/// Blur kernels converted to X format
|
||||||
xcb_render_fixed_t *x_blur_kern[MAX_BLUR_PASS];
|
xcb_render_fixed_t *x_blur_kern[MAX_BLUR_PASS];
|
||||||
/// Number of elements in each blur kernel
|
/// Number of elements in each blur kernel
|
||||||
size_t x_blur_kern_size[MAX_BLUR_PASS];
|
int x_blur_kern_size[MAX_BLUR_PASS];
|
||||||
|
|
||||||
xcb_special_event_t *present_event;
|
xcb_special_event_t *present_event;
|
||||||
} xrender_data;
|
} xrender_data;
|
||||||
|
@ -75,9 +75,9 @@ struct _xrender_image_data {
|
||||||
xcb_pixmap_t pixmap;
|
xcb_pixmap_t pixmap;
|
||||||
// A Picture links to the Pixmap
|
// A Picture links to the Pixmap
|
||||||
xcb_render_picture_t pict;
|
xcb_render_picture_t pict;
|
||||||
long width, height;
|
int width, height;
|
||||||
// The effective size of the image
|
// The effective size of the image
|
||||||
long ewidth, eheight;
|
int ewidth, eheight;
|
||||||
bool has_alpha;
|
bool has_alpha;
|
||||||
double opacity;
|
double opacity;
|
||||||
xcb_visualid_t visual;
|
xcb_visualid_t visual;
|
||||||
|
@ -89,7 +89,7 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
|
||||||
const region_t *reg_paint, const region_t *reg_visible) {
|
const region_t *reg_paint, const region_t *reg_visible) {
|
||||||
struct _xrender_data *xd = (void *)base;
|
struct _xrender_data *xd = (void *)base;
|
||||||
struct _xrender_image_data *img = img_data;
|
struct _xrender_image_data *img = img_data;
|
||||||
int op = (img->has_alpha ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC);
|
uint8_t op = (img->has_alpha ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC);
|
||||||
auto alpha_pict = xd->alpha_pict[(int)(img->opacity * 255.0)];
|
auto alpha_pict = xd->alpha_pict[(int)(img->opacity * 255.0)];
|
||||||
region_t reg;
|
region_t reg;
|
||||||
pixman_region32_init(®);
|
pixman_region32_init(®);
|
||||||
|
@ -101,7 +101,8 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
|
||||||
|
|
||||||
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, ®);
|
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, ®);
|
||||||
xcb_render_composite(base->c, op, img->pict, alpha_pict, xd->back[xd->curr_back],
|
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(®);
|
pixman_region32_fini(®);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,13 +114,15 @@ fill(backend_t *base, double r, double g, double b, double a, const region_t *cl
|
||||||
// color is in X fixed point representation
|
// color is in X fixed point representation
|
||||||
xcb_render_fill_rectangles(
|
xcb_render_fill_rectangles(
|
||||||
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
|
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
|
||||||
(xcb_render_color_t){
|
(xcb_render_color_t){.red = (uint16_t)(r * 0xffff),
|
||||||
.red = r * 0xffff, .green = g * 0xffff, .blue = b * 0xffff, .alpha = a * 0xffff},
|
.green = (uint16_t)(g * 0xffff),
|
||||||
|
.blue = (uint16_t)(b * 0xffff),
|
||||||
|
.alpha = (uint16_t)(a * 0xffff)},
|
||||||
1,
|
1,
|
||||||
(xcb_rectangle_t[]){{.x = extent->x1,
|
(xcb_rectangle_t[]){{.x = to_i16_checked(extent->x1),
|
||||||
.y = extent->y1,
|
.y = to_i16_checked(extent->y1),
|
||||||
.width = extent->x2 - extent->x1,
|
.width = to_u16_checked(extent->x2 - extent->x1),
|
||||||
.height = extent->y2 - extent->y1}});
|
.height = to_u16_checked(extent->y2 - extent->y1)}});
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
||||||
|
@ -135,9 +138,10 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
|
||||||
}
|
}
|
||||||
|
|
||||||
const pixman_box32_t *extent = pixman_region32_extents(®_op);
|
const pixman_box32_t *extent = pixman_region32_extents(®_op);
|
||||||
const int height = extent->y2 - extent->y1;
|
const auto height = to_u16_checked(extent->y2 - extent->y1);
|
||||||
const int width = extent->x2 - extent->x1;
|
const auto width = to_u16_checked(extent->x2 - extent->x1);
|
||||||
int src_x = extent->x1, src_y = extent->y1;
|
auto src_x = to_i16_checked(extent->x1);
|
||||||
|
auto src_y = to_i16_checked(extent->y1);
|
||||||
static const char *filter0 = "Nearest"; // The "null" filter
|
static const char *filter0 = "Nearest"; // The "null" filter
|
||||||
static const char *filter = "convolution";
|
static const char *filter = "convolution";
|
||||||
|
|
||||||
|
@ -183,8 +187,9 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
|
||||||
// be applied on source picture, to get the nearby pixels outside the
|
// be applied on source picture, to get the nearby pixels outside the
|
||||||
// window.
|
// window.
|
||||||
// TODO cache converted blur_kerns
|
// TODO cache converted blur_kerns
|
||||||
xcb_render_set_picture_filter(c, src_pict, strlen(filter), filter,
|
xcb_render_set_picture_filter(
|
||||||
xd->x_blur_kern_size[i], xd->x_blur_kern[i]);
|
c, src_pict, to_u16_checked(strlen(filter)), filter,
|
||||||
|
to_u32_checked(xd->x_blur_kern_size[i]), xd->x_blur_kern[i]);
|
||||||
|
|
||||||
if (xd->x_blur_kern[i + 1] || i == 0) {
|
if (xd->x_blur_kern[i + 1] || i == 0) {
|
||||||
// This is not the last pass, or this is the first pass
|
// This is not the last pass, or this is the first pass
|
||||||
|
@ -199,7 +204,8 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset filter
|
// reset filter
|
||||||
xcb_render_set_picture_filter(c, src_pict, strlen(filter0), filter0, 0, NULL);
|
xcb_render_set_picture_filter(
|
||||||
|
c, src_pict, to_u16_checked(strlen(filter0)), filter0, 0, NULL);
|
||||||
|
|
||||||
src_pict = tmp_picture[current];
|
src_pict = tmp_picture[current];
|
||||||
dst_pict = tmp_picture[!current];
|
dst_pict = tmp_picture[!current];
|
||||||
|
@ -211,8 +217,9 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
|
||||||
// There is only 1 pass
|
// There is only 1 pass
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict,
|
xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict,
|
||||||
xd->back[xd->curr_back], 0, 0, 0, 0, extent->x1,
|
xd->back[xd->curr_back], 0, 0, 0, 0,
|
||||||
extent->y1, width, height);
|
to_i16_checked(extent->x1),
|
||||||
|
to_i16_checked(extent->y1), width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_render_free_picture(c, tmp_picture[0]);
|
xcb_render_free_picture(c, tmp_picture[0]);
|
||||||
|
@ -232,7 +239,7 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
auto img = ccalloc(1, struct _xrender_image_data);
|
auto img = ccalloc(1, struct _xrender_image_data);
|
||||||
img->depth = fmt.visual_depth;
|
img->depth = (uint8_t)fmt.visual_depth;
|
||||||
img->width = img->ewidth = r->width;
|
img->width = img->ewidth = r->width;
|
||||||
img->height = img->eheight = r->height;
|
img->height = img->eheight = r->height;
|
||||||
img->pixmap = pixmap;
|
img->pixmap = pixmap;
|
||||||
|
@ -328,7 +335,8 @@ static void present(backend_t *base) {
|
||||||
// but that will require a different backend API
|
// but that will require a different backend API
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC,
|
||||||
xd->back[xd->curr_back], XCB_NONE, xd->target, 0, 0,
|
xd->back[xd->curr_back], XCB_NONE, xd->target, 0, 0,
|
||||||
0, 0, 0, 0, xd->target_width, xd->target_height);
|
0, 0, 0, 0, to_u16_checked(xd->target_width),
|
||||||
|
to_u16_checked(xd->target_height));
|
||||||
xd->buffer_age[xd->curr_back] = 1;
|
xd->buffer_age[xd->curr_back] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,6 +366,8 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
|
||||||
|
|
||||||
pixman_region32_init(®);
|
pixman_region32_init(®);
|
||||||
|
|
||||||
|
const auto tmpw = to_u16_checked(img->width);
|
||||||
|
const auto tmph = to_u16_checked(img->height);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case IMAGE_OP_INVERT_COLOR_ALL:
|
case IMAGE_OP_INVERT_COLOR_ALL:
|
||||||
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
|
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
|
||||||
|
@ -366,36 +376,35 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
|
||||||
x_create_picture_with_visual(base->c, base->root, img->width,
|
x_create_picture_with_visual(base->c, base->root, img->width,
|
||||||
img->height, img->visual, 0, NULL);
|
img->height, img->visual, 0, NULL);
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict,
|
||||||
XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0,
|
XCB_NONE, tmp_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
|
||||||
img->width, img->height);
|
|
||||||
|
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE,
|
||||||
xd->white_pixel, XCB_NONE, tmp_pict, 0, 0, 0,
|
xd->white_pixel, XCB_NONE, tmp_pict, 0, 0, 0,
|
||||||
0, 0, 0, img->width, img->height);
|
0, 0, 0, tmpw, tmph);
|
||||||
// We use an extra PictOpInReverse operation to get correct pixel
|
// We use an extra PictOpInReverse operation to get correct pixel
|
||||||
// alpha. There could be a better solution.
|
// alpha. There could be a better solution.
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN_REVERSE,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN_REVERSE,
|
||||||
tmp_pict, XCB_NONE, img->pict, 0, 0, 0, 0, 0,
|
tmp_pict, XCB_NONE, img->pict, 0, 0, 0, 0, 0,
|
||||||
0, img->width, img->height);
|
0, tmpw, tmph);
|
||||||
xcb_render_free_picture(base->c, tmp_pict);
|
xcb_render_free_picture(base->c, tmp_pict);
|
||||||
} else {
|
} else {
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_DIFFERENCE,
|
||||||
xd->white_pixel, XCB_NONE, img->pict, 0, 0,
|
xd->white_pixel, XCB_NONE, img->pict, 0, 0,
|
||||||
0, 0, 0, 0, img->width, img->height);
|
0, 0, 0, 0, tmpw, tmph);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IMAGE_OP_DIM_ALL:
|
case IMAGE_OP_DIM_ALL:
|
||||||
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
|
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
|
||||||
|
|
||||||
xcb_render_color_t color = {
|
xcb_render_color_t color = {
|
||||||
.red = 0, .green = 0, .blue = 0, .alpha = 0xffff * dargs[0]};
|
.red = 0, .green = 0, .blue = 0, .alpha = (uint16_t)(0xffff * dargs[0])};
|
||||||
|
|
||||||
// Dim the actually content of window
|
// Dim the actually content of window
|
||||||
xcb_rectangle_t rect = {
|
xcb_rectangle_t rect = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
.width = img->width,
|
.width = tmpw,
|
||||||
.height = img->height,
|
.height = tmph,
|
||||||
};
|
};
|
||||||
|
|
||||||
xcb_render_fill_rectangles(base->c, XCB_RENDER_PICT_OP_OVER, img->pict,
|
xcb_render_fill_rectangles(base->c, XCB_RENDER_PICT_OP_OVER, img->pict,
|
||||||
|
@ -415,7 +424,7 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
|
||||||
auto alpha_pict = xd->alpha_pict[(int)(dargs[0] * 255)];
|
auto alpha_pict = xd->alpha_pict[(int)(dargs[0] * 255)];
|
||||||
x_set_picture_clip_region(base->c, img->pict, 0, 0, ®);
|
x_set_picture_clip_region(base->c, img->pict, 0, 0, ®);
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN, img->pict, XCB_NONE,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN, img->pict, XCB_NONE,
|
||||||
alpha_pict, 0, 0, 0, 0, 0, 0, img->width, img->height);
|
alpha_pict, 0, 0, 0, 0, 0, 0, tmpw, tmph);
|
||||||
img->has_alpha = true;
|
img->has_alpha = true;
|
||||||
break;
|
break;
|
||||||
case IMAGE_OP_RESIZE_TILE:
|
case IMAGE_OP_RESIZE_TILE:
|
||||||
|
@ -454,10 +463,11 @@ static void *copy(backend_t *base, const void *image, const region_t *reg) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto alpha_pict =
|
xcb_render_picture_t alpha_pict =
|
||||||
img->opacity == 1 ? XCB_NONE : xd->alpha_pict[(int)(img->opacity * 255)];
|
img->opacity == 1 ? XCB_NONE : xd->alpha_pict[(int)(img->opacity * 255)];
|
||||||
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict, alpha_pict,
|
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_SRC, img->pict, alpha_pict,
|
||||||
new_img->pict, 0, 0, 0, 0, 0, 0, img->width, img->height);
|
new_img->pict, 0, 0, 0, 0, 0, 0, to_u16_checked(img->width),
|
||||||
|
to_u16_checked(img->height));
|
||||||
return new_img;
|
return new_img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +536,8 @@ backend_t *backend_xrender_init(session_t *ps) {
|
||||||
int pixmap_needed = xd->vsync ? 2 : 1;
|
int pixmap_needed = xd->vsync ? 2 : 1;
|
||||||
for (int i = 0; i < pixmap_needed; i++) {
|
for (int i = 0; i < pixmap_needed; i++) {
|
||||||
xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root,
|
xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root,
|
||||||
ps->root_width, ps->root_height);
|
to_u16_checked(ps->root_width),
|
||||||
|
to_u16_checked(ps->root_height));
|
||||||
xd->back[i] = x_create_picture_with_pictfmt_and_pixmap(
|
xd->back[i] = x_create_picture_with_pictfmt_and_pixmap(
|
||||||
ps->c, pictfmt, xd->back_pixmap[i], 0, NULL);
|
ps->c, pictfmt, xd->back_pixmap[i], 0, NULL);
|
||||||
xd->buffer_age[i] = -1;
|
xd->buffer_age[i] = -1;
|
||||||
|
|
220
src/c2.c
220
src/c2.c
|
@ -106,8 +106,8 @@ struct _c2_l {
|
||||||
xcb_atom_t tgtatom;
|
xcb_atom_t tgtatom;
|
||||||
bool tgt_onframe;
|
bool tgt_onframe;
|
||||||
int index;
|
int index;
|
||||||
enum { C2_L_PUNDEFINED,
|
enum { C2_L_PUNDEFINED = -1,
|
||||||
C2_L_PID,
|
C2_L_PID = 0,
|
||||||
C2_L_PX,
|
C2_L_PX,
|
||||||
C2_L_PY,
|
C2_L_PY,
|
||||||
C2_L_PX2,
|
C2_L_PX2,
|
||||||
|
@ -554,17 +554,19 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy target name out
|
// Copy target name out
|
||||||
unsigned tgtlen = 0;
|
int tgtlen = 0;
|
||||||
for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]);
|
for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]);
|
||||||
++offset) {
|
++offset) {
|
||||||
++tgtlen;
|
++tgtlen;
|
||||||
}
|
}
|
||||||
if (!tgtlen)
|
if (!tgtlen) {
|
||||||
c2_error("Empty target.");
|
c2_error("Empty target.");
|
||||||
pleaf->tgt = strndup(&pattern[offset - tgtlen], tgtlen);
|
}
|
||||||
|
pleaf->tgt = strndup(&pattern[offset - tgtlen], (size_t)tgtlen);
|
||||||
|
|
||||||
// Check for predefined targets
|
// Check for predefined targets
|
||||||
for (unsigned i = 1; i < sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]); ++i) {
|
static const int npredefs = (int)(sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]));
|
||||||
|
for (int i = 0; i < npredefs; ++i) {
|
||||||
if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) {
|
if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) {
|
||||||
pleaf->predef = i;
|
pleaf->predef = i;
|
||||||
pleaf->type = C2_PREDEFS[i].type;
|
pleaf->type = C2_PREDEFS[i].type;
|
||||||
|
@ -573,25 +575,6 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alias for predefined targets
|
|
||||||
if (!pleaf->predef) {
|
|
||||||
#define TGTFILL(pdefid) \
|
|
||||||
(pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \
|
|
||||||
pleaf->format = C2_PREDEFS[pdefid].format)
|
|
||||||
|
|
||||||
// if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt))
|
|
||||||
// TGTFILL(C2_L_PNAME);
|
|
||||||
#undef TGTFILL
|
|
||||||
|
|
||||||
// Alias for custom properties
|
|
||||||
#define TGTFILL(target, type, format) \
|
|
||||||
(pleaf->target = strdup(target), pleaf->type = type, pleaf->format = format)
|
|
||||||
|
|
||||||
// if (!strcmp("SOME_ALIAS"))
|
|
||||||
// TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32);
|
|
||||||
#undef TGTFILL
|
|
||||||
}
|
|
||||||
|
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
|
|
||||||
// Parse target-on-frame flag
|
// Parse target-on-frame flag
|
||||||
|
@ -607,27 +590,29 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
|
|
||||||
int index = -1;
|
long index = -1;
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
|
|
||||||
index = strtol(pattern + offset, &endptr, 0);
|
index = strtol(pattern + offset, &endptr, 0);
|
||||||
|
|
||||||
if (!endptr || pattern + offset == endptr)
|
if (!endptr || pattern + offset == endptr) {
|
||||||
c2_error("No index number found after bracket.");
|
c2_error("No index number found after bracket.");
|
||||||
|
}
|
||||||
if (index < 0)
|
if (index < 0) {
|
||||||
c2_error("Index number invalid.");
|
c2_error("Index number invalid.");
|
||||||
|
}
|
||||||
if (pleaf->predef)
|
if (pleaf->predef != C2_L_PUNDEFINED) {
|
||||||
c2_error("Predefined targets can't have index.");
|
c2_error("Predefined targets can't have index.");
|
||||||
|
}
|
||||||
|
|
||||||
pleaf->index = index;
|
pleaf->index = to_int_checked(index);
|
||||||
offset = endptr - pattern;
|
offset = to_int_checked(endptr - pattern);
|
||||||
|
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
|
|
||||||
if (']' != pattern[offset])
|
if (pattern[offset] != ']') {
|
||||||
c2_error("Index end marker not found.");
|
c2_error("Index end marker not found.");
|
||||||
|
}
|
||||||
|
|
||||||
++offset;
|
++offset;
|
||||||
|
|
||||||
|
@ -641,44 +626,43 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
// Look for format
|
// Look for format
|
||||||
bool hasformat = false;
|
bool hasformat = false;
|
||||||
int format = 0;
|
long format = 0;
|
||||||
{
|
{
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
format = strtol(pattern + offset, &endptr, 0);
|
format = strtol(pattern + offset, &endptr, 0);
|
||||||
assert(endptr);
|
assert(endptr);
|
||||||
if ((hasformat = (endptr && endptr != pattern + offset)))
|
if ((hasformat = (endptr && endptr != pattern + offset))) {
|
||||||
offset = endptr - pattern;
|
offset = to_int_checked(endptr - pattern);
|
||||||
|
}
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for type
|
// Look for type
|
||||||
enum c2_l_type type = C2_L_TUNDEFINED;
|
enum c2_l_type type = C2_L_TUNDEFINED;
|
||||||
{
|
switch (pattern[offset]) {
|
||||||
switch (pattern[offset]) {
|
case 'w': type = C2_L_TWINDOW; break;
|
||||||
case 'w': type = C2_L_TWINDOW; break;
|
case 'd': type = C2_L_TDRAWABLE; break;
|
||||||
case 'd': type = C2_L_TDRAWABLE; break;
|
case 'c': type = C2_L_TCARDINAL; break;
|
||||||
case 'c': type = C2_L_TCARDINAL; break;
|
case 's': type = C2_L_TSTRING; break;
|
||||||
case 's': type = C2_L_TSTRING; break;
|
case 'a': type = C2_L_TATOM; break;
|
||||||
case 'a': type = C2_L_TATOM; break;
|
default: c2_error("Invalid type character.");
|
||||||
default: c2_error("Invalid type character.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type) {
|
|
||||||
if (pleaf->predef) {
|
|
||||||
log_warn("Type specified for a default target "
|
|
||||||
"will be ignored.");
|
|
||||||
} else {
|
|
||||||
if (pleaf->type && type != pleaf->type)
|
|
||||||
log_warn("Default type overridden on "
|
|
||||||
"target.");
|
|
||||||
pleaf->type = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
offset++;
|
|
||||||
C2H_SKIP_SPACES();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
if (pleaf->predef != C2_L_PUNDEFINED) {
|
||||||
|
log_warn("Type specified for a default target "
|
||||||
|
"will be ignored.");
|
||||||
|
} else {
|
||||||
|
if (pleaf->type && type != pleaf->type)
|
||||||
|
log_warn("Default type overridden on "
|
||||||
|
"target.");
|
||||||
|
pleaf->type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
C2H_SKIP_SPACES();
|
||||||
|
|
||||||
// Default format
|
// Default format
|
||||||
if (!pleaf->format) {
|
if (!pleaf->format) {
|
||||||
switch (pleaf->type) {
|
switch (pleaf->type) {
|
||||||
|
@ -692,20 +676,20 @@ static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
// Write format
|
// Write format
|
||||||
if (hasformat) {
|
if (hasformat) {
|
||||||
if (pleaf->predef)
|
if (pleaf->predef != C2_L_PUNDEFINED) {
|
||||||
log_warn("Format \"%d\" specified on a default target "
|
log_warn("Format \"%ld\" specified on a default target "
|
||||||
"will be ignored.",
|
"will be ignored.",
|
||||||
format);
|
format);
|
||||||
else if (C2_L_TSTRING == pleaf->type)
|
} else if (pleaf->type == C2_L_TSTRING) {
|
||||||
log_warn("Format \"%d\" specified on a string target "
|
log_warn("Format \"%ld\" specified on a string target "
|
||||||
"will be ignored.",
|
"will be ignored.",
|
||||||
format);
|
format);
|
||||||
else {
|
} else {
|
||||||
if (pleaf->format && pleaf->format != format)
|
if (pleaf->format && pleaf->format != format)
|
||||||
log_warn("Default format %d overridden on "
|
log_warn("Default format %d overridden on "
|
||||||
"target.",
|
"target.",
|
||||||
pleaf->format);
|
pleaf->format);
|
||||||
pleaf->format = format;
|
pleaf->format = to_int_checked(format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -798,52 +782,51 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
|
||||||
c2_l_t *const pleaf = presult->l;
|
c2_l_t *const pleaf = presult->l;
|
||||||
|
|
||||||
// Exists operator cannot have pattern
|
// Exists operator cannot have pattern
|
||||||
if (!pleaf->op)
|
if (!pleaf->op) {
|
||||||
return offset;
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
|
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
// Check for boolean patterns
|
|
||||||
if (!strcmp_wd("true", &pattern[offset])) {
|
if (!strcmp_wd("true", &pattern[offset])) {
|
||||||
pleaf->ptntype = C2_L_PTINT;
|
pleaf->ptntype = C2_L_PTINT;
|
||||||
pleaf->ptnint = true;
|
pleaf->ptnint = true;
|
||||||
offset += strlen("true");
|
offset += 4; // length of "true";
|
||||||
} else if (!strcmp_wd("false", &pattern[offset])) {
|
} else if (!strcmp_wd("false", &pattern[offset])) {
|
||||||
pleaf->ptntype = C2_L_PTINT;
|
pleaf->ptntype = C2_L_PTINT;
|
||||||
pleaf->ptnint = false;
|
pleaf->ptnint = false;
|
||||||
offset += strlen("false");
|
offset += 5; // length of "false";
|
||||||
}
|
} else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0),
|
||||||
// Check for integer patterns
|
pattern + offset != endptr) {
|
||||||
else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0),
|
|
||||||
pattern + offset != endptr) {
|
|
||||||
pleaf->ptntype = C2_L_PTINT;
|
pleaf->ptntype = C2_L_PTINT;
|
||||||
offset = endptr - pattern;
|
offset = to_int_checked(endptr - pattern);
|
||||||
// Make sure we are stopping at the end of a word
|
// Make sure we are stopping at the end of a word
|
||||||
if (isalnum(pattern[offset]))
|
if (isalnum(pattern[offset])) {
|
||||||
c2_error("Trailing characters after a numeric pattern.");
|
c2_error("Trailing characters after a numeric pattern.");
|
||||||
}
|
}
|
||||||
// Check for string patterns
|
} else {
|
||||||
else {
|
// Parse string patterns
|
||||||
bool raw = false;
|
bool raw = false;
|
||||||
char delim = '\0';
|
char delim = '\0';
|
||||||
|
|
||||||
// String flags
|
// String flags
|
||||||
if ('r' == tolower(pattern[offset])) {
|
if (tolower(pattern[offset]) == 'r') {
|
||||||
raw = true;
|
raw = true;
|
||||||
++offset;
|
++offset;
|
||||||
C2H_SKIP_SPACES();
|
C2H_SKIP_SPACES();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for delimiters
|
// Check for delimiters
|
||||||
if ('\"' == pattern[offset] || '\'' == pattern[offset]) {
|
if (pattern[offset] == '\"' || pattern[offset] == '\'') {
|
||||||
pleaf->ptntype = C2_L_PTSTRING;
|
pleaf->ptntype = C2_L_PTSTRING;
|
||||||
delim = pattern[offset];
|
delim = pattern[offset];
|
||||||
++offset;
|
++offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (C2_L_PTSTRING != pleaf->ptntype)
|
if (pleaf->ptntype != C2_L_PTSTRING) {
|
||||||
c2_error("Invalid pattern type.");
|
c2_error("Invalid pattern type.");
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the string now
|
// Parse the string now
|
||||||
// We can't determine the length of the pattern, so we use the length
|
// We can't determine the length of the pattern, so we use the length
|
||||||
|
@ -876,8 +859,7 @@ static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult)
|
||||||
if (pstr != &tstr[2] || val <= 0)
|
if (pstr != &tstr[2] || val <= 0)
|
||||||
c2_error("Invalid octal/hex escape "
|
c2_error("Invalid octal/hex escape "
|
||||||
"sequence.");
|
"sequence.");
|
||||||
assert(val < 256 && val >= 0);
|
*(ptptnstr++) = to_char_checked(val);
|
||||||
*(ptptnstr++) = val;
|
|
||||||
offset += 2;
|
offset += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -929,10 +911,10 @@ fail:
|
||||||
* Parse a condition with legacy syntax.
|
* Parse a condition with legacy syntax.
|
||||||
*/
|
*/
|
||||||
static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
|
static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
unsigned plen = strlen(pattern + offset);
|
if (strlen(pattern + offset) < 4 || pattern[offset + 1] != ':' ||
|
||||||
|
!strchr(pattern + offset + 2, ':')) {
|
||||||
if (plen < 4 || ':' != pattern[offset + 1] || !strchr(pattern + offset + 2, ':'))
|
|
||||||
c2_error("Legacy parser: Invalid format.");
|
c2_error("Legacy parser: Invalid format.");
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate memory for new leaf
|
// Allocate memory for new leaf
|
||||||
auto pleaf = cmalloc(c2_l_t);
|
auto pleaf = cmalloc(c2_l_t);
|
||||||
|
@ -1000,7 +982,7 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get target atom if it's not a predefined one
|
// Get target atom if it's not a predefined one
|
||||||
if (!pleaf->predef) {
|
if (pleaf->predef == C2_L_PUNDEFINED) {
|
||||||
pleaf->tgtatom = get_atom(ps, pleaf->tgt);
|
pleaf->tgtatom = get_atom(ps, pleaf->tgt);
|
||||||
if (!pleaf->tgtatom) {
|
if (!pleaf->tgtatom) {
|
||||||
log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
|
log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
|
||||||
|
@ -1027,20 +1009,18 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
||||||
|
|
||||||
// Enable specific tracking options in compton if needed by the condition
|
// Enable specific tracking options in compton if needed by the condition
|
||||||
// TODO: Add track_leader
|
// TODO: Add track_leader
|
||||||
if (pleaf->predef) {
|
switch (pleaf->predef) {
|
||||||
switch (pleaf->predef) {
|
case C2_L_PFOCUSED: ps->o.track_focus = true; break;
|
||||||
case C2_L_PFOCUSED: ps->o.track_focus = true; break;
|
// case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break;
|
||||||
// case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break;
|
case C2_L_PNAME:
|
||||||
case C2_L_PNAME:
|
case C2_L_PCLASSG:
|
||||||
case C2_L_PCLASSG:
|
case C2_L_PCLASSI:
|
||||||
case C2_L_PCLASSI:
|
case C2_L_PROLE: ps->o.track_wdata = true; break;
|
||||||
case C2_L_PROLE: ps->o.track_wdata = true; break;
|
default: break;
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn about lower case characters in target name
|
// Warn about lower case characters in target name
|
||||||
if (!pleaf->predef) {
|
if (pleaf->predef == C2_L_PUNDEFINED) {
|
||||||
for (const char *pc = pleaf->tgt; *pc; ++pc) {
|
for (const char *pc = pleaf->tgt; *pc; ++pc) {
|
||||||
if (islower(*pc)) {
|
if (islower(*pc)) {
|
||||||
log_warn("Lowercase character in target name \"%s\".",
|
log_warn("Lowercase character in target name \"%s\".",
|
||||||
|
@ -1160,10 +1140,11 @@ c2_lptr_t *c2_free_lptr(c2_lptr_t *lp) {
|
||||||
* Get a string representation of a rule target.
|
* Get a string representation of a rule target.
|
||||||
*/
|
*/
|
||||||
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) {
|
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) {
|
||||||
if (pleaf->predef)
|
if (pleaf->predef != C2_L_PUNDEFINED) {
|
||||||
return C2_PREDEFS[pleaf->predef].name;
|
return C2_PREDEFS[pleaf->predef].name;
|
||||||
else
|
} else {
|
||||||
return pleaf->tgt;
|
return pleaf->tgt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1298,8 +1279,9 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
|
const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
|
||||||
|
|
||||||
// Return if wid is missing
|
// Return if wid is missing
|
||||||
if (!pleaf->predef && !wid)
|
if (pleaf->predef == C2_L_PUNDEFINED && !wid) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const int idx = (pleaf->index < 0 ? 0 : pleaf->index);
|
const int idx = (pleaf->index < 0 ? 0 : pleaf->index);
|
||||||
|
|
||||||
|
@ -1310,7 +1292,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
|
|
||||||
// Get the value
|
// Get the value
|
||||||
// A predefined target
|
// A predefined target
|
||||||
if (pleaf->predef) {
|
if (pleaf->predef != C2_L_PUNDEFINED) {
|
||||||
*perr = false;
|
*perr = false;
|
||||||
switch (pleaf->predef) {
|
switch (pleaf->predef) {
|
||||||
case C2_L_PID: tgt = wid; break;
|
case C2_L_PID: tgt = wid; break;
|
||||||
|
@ -1355,7 +1337,9 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
|
|
||||||
// Do comparison
|
// Do comparison
|
||||||
switch (pleaf->op) {
|
switch (pleaf->op) {
|
||||||
case C2_L_OEXISTS: *pres = (pleaf->predef ? tgt : true); break;
|
case C2_L_OEXISTS:
|
||||||
|
*pres = (pleaf->predef != C2_L_PUNDEFINED ? tgt : true);
|
||||||
|
break;
|
||||||
case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break;
|
case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break;
|
||||||
case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break;
|
case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break;
|
||||||
case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break;
|
case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break;
|
||||||
|
@ -1373,7 +1357,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
char *tgt_free = NULL;
|
char *tgt_free = NULL;
|
||||||
|
|
||||||
// A predefined target
|
// A predefined target
|
||||||
if (pleaf->predef) {
|
if (pleaf->predef != C2_L_PUNDEFINED) {
|
||||||
switch (pleaf->predef) {
|
switch (pleaf->predef) {
|
||||||
case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break;
|
case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break;
|
||||||
case C2_L_PNAME: tgt = w->name; break;
|
case C2_L_PNAME: tgt = w->name; break;
|
||||||
|
@ -1382,20 +1366,19 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
case C2_L_PROLE: tgt = w->role; break;
|
case C2_L_PROLE: tgt = w->role; break;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
}
|
}
|
||||||
}
|
} else if (pleaf->type == C2_L_TATOM) {
|
||||||
// If it's an atom type property, convert atom to string
|
// An atom type property, convert it to string
|
||||||
else if (C2_L_TATOM == pleaf->type) {
|
|
||||||
winprop_t prop =
|
winprop_t prop =
|
||||||
wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L,
|
wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L,
|
||||||
c2_get_atom_type(pleaf), pleaf->format);
|
c2_get_atom_type(pleaf), pleaf->format);
|
||||||
xcb_atom_t atom = winprop_get_int(prop);
|
xcb_atom_t atom = (xcb_atom_t)winprop_get_int(prop);
|
||||||
if (atom) {
|
if (atom) {
|
||||||
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
|
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
|
||||||
ps->c, xcb_get_atom_name(ps->c, atom), NULL);
|
ps->c, xcb_get_atom_name(ps->c, atom), NULL);
|
||||||
if (reply) {
|
if (reply) {
|
||||||
tgt_free =
|
tgt_free = strndup(
|
||||||
strndup(xcb_get_atom_name_name(reply),
|
xcb_get_atom_name_name(reply),
|
||||||
xcb_get_atom_name_name_length(reply));
|
(size_t)xcb_get_atom_name_name_length(reply));
|
||||||
free(reply);
|
free(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1403,9 +1386,8 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
tgt = tgt_free;
|
tgt = tgt_free;
|
||||||
}
|
}
|
||||||
free_winprop(&prop);
|
free_winprop(&prop);
|
||||||
}
|
} else {
|
||||||
// Otherwise, just fetch the string list
|
// Not an atom type, just fetch the string list
|
||||||
else {
|
|
||||||
char **strlst = NULL;
|
char **strlst = NULL;
|
||||||
int nstr;
|
int nstr;
|
||||||
if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) &&
|
if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) &&
|
||||||
|
@ -1456,8 +1438,10 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres,
|
||||||
} break;
|
} break;
|
||||||
case C2_L_MPCRE:
|
case C2_L_MPCRE:
|
||||||
#ifdef CONFIG_REGEX_PCRE
|
#ifdef CONFIG_REGEX_PCRE
|
||||||
*pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra,
|
assert(strlen(tgt) <= INT_MAX);
|
||||||
tgt, strlen(tgt), 0, 0, NULL, 0) >= 0);
|
*pres =
|
||||||
|
(pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra,
|
||||||
|
tgt, (int)strlen(tgt), 0, 0, NULL, 0) >= 0);
|
||||||
#else
|
#else
|
||||||
assert(0);
|
assert(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
35
src/common.h
35
src/common.h
|
@ -186,8 +186,8 @@ struct _glx_texture {
|
||||||
GLXPixmap glpixmap;
|
GLXPixmap glpixmap;
|
||||||
xcb_pixmap_t pixmap;
|
xcb_pixmap_t pixmap;
|
||||||
GLenum target;
|
GLenum target;
|
||||||
unsigned width;
|
int width;
|
||||||
unsigned height;
|
int height;
|
||||||
bool y_inverted;
|
bool y_inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ typedef struct session {
|
||||||
/// Pre-generated alpha pictures.
|
/// Pre-generated alpha pictures.
|
||||||
xcb_render_picture_t *alpha_picts;
|
xcb_render_picture_t *alpha_picts;
|
||||||
/// Time of last fading. In milliseconds.
|
/// Time of last fading. In milliseconds.
|
||||||
unsigned long fade_time;
|
long fade_time;
|
||||||
/// Head pointer of the error ignore linked list.
|
/// Head pointer of the error ignore linked list.
|
||||||
ignore_t *ignore_head;
|
ignore_t *ignore_head;
|
||||||
/// Pointer to the <code>next</code> member of tail element of the error
|
/// Pointer to the <code>next</code> member of tail element of the error
|
||||||
|
@ -416,7 +416,7 @@ typedef struct session {
|
||||||
|
|
||||||
// === Software-optimization-related ===
|
// === Software-optimization-related ===
|
||||||
/// Currently used refresh rate.
|
/// Currently used refresh rate.
|
||||||
short refresh_rate;
|
int refresh_rate;
|
||||||
/// Interval between refresh in nanoseconds.
|
/// Interval between refresh in nanoseconds.
|
||||||
long refresh_intv;
|
long refresh_intv;
|
||||||
/// Nanosecond offset of the first painting.
|
/// Nanosecond offset of the first painting.
|
||||||
|
@ -566,20 +566,20 @@ static inline int timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
|
||||||
|
|
||||||
// We use those if statement instead of a - expression because of possible
|
// We use those if statement instead of a - expression because of possible
|
||||||
// truncation problem from long to int.
|
// truncation problem from long to int.
|
||||||
{
|
auto sec = (long)(ms / MS_PER_SEC);
|
||||||
long sec = ms / MS_PER_SEC;
|
if (ptv->tv_sec > sec) {
|
||||||
if (ptv->tv_sec > sec)
|
return 1;
|
||||||
return 1;
|
}
|
||||||
if (ptv->tv_sec < sec)
|
if (ptv->tv_sec < sec) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
auto usec = (long)(ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC));
|
||||||
long usec = ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC);
|
if (ptv->tv_usec > usec) {
|
||||||
if (ptv->tv_usec > usec)
|
return 1;
|
||||||
return 1;
|
}
|
||||||
if (ptv->tv_usec < usec)
|
if (ptv->tv_usec < usec) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -712,7 +712,8 @@ _Noreturn static inline void die(const char *msg) {
|
||||||
*/
|
*/
|
||||||
static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) {
|
static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) {
|
||||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(
|
||||||
ps->c, xcb_intern_atom(ps->c, 0, strlen(atom_name), atom_name), NULL);
|
ps->c,
|
||||||
|
xcb_intern_atom(ps->c, 0, to_u16_checked(strlen(atom_name)), atom_name), NULL);
|
||||||
|
|
||||||
xcb_atom_t atom = XCB_NONE;
|
xcb_atom_t atom = XCB_NONE;
|
||||||
if (reply) {
|
if (reply) {
|
||||||
|
|
|
@ -95,3 +95,6 @@
|
||||||
#else
|
#else
|
||||||
# define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__
|
# define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
typedef unsigned int uint;
|
||||||
|
|
|
@ -108,10 +108,10 @@ static inline void free_xinerama_info(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Get current system clock in milliseconds.
|
* Get current system clock in milliseconds.
|
||||||
*/
|
*/
|
||||||
static inline uint64_t get_time_ms(void) {
|
static inline int64_t get_time_ms(void) {
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||||
return tp.tv_sec * ((uint64_t)1000ul) + tp.tv_nsec / 1000000;
|
return (int64_t)tp.tv_sec * 1000 + (int64_t)tp.tv_nsec / 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Move to x.c
|
// XXX Move to x.c
|
||||||
|
@ -202,11 +202,11 @@ static double fade_timeout(session_t *ps) {
|
||||||
if (ps->o.fade_delta + ps->fade_time < now)
|
if (ps->o.fade_delta + ps->fade_time < now)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int diff = ps->o.fade_delta + ps->fade_time - now;
|
auto diff = ps->o.fade_delta + ps->fade_time - now;
|
||||||
|
|
||||||
diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2);
|
diff = clamp(diff, 0, ps->o.fade_delta * 2);
|
||||||
|
|
||||||
return diff / 1000.0;
|
return (double)diff / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -215,7 +215,7 @@ static double fade_timeout(session_t *ps) {
|
||||||
* @param steps steps of fading
|
* @param steps steps of fading
|
||||||
* @return whether we are still in fading mode
|
* @return whether we are still in fading mode
|
||||||
*/
|
*/
|
||||||
static bool run_fade(session_t *ps, win **_w, unsigned steps) {
|
static bool run_fade(session_t *ps, win **_w, long steps) {
|
||||||
win *w = *_w;
|
win *w = *_w;
|
||||||
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
|
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
|
||||||
// We are not fading
|
// We are not fading
|
||||||
|
@ -237,11 +237,11 @@ static bool run_fade(session_t *ps, win **_w, unsigned steps) {
|
||||||
|
|
||||||
if (steps) {
|
if (steps) {
|
||||||
if (w->opacity < w->opacity_tgt) {
|
if (w->opacity < w->opacity_tgt) {
|
||||||
w->opacity = normalize_d_range(
|
w->opacity = clamp(w->opacity + ps->o.fade_in_step * (double)steps,
|
||||||
w->opacity + ps->o.fade_in_step * steps, 0.0, w->opacity_tgt);
|
0.0, w->opacity_tgt);
|
||||||
} else {
|
} else {
|
||||||
w->opacity = normalize_d_range(
|
w->opacity = clamp(w->opacity - ps->o.fade_out_step * (double)steps,
|
||||||
w->opacity - ps->o.fade_out_step * steps, w->opacity_tgt, 1);
|
w->opacity_tgt, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,8 +277,8 @@ static int should_ignore(session_t *ps, unsigned long sequence) {
|
||||||
/**
|
/**
|
||||||
* Determine the event mask for a window.
|
* Determine the event mask for a window.
|
||||||
*/
|
*/
|
||||||
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
|
uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
|
||||||
long evmask = 0;
|
uint32_t evmask = 0;
|
||||||
win *w = NULL;
|
win *w = NULL;
|
||||||
|
|
||||||
// Check if it's a mapped frame window
|
// Check if it's a mapped frame window
|
||||||
|
@ -292,7 +292,7 @@ long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
|
||||||
// Check if it's a mapped client window
|
// Check if it's a mapped client window
|
||||||
if (WIN_EVMODE_CLIENT == mode ||
|
if (WIN_EVMODE_CLIENT == mode ||
|
||||||
((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
|
((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) {
|
||||||
if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst ||
|
if (ps->o.frame_opacity > 0 || ps->o.track_wdata || ps->track_atom_lst ||
|
||||||
ps->o.detect_client_opacity)
|
ps->o.detect_client_opacity)
|
||||||
evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
|
evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +412,7 @@ static void handle_root_flags(session_t *ps) {
|
||||||
"temporarily disabled");
|
"temporarily disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ps->root_flags &= ~ROOT_FLAGS_SCREEN_CHANGE;
|
ps->root_flags &= ~(uint64_t)ROOT_FLAGS_SCREEN_CHANGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
|
||||||
*fade_running = false;
|
*fade_running = false;
|
||||||
|
|
||||||
// Fading step calculation
|
// Fading step calculation
|
||||||
unsigned long steps = 0L;
|
long steps = 0L;
|
||||||
auto now = get_time_ms();
|
auto now = get_time_ms();
|
||||||
if (ps->fade_time) {
|
if (ps->fade_time) {
|
||||||
assert(now >= ps->fade_time);
|
assert(now >= ps->fade_time);
|
||||||
|
@ -616,8 +616,9 @@ static win *paint_preprocess(session_t *ps, bool *fade_running) {
|
||||||
if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit)
|
if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit)
|
||||||
redir_stop(ps);
|
redir_stop(ps);
|
||||||
else if (!ev_is_active(&ps->unredir_timer)) {
|
else if (!ev_is_active(&ps->unredir_timer)) {
|
||||||
ev_timer_set(&ps->unredir_timer,
|
ev_timer_set(
|
||||||
ps->o.unredir_if_possible_delay / 1000.0, 0);
|
&ps->unredir_timer,
|
||||||
|
(double)ps->o.unredir_if_possible_delay / 1000.0, 0);
|
||||||
ev_timer_start(ps->loop, &ps->unredir_timer);
|
ev_timer_start(ps->loop, &ps->unredir_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1066,11 +1067,14 @@ void update_ewmh_active_win(session_t *ps) {
|
||||||
static bool register_cm(session_t *ps) {
|
static bool register_cm(session_t *ps) {
|
||||||
assert(!ps->reg_win);
|
assert(!ps->reg_win);
|
||||||
|
|
||||||
ps->reg_win =
|
ps->reg_win = xcb_generate_id(ps->c);
|
||||||
XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, XCB_NONE, XCB_NONE);
|
auto e = xcb_request_check(
|
||||||
|
ps->c, xcb_create_window_checked(ps->c, XCB_COPY_FROM_PARENT, ps->reg_win, ps->root,
|
||||||
|
0, 0, 1, 1, 0, XCB_NONE, ps->vis, 0, NULL));
|
||||||
|
|
||||||
if (!ps->reg_win) {
|
if (e) {
|
||||||
log_fatal("Failed to create window.");
|
log_fatal("Failed to create window.");
|
||||||
|
free(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,7 +1096,7 @@ static bool register_cm(session_t *ps) {
|
||||||
|
|
||||||
// Set _NET_WM_PID
|
// Set _NET_WM_PID
|
||||||
{
|
{
|
||||||
uint32_t pid = getpid();
|
auto pid = getpid();
|
||||||
xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
|
xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
|
||||||
get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1,
|
get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1,
|
||||||
&pid);
|
&pid);
|
||||||
|
@ -1108,7 +1112,7 @@ static bool register_cm(session_t *ps) {
|
||||||
if (!ps->o.no_x_selection) {
|
if (!ps->o.no_x_selection) {
|
||||||
unsigned len = strlen(REGISTER_PROP) + 2;
|
unsigned len = strlen(REGISTER_PROP) + 2;
|
||||||
int s = ps->scr;
|
int s = ps->scr;
|
||||||
Atom atom;
|
xcb_atom_t atom;
|
||||||
|
|
||||||
while (s >= 10) {
|
while (s >= 10) {
|
||||||
++len;
|
++len;
|
||||||
|
@ -1260,7 +1264,7 @@ static double swopti_handle_timeout(session_t *ps) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Add an offset so we wait until the next refresh after timeout
|
// Add an offset so we wait until the next refresh after timeout
|
||||||
return (ps->refresh_intv - offset) / 1e6;
|
return (double)(ps->refresh_intv - offset) / 1e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1768,10 +1772,13 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
||||||
XSetErrorHandler(xerror);
|
XSetErrorHandler(xerror);
|
||||||
|
|
||||||
ps->scr = DefaultScreen(ps->dpy);
|
ps->scr = DefaultScreen(ps->dpy);
|
||||||
ps->root = RootWindow(ps->dpy, ps->scr);
|
|
||||||
|
|
||||||
ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr));
|
auto screen = x_screen_of_display(ps->c, ps->scr);
|
||||||
ps->depth = DefaultDepth(ps->dpy, ps->scr);
|
ps->vis = screen->root_visual;
|
||||||
|
ps->depth = screen->root_depth;
|
||||||
|
ps->root = screen->root;
|
||||||
|
ps->root_width = screen->width_in_pixels;
|
||||||
|
ps->root_height = screen->height_in_pixels;
|
||||||
|
|
||||||
// Start listening to events on root earlier to catch all possible
|
// Start listening to events on root earlier to catch all possible
|
||||||
// root geometry changes
|
// root geometry changes
|
||||||
|
@ -1786,9 +1793,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
||||||
free(e);
|
free(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
ps->root_width = DisplayWidth(ps->dpy, ps->scr);
|
|
||||||
ps->root_height = DisplayHeight(ps->dpy, ps->scr);
|
|
||||||
|
|
||||||
xcb_prefetch_extension_data(ps->c, &xcb_render_id);
|
xcb_prefetch_extension_data(ps->c, &xcb_render_id);
|
||||||
xcb_prefetch_extension_data(ps->c, &xcb_composite_id);
|
xcb_prefetch_extension_data(ps->c, &xcb_composite_id);
|
||||||
xcb_prefetch_extension_data(ps->c, &xcb_damage_id);
|
xcb_prefetch_extension_data(ps->c, &xcb_damage_id);
|
||||||
|
|
|
@ -38,7 +38,7 @@ enum root_flags {
|
||||||
|
|
||||||
void add_damage(session_t *ps, const region_t *damage);
|
void add_damage(session_t *ps, const region_t *damage);
|
||||||
|
|
||||||
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
|
uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
|
||||||
|
|
||||||
xcb_window_t find_client_win(session_t *ps, xcb_window_t w);
|
xcb_window_t find_client_win(session_t *ps, xcb_window_t w);
|
||||||
|
|
||||||
|
|
76
src/config.c
76
src/config.c
|
@ -3,6 +3,7 @@
|
||||||
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
|
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -42,6 +43,22 @@ bool parse_long(const char *s, long *dest) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an int number.
|
||||||
|
*/
|
||||||
|
bool parse_int(const char *s, int *dest) {
|
||||||
|
long val;
|
||||||
|
if (!parse_long(s, &val)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (val > INT_MAX || val < INT_MIN) {
|
||||||
|
log_error("Number exceeded int limits: %ld", val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*dest = (int)val;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a floating-point number in from a string,
|
* Parse a floating-point number in from a string,
|
||||||
* also strips the trailing space and comma after the number.
|
* also strips the trailing space and comma after the number.
|
||||||
|
@ -82,11 +99,11 @@ conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
|
||||||
if (src == (pc = parse_readnum(src, &val)))
|
if (src == (pc = parse_readnum(src, &val)))
|
||||||
goto err1;
|
goto err1;
|
||||||
src = pc;
|
src = pc;
|
||||||
width = val;
|
width = (int)val;
|
||||||
if (src == (pc = parse_readnum(src, &val)))
|
if (src == (pc = parse_readnum(src, &val)))
|
||||||
goto err1;
|
goto err1;
|
||||||
src = pc;
|
src = pc;
|
||||||
height = val;
|
height = (int)val;
|
||||||
|
|
||||||
// Validate matrix width and height
|
// Validate matrix width and height
|
||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
|
@ -102,7 +119,7 @@ conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
|
||||||
"rendering, and/or consume lots of memory");
|
"rendering, and/or consume lots of memory");
|
||||||
|
|
||||||
// Allocate memory
|
// Allocate memory
|
||||||
conv *matrix = cvalloc(sizeof(conv) + width * height * sizeof(double));
|
conv *matrix = cvalloc(sizeof(conv) + (size_t)(width * height) * sizeof(double));
|
||||||
|
|
||||||
// Read elements
|
// Read elements
|
||||||
int skip = height / 2 * width + width / 2;
|
int skip = height / 2 * width + width / 2;
|
||||||
|
@ -276,70 +293,76 @@ bool parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
|
||||||
*/
|
*/
|
||||||
bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
|
bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
|
||||||
pixman_region32_clear(dest);
|
pixman_region32_clear(dest);
|
||||||
if (!src)
|
if (!src) {
|
||||||
return true;
|
return true;
|
||||||
if (!ps->root_width || !ps->root_height)
|
}
|
||||||
|
if (!ps->root_width || !ps->root_height) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
geometry_t geom = {.wid = ps->root_width, .hei = ps->root_height, .x = 0, .y = 0};
|
long x = 0, y = 0;
|
||||||
|
long width = ps->root_width, height = ps->root_height;
|
||||||
long val = 0L;
|
long val = 0L;
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
|
|
||||||
src = skip_space(src);
|
src = skip_space(src);
|
||||||
if (!*src)
|
if (!*src) {
|
||||||
goto parse_geometry_end;
|
goto parse_geometry_end;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse width
|
// Parse width
|
||||||
// Must be base 10, because "0x0..." may appear
|
// Must be base 10, because "0x0..." may appear
|
||||||
if (!('+' == *src || '-' == *src)) {
|
if (*src != '+' && *src != '-') {
|
||||||
val = strtol(src, &endptr, 10);
|
val = strtol(src, &endptr, 10);
|
||||||
assert(endptr);
|
assert(endptr);
|
||||||
if (src != endptr) {
|
if (src != endptr) {
|
||||||
geom.wid = val;
|
if (val < 0) {
|
||||||
if (geom.wid < 0) {
|
|
||||||
log_error("Invalid width: %s", src);
|
log_error("Invalid width: %s", src);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
width = val;
|
||||||
src = endptr;
|
src = endptr;
|
||||||
}
|
}
|
||||||
src = skip_space(src);
|
src = skip_space(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse height
|
// Parse height
|
||||||
if ('x' == *src) {
|
if (*src == 'x') {
|
||||||
++src;
|
++src;
|
||||||
val = strtol(src, &endptr, 10);
|
val = strtol(src, &endptr, 10);
|
||||||
assert(endptr);
|
assert(endptr);
|
||||||
if (src != endptr) {
|
if (src != endptr) {
|
||||||
geom.hei = val;
|
if (val < 0) {
|
||||||
if (geom.hei < 0) {
|
|
||||||
log_error("Invalid height: %s", src);
|
log_error("Invalid height: %s", src);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
height = val;
|
||||||
src = endptr;
|
src = endptr;
|
||||||
}
|
}
|
||||||
src = skip_space(src);
|
src = skip_space(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse x
|
// Parse x
|
||||||
if ('+' == *src || '-' == *src) {
|
if (*src == '+' || *src == '-') {
|
||||||
val = strtol(src, &endptr, 10);
|
val = strtol(src, &endptr, 10);
|
||||||
if (endptr && src != endptr) {
|
if (endptr && src != endptr) {
|
||||||
geom.x = val;
|
x = val;
|
||||||
if (*src == '-')
|
if (*src == '-') {
|
||||||
geom.x += ps->root_width - geom.wid;
|
x += ps->root_width - width;
|
||||||
|
}
|
||||||
src = endptr;
|
src = endptr;
|
||||||
}
|
}
|
||||||
src = skip_space(src);
|
src = skip_space(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse y
|
// Parse y
|
||||||
if ('+' == *src || '-' == *src) {
|
if (*src == '+' || *src == '-') {
|
||||||
val = strtol(src, &endptr, 10);
|
val = strtol(src, &endptr, 10);
|
||||||
if (endptr && src != endptr) {
|
if (endptr && src != endptr) {
|
||||||
geom.y = val;
|
y = val;
|
||||||
if (*src == '-')
|
if (*src == '-') {
|
||||||
geom.y += ps->root_height - geom.hei;
|
y += ps->root_height - height;
|
||||||
|
}
|
||||||
src = endptr;
|
src = endptr;
|
||||||
}
|
}
|
||||||
src = skip_space(src);
|
src = skip_space(src);
|
||||||
|
@ -351,7 +374,16 @@ bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_geometry_end:
|
parse_geometry_end:
|
||||||
pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei);
|
if (x < INT_MIN || x > INT_MAX || y < INT_MIN || y > INT_MAX) {
|
||||||
|
log_error("Geometry coordinates exceeded limits: %s", src);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (width > UINT_MAX || height > UINT_MAX) {
|
||||||
|
// less than 0 is checked for earlier
|
||||||
|
log_error("Geometry size exceeded limits: %s", src);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pixman_region32_union_rect(dest, dest, (int)x, (int)y, (uint)width, (uint)height);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/config.h
13
src/config.h
|
@ -97,7 +97,7 @@ typedef struct options_t {
|
||||||
/// when determining if a window could be unredirected.
|
/// when determining if a window could be unredirected.
|
||||||
c2_lptr_t *unredir_if_possible_blacklist;
|
c2_lptr_t *unredir_if_possible_blacklist;
|
||||||
/// Delay before unredirecting screen, in milliseconds.
|
/// Delay before unredirecting screen, in milliseconds.
|
||||||
unsigned long unredir_if_possible_delay;
|
long unredir_if_possible_delay;
|
||||||
/// Forced redirection setting through D-Bus.
|
/// Forced redirection setting through D-Bus.
|
||||||
switch_t redirected_force;
|
switch_t redirected_force;
|
||||||
/// Whether to stop painting. Controlled through D-Bus.
|
/// Whether to stop painting. Controlled through D-Bus.
|
||||||
|
@ -155,7 +155,7 @@ typedef struct options_t {
|
||||||
/// How much to fade out in a single fading step.
|
/// How much to fade out in a single fading step.
|
||||||
double fade_out_step;
|
double fade_out_step;
|
||||||
/// Fading time delta. In milliseconds.
|
/// Fading time delta. In milliseconds.
|
||||||
unsigned long fade_delta;
|
int fade_delta;
|
||||||
/// Whether to disable fading on window open/close.
|
/// Whether to disable fading on window open/close.
|
||||||
bool no_fading_openclose;
|
bool no_fading_openclose;
|
||||||
/// Whether to disable fading on ARGB managed destroyed windows.
|
/// Whether to disable fading on ARGB managed destroyed windows.
|
||||||
|
@ -227,10 +227,11 @@ typedef struct options_t {
|
||||||
|
|
||||||
extern const char *const BACKEND_STRS[NUM_BKEND + 1];
|
extern const char *const BACKEND_STRS[NUM_BKEND + 1];
|
||||||
|
|
||||||
attr_warn_unused_result bool parse_long(const char *, long *);
|
bool must_use parse_long(const char *, long *);
|
||||||
attr_warn_unused_result bool parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
|
bool must_use parse_int(const char *, int *);
|
||||||
attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *);
|
bool must_use parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
|
||||||
attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *);
|
bool must_use parse_geometry(session_t *, const char *, region_t *);
|
||||||
|
bool must_use parse_rule_opacity(c2_lptr_t **, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a pattern to a condition linked list.
|
* Add a pattern to a condition linked list.
|
||||||
|
|
|
@ -295,7 +295,12 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
// --detect-client-opacity
|
// --detect-client-opacity
|
||||||
lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity);
|
lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity);
|
||||||
// --refresh-rate
|
// --refresh-rate
|
||||||
config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate);
|
if (config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate)) {
|
||||||
|
if (opt->refresh_rate < 0) {
|
||||||
|
log_warn("Invalid refresh rate %d, fallback to 0", opt->refresh_rate);
|
||||||
|
opt->refresh_rate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
// --vsync
|
// --vsync
|
||||||
if (config_lookup_string(&cfg, "vsync", &sval)) {
|
if (config_lookup_string(&cfg, "vsync", &sval)) {
|
||||||
opt->vsync = parse_vsync(sval);
|
opt->vsync = parse_vsync(sval);
|
||||||
|
@ -337,8 +342,13 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
// --unredir-if-possible
|
// --unredir-if-possible
|
||||||
lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible);
|
lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible);
|
||||||
// --unredir-if-possible-delay
|
// --unredir-if-possible-delay
|
||||||
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival))
|
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) {
|
||||||
opt->unredir_if_possible_delay = ival;
|
if (ival < 0) {
|
||||||
|
log_warn("Invalid unredir-if-possible-delay %d", ival);
|
||||||
|
} else {
|
||||||
|
opt->unredir_if_possible_delay = ival;
|
||||||
|
}
|
||||||
|
}
|
||||||
// --inactive-dim-fixed
|
// --inactive-dim-fixed
|
||||||
lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed);
|
lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed);
|
||||||
// --detect-transient
|
// --detect-transient
|
||||||
|
|
36
src/dbus.c
36
src/dbus.c
|
@ -41,9 +41,9 @@ typedef uint32_t cdbus_window_t;
|
||||||
#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32
|
#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32
|
||||||
#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING
|
#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING
|
||||||
|
|
||||||
typedef uint16_t cdbus_enum_t;
|
typedef uint32_t cdbus_enum_t;
|
||||||
#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16
|
#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT32
|
||||||
#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING
|
#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT32_AS_STRING
|
||||||
|
|
||||||
#define CDBUS_SERVICE_NAME "com.github.chjj.compton"
|
#define CDBUS_SERVICE_NAME "com.github.chjj.compton"
|
||||||
#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME
|
#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME
|
||||||
|
@ -610,6 +610,14 @@ static inline bool cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a reply with an int32 argument, cast from a long.
|
||||||
|
*/
|
||||||
|
static inline bool cdbus_reply_int32l(session_t *ps, DBusMessage *srcmsg, long val) {
|
||||||
|
int32_t tmp = (int32_t)val;
|
||||||
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &tmp);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with an uint32 argument.
|
* Send a reply with an uint32 argument.
|
||||||
*/
|
*/
|
||||||
|
@ -786,12 +794,12 @@ static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_m_win_get_do(class_general, cdbus_reply_string);
|
cdbus_m_win_get_do(class_general, cdbus_reply_string);
|
||||||
cdbus_m_win_get_do(role, cdbus_reply_string);
|
cdbus_m_win_get_do(role, cdbus_reply_string);
|
||||||
|
|
||||||
cdbus_m_win_get_do(opacity, cdbus_reply_uint32);
|
cdbus_m_win_get_do(opacity, cdbus_reply_double);
|
||||||
cdbus_m_win_get_do(opacity_tgt, cdbus_reply_uint32);
|
cdbus_m_win_get_do(opacity_tgt, cdbus_reply_double);
|
||||||
cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool);
|
cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool);
|
||||||
cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32);
|
cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32);
|
||||||
cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool);
|
cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool);
|
||||||
cdbus_m_win_get_do(opacity_set, cdbus_reply_uint32);
|
cdbus_m_win_get_do(opacity_set, cdbus_reply_double);
|
||||||
|
|
||||||
cdbus_m_win_get_do(frame_opacity, cdbus_reply_double);
|
cdbus_m_win_get_do(frame_opacity, cdbus_reply_double);
|
||||||
if (!strcmp("left_width", target)) {
|
if (!strcmp("left_width", target)) {
|
||||||
|
@ -986,7 +994,7 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool);
|
cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool);
|
||||||
cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32);
|
cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32l);
|
||||||
cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum);
|
cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum);
|
||||||
cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum);
|
cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum);
|
||||||
cdbus_m_opts_get_do(logpath, cdbus_reply_string);
|
cdbus_m_opts_get_do(logpath, cdbus_reply_string);
|
||||||
|
@ -1010,8 +1018,8 @@ static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool);
|
cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool);
|
||||||
|
|
||||||
cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32);
|
cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32);
|
||||||
cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32);
|
cdbus_m_opts_get_do(fade_in_step, cdbus_reply_double);
|
||||||
cdbus_m_opts_get_do(fade_out_step, cdbus_reply_int32);
|
cdbus_m_opts_get_do(fade_out_step, cdbus_reply_double);
|
||||||
cdbus_m_opts_get_do(no_fading_openclose, cdbus_reply_bool);
|
cdbus_m_opts_get_do(no_fading_openclose, cdbus_reply_bool);
|
||||||
|
|
||||||
cdbus_m_opts_get_do(blur_background, cdbus_reply_bool);
|
cdbus_m_opts_get_do(blur_background, cdbus_reply_bool);
|
||||||
|
@ -1066,10 +1074,14 @@ static bool cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
|
||||||
|
|
||||||
// fade_delta
|
// fade_delta
|
||||||
if (!strcmp("fade_delta", target)) {
|
if (!strcmp("fade_delta", target)) {
|
||||||
int32_t val = 0.0;
|
int32_t val = 0;
|
||||||
if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val))
|
if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) {
|
||||||
return false;
|
return false;
|
||||||
ps->o.fade_delta = max_i(val, 1);
|
}
|
||||||
|
if (val <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ps->o.fade_delta = max2(val, 1);
|
||||||
goto cdbus_process_opts_set_success;
|
goto cdbus_process_opts_set_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/event.c
10
src/event.c
|
@ -4,8 +4,8 @@
|
||||||
#include <X11/Xlibint.h>
|
#include <X11/Xlibint.h>
|
||||||
#include <X11/extensions/sync.h>
|
#include <X11/extensions/sync.h>
|
||||||
|
|
||||||
#include "compiler.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
#include "compton.h"
|
#include "compton.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -93,7 +93,7 @@ static inline xcb_window_t attr_pure ev_window(session_t *ps, xcb_generic_event_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char * ev_name(session_t *ps, xcb_generic_event_t *ev) {
|
static inline const char *ev_name(session_t *ps, xcb_generic_event_t *ev) {
|
||||||
static char buf[128];
|
static char buf[128];
|
||||||
switch (ev->response_type & 0x7f) {
|
switch (ev->response_type & 0x7f) {
|
||||||
CASESTRRET(FocusIn);
|
CASESTRRET(FocusIn);
|
||||||
|
@ -363,7 +363,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
|
||||||
}
|
}
|
||||||
|
|
||||||
// If frame extents property changes
|
// If frame extents property changes
|
||||||
if (ps->o.frame_opacity && ev->atom == ps->atom_frame_extents) {
|
if (ps->o.frame_opacity > 0 && ev->atom == ps->atom_frame_extents) {
|
||||||
win *w = find_toplevel(ps, ev->window);
|
win *w = find_toplevel(ps, ev->window);
|
||||||
if (w) {
|
if (w) {
|
||||||
win_update_frame_extents(ps, w, ev->window);
|
win_update_frame_extents(ps, w, ev->window);
|
||||||
|
@ -441,10 +441,10 @@ static inline void repair_win(session_t *ps, win *w) {
|
||||||
xcb_xfixes_region_t tmp = xcb_generate_id(ps->c);
|
xcb_xfixes_region_t tmp = xcb_generate_id(ps->c);
|
||||||
xcb_xfixes_create_region(ps->c, tmp, 0, NULL);
|
xcb_xfixes_create_region(ps->c, tmp, 0, NULL);
|
||||||
set_ignore_cookie(ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp));
|
set_ignore_cookie(ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp));
|
||||||
xcb_xfixes_translate_region(ps->c, tmp, w->g.x + w->g.border_width,
|
|
||||||
w->g.y + w->g.border_width);
|
|
||||||
x_fetch_region(ps->c, tmp, &parts);
|
x_fetch_region(ps->c, tmp, &parts);
|
||||||
xcb_xfixes_destroy_region(ps->c, tmp);
|
xcb_xfixes_destroy_region(ps->c, tmp);
|
||||||
|
pixman_region32_translate(&parts, w->g.x + w->g.border_width,
|
||||||
|
w->g.y + w->g.border_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
w->ever_damaged = true;
|
w->ever_damaged = true;
|
||||||
|
|
22
src/kernel.c
22
src/kernel.c
|
@ -14,20 +14,10 @@ double sum_kernel(const conv *map, int x, int y, int width, int height) {
|
||||||
double ret = 0;
|
double ret = 0;
|
||||||
|
|
||||||
// Compute sum of values which are "in range"
|
// Compute sum of values which are "in range"
|
||||||
int xstart = x, xend = width + x;
|
int xstart = normalize_i_range(x, 0, map->w),
|
||||||
if (xstart < 0) {
|
xend = normalize_i_range(width + x, 0, map->w);
|
||||||
xstart = 0;
|
int ystart = normalize_i_range(y, 0, map->h),
|
||||||
}
|
yend = normalize_i_range(height + y, 0, map->h);
|
||||||
if (xend > map->w) {
|
|
||||||
xend = map->w;
|
|
||||||
}
|
|
||||||
int ystart = y, yend = height + y;
|
|
||||||
if (ystart < 0) {
|
|
||||||
ystart = 0;
|
|
||||||
}
|
|
||||||
if (yend > map->h) {
|
|
||||||
yend = map->h;
|
|
||||||
}
|
|
||||||
assert(yend >= ystart && xend >= xstart);
|
assert(yend >= ystart && xend >= xstart);
|
||||||
|
|
||||||
int d = map->w;
|
int d = map->w;
|
||||||
|
@ -70,11 +60,11 @@ static double attr_const gaussian(double r, double x, double y) {
|
||||||
|
|
||||||
conv *gaussian_kernel(double r) {
|
conv *gaussian_kernel(double r) {
|
||||||
conv *c;
|
conv *c;
|
||||||
int size = r * 2 + 1;
|
int size = (int)r * 2 + 1;
|
||||||
int center = size / 2;
|
int center = size / 2;
|
||||||
double t;
|
double t;
|
||||||
|
|
||||||
c = cvalloc(sizeof(conv) + size * size * sizeof(double));
|
c = cvalloc(sizeof(conv) + (size_t)(size * size) * sizeof(double));
|
||||||
c->w = c->h = size;
|
c->w = c->h = size;
|
||||||
c->rsum = NULL;
|
c->rsum = NULL;
|
||||||
t = 0.0;
|
t = 0.0;
|
||||||
|
|
19
src/log.c
19
src/log.c
|
@ -150,11 +150,13 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
size_t blen = vasprintf(&buf, fmt, args);
|
int blen = vasprintf(&buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if (!buf)
|
if (blen < 0 || !buf) {
|
||||||
|
free(buf);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
timespec_get(&ts, TIME_UTC);
|
timespec_get(&ts, TIME_UTC);
|
||||||
|
@ -163,9 +165,10 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
|
||||||
strftime(time_buf, sizeof time_buf, "%x %T", tm);
|
strftime(time_buf, sizeof time_buf, "%x %T", tm);
|
||||||
|
|
||||||
char *time = NULL;
|
char *time = NULL;
|
||||||
size_t tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000);
|
int tlen = asprintf(&time, "%s.%03ld", time_buf, ts.tv_nsec / 1000000);
|
||||||
if (!time) {
|
if (tlen < 0 || !time) {
|
||||||
free(buf);
|
free(buf);
|
||||||
|
free(time);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +193,7 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
|
||||||
head->ops->writev(
|
head->ops->writev(
|
||||||
head,
|
head,
|
||||||
(struct iovec[]){{.iov_base = "[ ", .iov_len = 2},
|
(struct iovec[]){{.iov_base = "[ ", .iov_len = 2},
|
||||||
{.iov_base = time, .iov_len = tlen},
|
{.iov_base = time, .iov_len = (size_t)tlen},
|
||||||
{.iov_base = " ", .iov_len = 1},
|
{.iov_base = " ", .iov_len = 1},
|
||||||
{.iov_base = (void *)func, .iov_len = flen},
|
{.iov_base = (void *)func, .iov_len = flen},
|
||||||
{.iov_base = " ", .iov_len = 1},
|
{.iov_base = " ", .iov_len = 1},
|
||||||
|
@ -198,7 +201,7 @@ attr_printf(4, 5) void log_printf(struct log *l, int level, const char *func,
|
||||||
{.iov_base = (void *)log_level_str, .iov_len = llen},
|
{.iov_base = (void *)log_level_str, .iov_len = llen},
|
||||||
{.iov_base = (void *)s, .iov_len = slen},
|
{.iov_base = (void *)s, .iov_len = slen},
|
||||||
{.iov_base = " ] ", .iov_len = 3},
|
{.iov_base = " ] ", .iov_len = 3},
|
||||||
{.iov_base = buf, .iov_len = blen},
|
{.iov_base = buf, .iov_len = (size_t)blen},
|
||||||
{.iov_base = "\n", .iov_len = 1}},
|
{.iov_base = "\n", .iov_len = 1}},
|
||||||
11);
|
11);
|
||||||
head = head->next;
|
head = head->next;
|
||||||
|
@ -329,12 +332,12 @@ struct log_target *stderr_logger_new(void) {
|
||||||
/// such as apitrace
|
/// such as apitrace
|
||||||
struct gl_string_marker_logger {
|
struct gl_string_marker_logger {
|
||||||
struct log_target tgt;
|
struct log_target tgt;
|
||||||
void (*gl_string_marker)(GLsizei len, const char *);
|
PFNGLSTRINGMARKERGREMEDYPROC gl_string_marker;
|
||||||
};
|
};
|
||||||
|
|
||||||
void gl_string_marker_logger_write(struct log_target *tgt, const char *str, size_t len) {
|
void gl_string_marker_logger_write(struct log_target *tgt, const char *str, size_t len) {
|
||||||
auto g = (struct gl_string_marker_logger *)tgt;
|
auto g = (struct gl_string_marker_logger *)tgt;
|
||||||
g->gl_string_marker(len, str);
|
g->gl_string_marker((GLsizei)len, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct log_ops gl_string_marker_logger_ops = {
|
static const struct log_ops gl_string_marker_logger_ops = {
|
||||||
|
|
220
src/opengl.c
220
src/opengl.c
|
@ -323,45 +323,42 @@ bool glx_init_blur(session_t *ps) {
|
||||||
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
|
glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i];
|
||||||
|
|
||||||
// Build shader
|
// Build shader
|
||||||
{
|
int width = kern->w, height = kern->h;
|
||||||
int width = kern->w, height = kern->h;
|
int nele = width * height - 1;
|
||||||
int nele = width * height - 1;
|
assert(nele >= 0);
|
||||||
unsigned int len =
|
auto len =
|
||||||
strlen(FRAG_SHADER_BLUR_PREFIX) +
|
strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) +
|
||||||
strlen(sampler_type) + strlen(extension) +
|
strlen(extension) +
|
||||||
(strlen(shader_add) + strlen(texture_func) + 42) * nele +
|
(strlen(shader_add) + strlen(texture_func) + 42) * (uint)nele +
|
||||||
strlen(FRAG_SHADER_BLUR_SUFFIX) +
|
strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1;
|
||||||
strlen(texture_func) + 12 + 1;
|
char *shader_str = ccalloc(len, char);
|
||||||
char *shader_str = ccalloc(len, char);
|
char *pc = shader_str;
|
||||||
char *pc = shader_str;
|
sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type);
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type);
|
pc += strlen(pc);
|
||||||
pc += strlen(pc);
|
assert(strlen(shader_str) < len);
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
|
|
||||||
double sum = 0.0;
|
double sum = 0.0;
|
||||||
for (int j = 0; j < height; ++j) {
|
for (int j = 0; j < height; ++j) {
|
||||||
for (int k = 0; k < width; ++k) {
|
for (int k = 0; k < width; ++k) {
|
||||||
if (height / 2 == j && width / 2 == k)
|
if (height / 2 == j && width / 2 == k)
|
||||||
continue;
|
continue;
|
||||||
double val = kern->data[j * width + k];
|
double val = kern->data[j * width + k];
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
sum += val;
|
|
||||||
sprintf(pc, shader_add, val, texture_func,
|
|
||||||
k - width / 2, j - height / 2);
|
|
||||||
pc += strlen(pc);
|
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
}
|
}
|
||||||
|
sum += val;
|
||||||
|
sprintf(pc, shader_add, val, texture_func,
|
||||||
|
k - width / 2, j - height / 2);
|
||||||
|
pc += strlen(pc);
|
||||||
|
assert(strlen(shader_str) < len);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
|
||||||
assert(strlen(shader_str) < len);
|
|
||||||
ppass->frag_shader =
|
|
||||||
gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
|
||||||
free(shader_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
||||||
|
assert(strlen(shader_str) < len);
|
||||||
|
ppass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
||||||
|
free(shader_str);
|
||||||
|
|
||||||
if (!ppass->frag_shader) {
|
if (!ppass->frag_shader) {
|
||||||
log_error("Failed to create fragment shader %d.", i);
|
log_error("Failed to create fragment shader %d.", i);
|
||||||
free(extension);
|
free(extension);
|
||||||
|
@ -443,8 +440,8 @@ bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fsha
|
||||||
/**
|
/**
|
||||||
* Bind a X pixmap to an OpenGL texture.
|
* Bind a X pixmap to an OpenGL texture.
|
||||||
*/
|
*/
|
||||||
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width,
|
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, int width,
|
||||||
unsigned height, bool repeat, const struct glx_fbconfig_info *fbcfg) {
|
int height, bool repeat, const struct glx_fbconfig_info *fbcfg) {
|
||||||
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -480,25 +477,27 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create GLX pixmap
|
// Create GLX pixmap
|
||||||
unsigned depth = 0;
|
int depth = 0;
|
||||||
if (!ptex->glpixmap) {
|
if (!ptex->glpixmap) {
|
||||||
need_release = false;
|
need_release = false;
|
||||||
|
|
||||||
// Retrieve pixmap parameters, if they aren't provided
|
// Retrieve pixmap parameters, if they aren't provided
|
||||||
if (!(width && height)) {
|
if (!width || !height) {
|
||||||
Window rroot = None;
|
auto r = xcb_get_geometry_reply(
|
||||||
int rx = 0, ry = 0;
|
ps->c, xcb_get_geometry(ps->c, pixmap), NULL);
|
||||||
unsigned rbdwid = 0;
|
if (!r) {
|
||||||
if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, &width,
|
|
||||||
&height, &rbdwid, &depth)) {
|
|
||||||
log_error("Failed to query info of pixmap %#010x.", pixmap);
|
log_error("Failed to query info of pixmap %#010x.", pixmap);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (depth > OPENGL_MAX_DEPTH) {
|
if (r->depth > OPENGL_MAX_DEPTH) {
|
||||||
log_error("Requested depth %d higher than %d.", depth,
|
log_error("Requested depth %d higher than %d.", depth,
|
||||||
OPENGL_MAX_DEPTH);
|
OPENGL_MAX_DEPTH);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
depth = r->depth;
|
||||||
|
width = r->width;
|
||||||
|
height = r->height;
|
||||||
|
free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine texture target, copied from compiz
|
// Determine texture target, copied from compiz
|
||||||
|
@ -522,7 +521,7 @@ bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
GLX_TEXTURE_FORMAT_EXT,
|
GLX_TEXTURE_FORMAT_EXT,
|
||||||
fbcfg->texture_fmt,
|
fbcfg->texture_fmt,
|
||||||
GLX_TEXTURE_TARGET_EXT,
|
GLX_TEXTURE_TARGET_EXT,
|
||||||
tex_tgt,
|
(GLint)tex_tgt,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -636,7 +635,8 @@ void glx_set_clip(session_t *ps, const region_t *reg) {
|
||||||
region_t reg_new; \
|
region_t reg_new; \
|
||||||
int nrects; \
|
int nrects; \
|
||||||
const rect_t *rects; \
|
const rect_t *rects; \
|
||||||
pixman_region32_init_rect(®_new, dx, dy, width, height); \
|
assert(width >= 0 && height >= 0); \
|
||||||
|
pixman_region32_init_rect(®_new, dx, dy, (uint)width, (uint)height); \
|
||||||
pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \
|
pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \
|
||||||
rects = pixman_region32_rectangles(®_new, &nrects); \
|
rects = pixman_region32_rectangles(®_new, &nrects); \
|
||||||
glBegin(GL_QUADS); \
|
glBegin(GL_QUADS); \
|
||||||
|
@ -704,13 +704,13 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2;
|
inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2;
|
||||||
inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2;
|
inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2;
|
||||||
}
|
}
|
||||||
inc_x = min_i(ps->o.resize_damage, inc_x);
|
inc_x = min2(ps->o.resize_damage, inc_x);
|
||||||
inc_y = min_i(ps->o.resize_damage, inc_y);
|
inc_y = min2(ps->o.resize_damage, inc_y);
|
||||||
|
|
||||||
mdx = max_i(dx - inc_x, 0);
|
mdx = max2(dx - inc_x, 0);
|
||||||
mdy = max_i(dy - inc_y, 0);
|
mdy = max2(dy - inc_y, 0);
|
||||||
int mdx2 = min_i(dx + width + inc_x, ps->root_width),
|
int mdx2 = min2(dx + width + inc_x, ps->root_width),
|
||||||
mdy2 = min_i(dy + height + inc_y, ps->root_height);
|
mdy2 = min2(dy + height + inc_y, ps->root_height);
|
||||||
mwidth = mdx2 - mdx;
|
mwidth = mdx2 - mdx;
|
||||||
mheight = mdy2 - mdy;
|
mheight = mdy2 - mdy;
|
||||||
}
|
}
|
||||||
|
@ -763,9 +763,9 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
|
|
||||||
// Texture scaling factor
|
// Texture scaling factor
|
||||||
GLfloat texfac_x = 1.0f, texfac_y = 1.0f;
|
GLfloat texfac_x = 1.0f, texfac_y = 1.0f;
|
||||||
if (GL_TEXTURE_2D == tex_tgt) {
|
if (tex_tgt == GL_TEXTURE_2D) {
|
||||||
texfac_x /= mwidth;
|
texfac_x /= (GLfloat)mwidth;
|
||||||
texfac_y /= mheight;
|
texfac_y /= (GLfloat)mheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paint it back
|
// Paint it back
|
||||||
|
@ -816,39 +816,37 @@ bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
if (ppass->unifm_factor_center >= 0)
|
if (ppass->unifm_factor_center >= 0)
|
||||||
glUniform1f(ppass->unifm_factor_center, factor_center);
|
glUniform1f(ppass->unifm_factor_center, factor_center);
|
||||||
|
|
||||||
{
|
P_PAINTREG_START(crect) {
|
||||||
P_PAINTREG_START(crect) {
|
auto rx = (GLfloat)(crect.x1 - mdx) * texfac_x;
|
||||||
const GLfloat rx = (crect.x1 - mdx) * texfac_x;
|
auto ry = (GLfloat)(mheight - (crect.y1 - mdy)) * texfac_y;
|
||||||
const GLfloat ry = (mheight - (crect.y1 - mdy)) * texfac_y;
|
auto rxe = rx + (GLfloat)(crect.x2 - crect.x1) * texfac_x;
|
||||||
const GLfloat rxe = rx + (crect.x2 - crect.x1) * texfac_x;
|
auto rye = ry - (GLfloat)(crect.y2 - crect.y1) * texfac_y;
|
||||||
const GLfloat rye = ry - (crect.y2 - crect.y1) * texfac_y;
|
auto rdx = (GLfloat)(crect.x1 - mdx);
|
||||||
GLfloat rdx = crect.x1 - mdx;
|
auto rdy = (GLfloat)(mheight - crect.y1 + mdy);
|
||||||
GLfloat rdy = mheight - crect.y1 + mdy;
|
if (last_pass) {
|
||||||
if (last_pass) {
|
rdx = (GLfloat)crect.x1;
|
||||||
rdx = crect.x1;
|
rdy = (GLfloat)(ps->root_height - crect.y1);
|
||||||
rdy = ps->root_height - crect.y1;
|
|
||||||
}
|
|
||||||
GLfloat rdxe = rdx + (crect.x2 - crect.x1);
|
|
||||||
GLfloat rdye = rdy - (crect.y2 - crect.y1);
|
|
||||||
|
|
||||||
// log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry,
|
|
||||||
// rxe, rye, rdx,
|
|
||||||
// rdy, rdxe, rdye);
|
|
||||||
|
|
||||||
glTexCoord2f(rx, ry);
|
|
||||||
glVertex3f(rdx, rdy, z);
|
|
||||||
|
|
||||||
glTexCoord2f(rxe, ry);
|
|
||||||
glVertex3f(rdxe, rdy, z);
|
|
||||||
|
|
||||||
glTexCoord2f(rxe, rye);
|
|
||||||
glVertex3f(rdxe, rdye, z);
|
|
||||||
|
|
||||||
glTexCoord2f(rx, rye);
|
|
||||||
glVertex3f(rdx, rdye, z);
|
|
||||||
}
|
}
|
||||||
P_PAINTREG_END();
|
auto rdxe = rdx + (GLfloat)(crect.x2 - crect.x1);
|
||||||
|
auto rdye = rdy - (GLfloat)(crect.y2 - crect.y1);
|
||||||
|
|
||||||
|
// log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry,
|
||||||
|
// rxe, rye, rdx,
|
||||||
|
// rdy, rdxe, rdye);
|
||||||
|
|
||||||
|
glTexCoord2f(rx, ry);
|
||||||
|
glVertex3f(rdx, rdy, z);
|
||||||
|
|
||||||
|
glTexCoord2f(rxe, ry);
|
||||||
|
glVertex3f(rdxe, rdy, z);
|
||||||
|
|
||||||
|
glTexCoord2f(rxe, rye);
|
||||||
|
glVertex3f(rdxe, rdye, z);
|
||||||
|
|
||||||
|
glTexCoord2f(rx, rye);
|
||||||
|
glVertex3f(rdx, rdye, z);
|
||||||
}
|
}
|
||||||
|
P_PAINTREG_END();
|
||||||
|
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
|
||||||
|
@ -880,7 +878,7 @@ glx_blur_dst_end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, int z,
|
||||||
GLfloat factor, const region_t *reg_tgt) {
|
GLfloat factor, const region_t *reg_tgt) {
|
||||||
// It's possible to dim in glx_render(), but it would be over-complicated
|
// It's possible to dim in glx_render(), but it would be over-complicated
|
||||||
// considering all those mess in color negation and modulation
|
// considering all those mess in color negation and modulation
|
||||||
|
@ -888,21 +886,19 @@ bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glColor4f(0.0f, 0.0f, 0.0f, factor);
|
glColor4f(0.0f, 0.0f, 0.0f, factor);
|
||||||
|
|
||||||
{
|
P_PAINTREG_START(crect) {
|
||||||
P_PAINTREG_START(crect) {
|
// XXX what does all of these variables mean?
|
||||||
// XXX what does all of these variables mean?
|
GLint rdx = crect.x1;
|
||||||
GLint rdx = crect.x1;
|
GLint rdy = ps->root_height - crect.y1;
|
||||||
GLint rdy = ps->root_height - crect.y1;
|
GLint rdxe = rdx + (crect.x2 - crect.x1);
|
||||||
GLint rdxe = rdx + (crect.x2 - crect.x1);
|
GLint rdye = rdy - (crect.y2 - crect.y1);
|
||||||
GLint rdye = rdy - (crect.y2 - crect.y1);
|
|
||||||
|
|
||||||
glVertex3i(rdx, rdy, z);
|
glVertex3i(rdx, rdy, z);
|
||||||
glVertex3i(rdxe, rdy, z);
|
glVertex3i(rdxe, rdy, z);
|
||||||
glVertex3i(rdxe, rdye, z);
|
glVertex3i(rdxe, rdye, z);
|
||||||
glVertex3i(rdx, rdye, z);
|
glVertex3i(rdx, rdye, z);
|
||||||
}
|
|
||||||
P_PAINTREG_END();
|
|
||||||
}
|
}
|
||||||
|
P_PAINTREG_END();
|
||||||
|
|
||||||
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
|
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
@ -941,7 +937,7 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
|
||||||
// This is all weird, but X Render is using premultiplied ARGB format, and
|
// This is all weird, but X Render is using premultiplied ARGB format, and
|
||||||
// we need to use those things to correct it. Thanks to derhass for help.
|
// we need to use those things to correct it. Thanks to derhass for help.
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glColor4f(opacity, opacity, opacity, opacity);
|
glColor4d(opacity, opacity, opacity, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_prog) {
|
if (!has_prog) {
|
||||||
|
@ -1023,7 +1019,7 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
|
||||||
assert(pprogram->prog);
|
assert(pprogram->prog);
|
||||||
glUseProgram(pprogram->prog);
|
glUseProgram(pprogram->prog);
|
||||||
if (pprogram->unifm_opacity >= 0)
|
if (pprogram->unifm_opacity >= 0)
|
||||||
glUniform1f(pprogram->unifm_opacity, opacity);
|
glUniform1f(pprogram->unifm_opacity, (float)opacity);
|
||||||
if (pprogram->unifm_invert_color >= 0)
|
if (pprogram->unifm_invert_color >= 0)
|
||||||
glUniform1i(pprogram->unifm_invert_color, neg);
|
glUniform1i(pprogram->unifm_invert_color, neg);
|
||||||
if (pprogram->unifm_tex >= 0)
|
if (pprogram->unifm_tex >= 0)
|
||||||
|
@ -1045,17 +1041,17 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
|
||||||
{
|
{
|
||||||
P_PAINTREG_START(crect) {
|
P_PAINTREG_START(crect) {
|
||||||
// XXX explain these variables
|
// XXX explain these variables
|
||||||
GLfloat rx = (double)(crect.x1 - dx + x);
|
auto rx = (GLfloat)(crect.x1 - dx + x);
|
||||||
GLfloat ry = (double)(crect.y1 - dy + y);
|
auto ry = (GLfloat)(crect.y1 - dy + y);
|
||||||
GLfloat rxe = rx + (double)(crect.x2 - crect.x1);
|
auto rxe = rx + (GLfloat)(crect.x2 - crect.x1);
|
||||||
GLfloat rye = ry + (double)(crect.y2 - crect.y1);
|
auto rye = ry + (GLfloat)(crect.y2 - crect.y1);
|
||||||
// Rectangle textures have [0-w] [0-h] while 2D texture has [0-1]
|
// Rectangle textures have [0-w] [0-h] while 2D texture has [0-1]
|
||||||
// [0-1] Thanks to amonakov for pointing out!
|
// [0-1] Thanks to amonakov for pointing out!
|
||||||
if (GL_TEXTURE_2D == ptex->target) {
|
if (GL_TEXTURE_2D == ptex->target) {
|
||||||
rx = rx / ptex->width;
|
rx = rx / (GLfloat)ptex->width;
|
||||||
ry = ry / ptex->height;
|
ry = ry / (GLfloat)ptex->height;
|
||||||
rxe = rxe / ptex->width;
|
rxe = rxe / (GLfloat)ptex->width;
|
||||||
rye = rye / ptex->height;
|
rye = rye / (GLfloat)ptex->height;
|
||||||
}
|
}
|
||||||
GLint rdx = crect.x1;
|
GLint rdx = crect.x1;
|
||||||
GLint rdy = ps->root_height - crect.y1;
|
GLint rdy = ps->root_height - crect.y1;
|
||||||
|
@ -1065,8 +1061,8 @@ bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx,
|
||||||
// Invert Y if needed, this may not work as expected, though. I
|
// Invert Y if needed, this may not work as expected, though. I
|
||||||
// don't have such a FBConfig to test with.
|
// don't have such a FBConfig to test with.
|
||||||
if (!ptex->y_inverted) {
|
if (!ptex->y_inverted) {
|
||||||
ry = 1.0 - ry;
|
ry = 1.0f - ry;
|
||||||
rye = 1.0 - rye;
|
rye = 1.0f - rye;
|
||||||
}
|
}
|
||||||
|
|
||||||
// log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx,
|
// log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx,
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <xcb/render.h>
|
#include <xcb/render.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, int z,
|
||||||
GLfloat factor, const region_t *reg_tgt);
|
GLfloat factor, const region_t *reg_tgt);
|
||||||
|
|
||||||
bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy,
|
bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy,
|
||||||
|
@ -46,8 +46,8 @@ bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fsha
|
||||||
glx_prog_main_t *pprogram);
|
glx_prog_main_t *pprogram);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width,
|
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, int width,
|
||||||
unsigned height, bool repeat, const struct glx_fbconfig_info *);
|
int height, bool repeat, const struct glx_fbconfig_info *);
|
||||||
|
|
||||||
void glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
|
void glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
|
||||||
|
|
||||||
|
|
|
@ -483,7 +483,6 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
"open a bug report.";
|
"open a bug report.";
|
||||||
optind = 1;
|
optind = 1;
|
||||||
while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
|
while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
|
||||||
long val = 0;
|
|
||||||
switch (o) {
|
switch (o) {
|
||||||
#define P_CASEBOOL(idx, option) \
|
#define P_CASEBOOL(idx, option) \
|
||||||
case idx: \
|
case idx: \
|
||||||
|
@ -491,9 +490,15 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
break
|
break
|
||||||
#define P_CASELONG(idx, option) \
|
#define P_CASELONG(idx, option) \
|
||||||
case idx: \
|
case idx: \
|
||||||
if (!parse_long(optarg, &val)) \
|
if (!parse_long(optarg, &opt->option)) { \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
opt->option = val; \
|
} \
|
||||||
|
break
|
||||||
|
#define P_CASEINT(idx, option) \
|
||||||
|
case idx: \
|
||||||
|
if (!parse_int(optarg, &opt->option)) { \
|
||||||
|
exit(1); \
|
||||||
|
} \
|
||||||
break
|
break
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
@ -511,7 +516,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
case 320:
|
case 320:
|
||||||
// These options are handled by get_early_config()
|
// These options are handled by get_early_config()
|
||||||
break;
|
break;
|
||||||
P_CASELONG('D', fade_delta);
|
P_CASEINT('D', fade_delta);
|
||||||
case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break;
|
case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break;
|
||||||
case 'O': opt->fade_out_step = normalize_d(atof(optarg)); break;
|
case 'O': opt->fade_out_step = normalize_d(atof(optarg)); break;
|
||||||
case 'c': shadow_enable = true; break;
|
case 'c': shadow_enable = true; break;
|
||||||
|
@ -535,12 +540,12 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
case 'F':
|
case 'F':
|
||||||
fading_enable = true;
|
fading_enable = true;
|
||||||
break;
|
break;
|
||||||
P_CASELONG('r', shadow_radius);
|
P_CASEINT('r', shadow_radius);
|
||||||
case 'o':
|
case 'o':
|
||||||
opt->shadow_opacity = atof(optarg);
|
opt->shadow_opacity = atof(optarg);
|
||||||
break;
|
break;
|
||||||
P_CASELONG('l', shadow_offset_x);
|
P_CASEINT('l', shadow_offset_x);
|
||||||
P_CASELONG('t', shadow_offset_y);
|
P_CASEINT('t', shadow_offset_y);
|
||||||
case 'i':
|
case 'i':
|
||||||
opt->inactive_opacity = normalize_d(atof(optarg));
|
opt->inactive_opacity = normalize_d(atof(optarg));
|
||||||
break;
|
break;
|
||||||
|
@ -587,7 +592,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
P_CASEBOOL(266, shadow_ignore_shaped);
|
P_CASEBOOL(266, shadow_ignore_shaped);
|
||||||
P_CASEBOOL(267, detect_rounded_corners);
|
P_CASEBOOL(267, detect_rounded_corners);
|
||||||
P_CASEBOOL(268, detect_client_opacity);
|
P_CASEBOOL(268, detect_client_opacity);
|
||||||
P_CASELONG(269, refresh_rate);
|
P_CASEINT(269, refresh_rate);
|
||||||
case 270:
|
case 270:
|
||||||
if (optarg) {
|
if (optarg) {
|
||||||
opt->vsync = parse_vsync(optarg);
|
opt->vsync = parse_vsync(optarg);
|
||||||
|
@ -656,10 +661,10 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
log_error("--glx-copy-from-front %s", deprecation_message);
|
log_error("--glx-copy-from-front %s", deprecation_message);
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
P_CASELONG(293, benchmark);
|
P_CASEINT(293, benchmark);
|
||||||
case 294:
|
case 294:
|
||||||
// --benchmark-wid
|
// --benchmark-wid
|
||||||
opt->benchmark_wid = strtol(optarg, NULL, 0);
|
opt->benchmark_wid = (xcb_window_t)strtol(optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case 295:
|
case 295:
|
||||||
log_error("--glx-use-copysubbuffermesa %s", deprecation_message);
|
log_error("--glx-use-copysubbuffermesa %s", deprecation_message);
|
||||||
|
@ -706,7 +711,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
MAX_BLUR_PASS, &conv_kern_hasneg))
|
MAX_BLUR_PASS, &conv_kern_hasneg))
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
P_CASELONG(302, resize_damage);
|
P_CASEINT(302, resize_damage);
|
||||||
case 303:
|
case 303:
|
||||||
// --glx-use-gpushader4
|
// --glx-use-gpushader4
|
||||||
log_warn("--glx-use-gpushader4 is deprecated since v6."
|
log_warn("--glx-use-gpushader4 is deprecated since v6."
|
||||||
|
@ -782,8 +787,8 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Range checking and option assignments
|
// Range checking and option assignments
|
||||||
opt->fade_delta = max_i(opt->fade_delta, 1);
|
opt->fade_delta = max2(opt->fade_delta, 1);
|
||||||
opt->shadow_radius = max_i(opt->shadow_radius, 0);
|
opt->shadow_radius = max2(opt->shadow_radius, 0);
|
||||||
opt->shadow_red = normalize_d(opt->shadow_red);
|
opt->shadow_red = normalize_d(opt->shadow_red);
|
||||||
opt->shadow_green = normalize_d(opt->shadow_green);
|
opt->shadow_green = normalize_d(opt->shadow_green);
|
||||||
opt->shadow_blue = normalize_d(opt->shadow_blue);
|
opt->shadow_blue = normalize_d(opt->shadow_blue);
|
||||||
|
@ -802,7 +807,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
// Other variables determined by options
|
// Other variables determined by options
|
||||||
|
|
||||||
// Determine whether we need to track focus changes
|
// Determine whether we need to track focus changes
|
||||||
if (opt->inactive_opacity != opt->active_opacity || opt->inactive_dim) {
|
if (opt->inactive_opacity != opt->active_opacity || opt->inactive_dim > 0) {
|
||||||
opt->track_focus = true;
|
opt->track_focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ static inline rect_t from_x_rect(const xcb_rectangle_t *rect) {
|
||||||
/// Returning an array that needs to be freed
|
/// Returning an array that needs to be freed
|
||||||
static inline rect_t *from_x_rects(int nrects, const xcb_rectangle_t *rects) {
|
static inline rect_t *from_x_rects(int nrects, const xcb_rectangle_t *rects) {
|
||||||
rect_t *ret = ccalloc(nrects, rect_t);
|
rect_t *ret = ccalloc(nrects, rect_t);
|
||||||
for (int i = 0; i < nrects; i++)
|
for (int i = 0; i < nrects; i++) {
|
||||||
ret[i] = from_x_rect(rects + i);
|
ret[i] = from_x_rect(rects + i);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
114
src/render.c
114
src/render.c
|
@ -34,9 +34,8 @@
|
||||||
/**
|
/**
|
||||||
* Bind texture in paint_t if we are using GLX backend.
|
* Bind texture in paint_t if we are using GLX backend.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int hei,
|
||||||
paint_bind_tex(session_t *ps, paint_t *ppaint, unsigned wid, unsigned hei, bool repeat,
|
bool repeat, int depth, xcb_visualid_t visual, bool force) {
|
||||||
int depth, xcb_visualid_t visual, bool force) {
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
// XXX This is a mess. But this will go away after the backend refactor.
|
// XXX This is a mess. But this will go away after the backend refactor.
|
||||||
static thread_local struct glx_fbconfig_info *argb_fbconfig = NULL;
|
static thread_local struct glx_fbconfig_info *argb_fbconfig = NULL;
|
||||||
|
@ -174,13 +173,15 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, doubl
|
||||||
switch (ps->o.backend) {
|
switch (ps->o.backend) {
|
||||||
case BKEND_XRENDER:
|
case BKEND_XRENDER:
|
||||||
case BKEND_XR_GLX_HYBRID: {
|
case BKEND_XR_GLX_HYBRID: {
|
||||||
int alpha_step = opacity * MAX_ALPHA;
|
auto alpha_step = (int)(opacity * MAX_ALPHA);
|
||||||
xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step];
|
xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step];
|
||||||
if (alpha_step != 0) {
|
if (alpha_step != 0) {
|
||||||
int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC
|
uint8_t op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC
|
||||||
: XCB_RENDER_PICT_OP_OVER);
|
: XCB_RENDER_PICT_OP_OVER);
|
||||||
xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
|
xcb_render_composite(
|
||||||
x, y, 0, 0, dx, dy, wid, hei);
|
ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
|
||||||
|
to_i16_checked(x), to_i16_checked(y), 0, 0, to_i16_checked(dx),
|
||||||
|
to_i16_checked(dy), to_u16_checked(wid), to_u16_checked(hei));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -279,8 +280,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
|
|
||||||
const int x = w->g.x;
|
const int x = w->g.x;
|
||||||
const int y = w->g.y;
|
const int y = w->g.y;
|
||||||
const int wid = w->widthb;
|
const uint16_t wid = to_u16_checked(w->widthb);
|
||||||
const int hei = w->heightb;
|
const uint16_t hei = to_u16_checked(w->heightb);
|
||||||
|
|
||||||
xcb_render_picture_t pict = w->paint.pict;
|
xcb_render_picture_t pict = w->paint.pict;
|
||||||
|
|
||||||
|
@ -320,10 +321,10 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
} else {
|
} else {
|
||||||
// Painting parameters
|
// Painting parameters
|
||||||
const margin_t extents = win_calc_frame_extents(w);
|
const margin_t extents = win_calc_frame_extents(w);
|
||||||
const int t = extents.top;
|
const auto t = (int)extents.top;
|
||||||
const int l = extents.left;
|
const auto l = (int)extents.left;
|
||||||
const int b = extents.bottom;
|
const auto b = (int)extents.bottom;
|
||||||
const int r = extents.right;
|
const auto r = (int)extents.right;
|
||||||
|
|
||||||
#define COMP_BDR(cx, cy, cwid, chei) \
|
#define COMP_BDR(cx, cy, cwid, chei) \
|
||||||
paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * w->opacity, \
|
paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * w->opacity, \
|
||||||
|
@ -337,7 +338,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
int body_height = hei;
|
int body_height = hei;
|
||||||
// ctop = checked top
|
// ctop = checked top
|
||||||
// Make sure top margin is smaller than height
|
// Make sure top margin is smaller than height
|
||||||
int ctop = min_i(body_height, t);
|
int ctop = min2(body_height, t);
|
||||||
if (ctop > 0)
|
if (ctop > 0)
|
||||||
COMP_BDR(0, 0, wid, ctop);
|
COMP_BDR(0, 0, wid, ctop);
|
||||||
|
|
||||||
|
@ -348,7 +349,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
// bottom
|
// bottom
|
||||||
// cbot = checked bottom
|
// cbot = checked bottom
|
||||||
// Make sure bottom margin is not too large
|
// Make sure bottom margin is not too large
|
||||||
int cbot = min_i(body_height, b);
|
int cbot = min2(body_height, b);
|
||||||
if (cbot > 0)
|
if (cbot > 0)
|
||||||
COMP_BDR(0, hei - cbot, wid, cbot);
|
COMP_BDR(0, hei - cbot, wid, cbot);
|
||||||
|
|
||||||
|
@ -359,7 +360,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
|
|
||||||
// left
|
// left
|
||||||
int body_width = wid;
|
int body_width = wid;
|
||||||
int cleft = min_i(body_width, l);
|
int cleft = min2(body_width, l);
|
||||||
if (cleft > 0)
|
if (cleft > 0)
|
||||||
COMP_BDR(0, ctop, cleft, body_height);
|
COMP_BDR(0, ctop, cleft, body_height);
|
||||||
|
|
||||||
|
@ -368,7 +369,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// right
|
// right
|
||||||
int cright = min_i(body_width, r);
|
int cright = min2(body_width, r);
|
||||||
if (cright > 0)
|
if (cright > 0)
|
||||||
COMP_BDR(wid - cright, ctop, cright, body_height);
|
COMP_BDR(wid - cright, ctop, cright, body_height);
|
||||||
|
|
||||||
|
@ -396,7 +397,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
switch (ps->o.backend) {
|
switch (ps->o.backend) {
|
||||||
case BKEND_XRENDER:
|
case BKEND_XRENDER:
|
||||||
case BKEND_XR_GLX_HYBRID: {
|
case BKEND_XR_GLX_HYBRID: {
|
||||||
unsigned short cval = 0xffff * dim_opacity;
|
auto cval = (uint16_t)(0xffff * dim_opacity);
|
||||||
|
|
||||||
// Premultiply color
|
// Premultiply color
|
||||||
xcb_render_color_t color = {
|
xcb_render_color_t color = {
|
||||||
|
@ -407,8 +408,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
};
|
};
|
||||||
|
|
||||||
xcb_rectangle_t rect = {
|
xcb_rectangle_t rect = {
|
||||||
.x = x,
|
.x = to_i16_checked(x),
|
||||||
.y = y,
|
.y = to_i16_checked(y),
|
||||||
.width = wid,
|
.width = wid,
|
||||||
.height = hei,
|
.height = hei,
|
||||||
};
|
};
|
||||||
|
@ -418,8 +419,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
} break;
|
} break;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
case BKEND_GLX:
|
case BKEND_GLX:
|
||||||
glx_dim_dst(ps, x, y, wid, hei, ps->psglx->z - 0.7, dim_opacity,
|
glx_dim_dst(ps, x, y, wid, hei, (int)(ps->psglx->z - 0.7),
|
||||||
reg_paint);
|
(float)dim_opacity, reg_paint);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
|
@ -447,7 +448,7 @@ static bool get_root_tile(session_t *ps) {
|
||||||
|
|
||||||
// Create a pixmap if there isn't any
|
// Create a pixmap if there isn't any
|
||||||
if (!pixmap) {
|
if (!pixmap) {
|
||||||
pixmap = x_create_pixmap(ps->c, ps->depth, ps->root, 1, 1);
|
pixmap = x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root, 1, 1);
|
||||||
if (pixmap == XCB_NONE) {
|
if (pixmap == XCB_NONE) {
|
||||||
log_error("Failed to create pixmaps for root tile.");
|
log_error("Failed to create pixmaps for root tile.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -605,8 +606,9 @@ static inline void win_paint_shadow(session_t *ps, win *w, region_t *reg_paint)
|
||||||
*
|
*
|
||||||
* @return true if successful, false otherwise
|
* @return true if successful, false otherwise
|
||||||
*/
|
*/
|
||||||
static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wid,
|
static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x,
|
||||||
int hei, xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) {
|
int16_t y, uint16_t wid, uint16_t hei,
|
||||||
|
xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) {
|
||||||
assert(blur_kerns[0]);
|
assert(blur_kerns[0]);
|
||||||
|
|
||||||
// Directly copying from tgt_buffer to it does not work, so we create a
|
// Directly copying from tgt_buffer to it does not work, so we create a
|
||||||
|
@ -627,16 +629,16 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, i
|
||||||
assert(i < MAX_BLUR_PASS - 1);
|
assert(i < MAX_BLUR_PASS - 1);
|
||||||
xcb_render_fixed_t *convolution_blur = blur_kerns[i];
|
xcb_render_fixed_t *convolution_blur = blur_kerns[i];
|
||||||
// `x / 65536.0` converts from X fixed point to double
|
// `x / 65536.0` converts from X fixed point to double
|
||||||
int kwid = ((double)convolution_blur[0]) / 65536.0,
|
int kwid = (int)((double)convolution_blur[0] / 65536.0),
|
||||||
khei = ((double)convolution_blur[1]) / 65536.0;
|
khei = (int)((double)convolution_blur[1] / 65536.0);
|
||||||
bool rd_from_tgt = (tgt_buffer == src_pict);
|
bool rd_from_tgt = (tgt_buffer == src_pict);
|
||||||
|
|
||||||
// Copy from source picture to destination. The filter must
|
// Copy from source picture to destination. The filter must
|
||||||
// be applied on source picture, to get the nearby pixels outside the
|
// be applied on source picture, to get the nearby pixels outside the
|
||||||
// window.
|
// window.
|
||||||
xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION),
|
xcb_render_set_picture_filter(
|
||||||
XRFILTER_CONVOLUTION, kwid * khei + 2,
|
ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
|
||||||
convolution_blur);
|
(uint32_t)(kwid * khei + 2), convolution_blur);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
|
||||||
dst_pict, (rd_from_tgt ? x : 0),
|
dst_pict, (rd_from_tgt ? x : 0),
|
||||||
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
|
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
|
||||||
|
@ -664,10 +666,10 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, i
|
||||||
*/
|
*/
|
||||||
static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
||||||
const region_t *reg_paint) {
|
const region_t *reg_paint) {
|
||||||
const int x = w->g.x;
|
const int16_t x = w->g.x;
|
||||||
const int y = w->g.y;
|
const int16_t y = w->g.y;
|
||||||
const int wid = w->widthb;
|
const auto wid = to_u16_checked(w->widthb);
|
||||||
const int hei = w->heightb;
|
const auto hei = to_u16_checked(w->heightb);
|
||||||
|
|
||||||
double factor_center = 1.0;
|
double factor_center = 1.0;
|
||||||
// Adjust blur strength according to window opacity, to make it appear
|
// Adjust blur strength according to window opacity, to make it appear
|
||||||
|
@ -702,7 +704,7 @@ static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture
|
||||||
|
|
||||||
// If kern_dst is allocated, it's always allocated to the right
|
// If kern_dst is allocated, it's always allocated to the right
|
||||||
// size
|
// size
|
||||||
size_t size = kern_dst ? kern_src->w * kern_src->h + 2 : 0;
|
size_t size = kern_dst ? (size_t)(kern_src->w * kern_src->h + 2) : 0;
|
||||||
x_picture_filter_from_conv(kern_src, factor_center, &kern_dst, &size);
|
x_picture_filter_from_conv(kern_src, factor_center, &kern_dst, &size);
|
||||||
ps->blur_kerns_cache[i] = kern_dst;
|
ps->blur_kerns_cache[i] = kern_dst;
|
||||||
}
|
}
|
||||||
|
@ -726,8 +728,8 @@ static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
case BKEND_GLX:
|
case BKEND_GLX:
|
||||||
// TODO: Handle frame opacity
|
// TODO: Handle frame opacity
|
||||||
glx_blur_dst(ps, x, y, wid, hei, ps->psglx->z - 0.5, factor_center,
|
glx_blur_dst(ps, x, y, wid, hei, (float)ps->psglx->z - 0.5f,
|
||||||
reg_paint, &w->glx_blur_cache);
|
(float)factor_center, reg_paint, &w->glx_blur_cache);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
|
@ -786,7 +788,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
pixman_region32_copy(®ion, &ps->screen_reg);
|
pixman_region32_copy(®ion, &ps->screen_reg);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < get_buffer_age(ps); i++) {
|
for (int i = 0; i < get_buffer_age(ps); i++) {
|
||||||
const int curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
||||||
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -800,7 +802,7 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ps->o.resize_damage > 0) {
|
if (ps->o.resize_damage > 0) {
|
||||||
resize_region(®ion, ps->o.resize_damage);
|
resize_region(®ion, (short)ps->o.resize_damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the damaged area out of screen
|
// Remove the damaged area out of screen
|
||||||
|
@ -809,8 +811,9 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
if (!paint_isvalid(ps, &ps->tgt_buffer)) {
|
if (!paint_isvalid(ps, &ps->tgt_buffer)) {
|
||||||
if (!ps->tgt_buffer.pixmap) {
|
if (!ps->tgt_buffer.pixmap) {
|
||||||
free_paint(ps, &ps->tgt_buffer);
|
free_paint(ps, &ps->tgt_buffer);
|
||||||
ps->tgt_buffer.pixmap = x_create_pixmap(
|
ps->tgt_buffer.pixmap =
|
||||||
ps->c, ps->depth, ps->root, ps->root_width, ps->root_height);
|
x_create_pixmap(ps->c, (uint8_t)ps->depth, ps->root,
|
||||||
|
ps->root_width, ps->root_height);
|
||||||
if (ps->tgt_buffer.pixmap == XCB_NONE) {
|
if (ps->tgt_buffer.pixmap == XCB_NONE) {
|
||||||
log_fatal("Failed to allocate a screen-sized pixmap for"
|
log_fatal("Failed to allocate a screen-sized pixmap for"
|
||||||
"painting");
|
"painting");
|
||||||
|
@ -874,9 +877,10 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
|
|
||||||
// Might be worth while to crop the region to shadow
|
// Might be worth while to crop the region to shadow
|
||||||
// border
|
// border
|
||||||
|
assert(w->shadow_width >= 0 && w->shadow_height >= 0);
|
||||||
pixman_region32_intersect_rect(
|
pixman_region32_intersect_rect(
|
||||||
®_tmp, ®_tmp, w->g.x + w->shadow_dx,
|
®_tmp, ®_tmp, w->g.x + w->shadow_dx, w->g.y + w->shadow_dy,
|
||||||
w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height);
|
(uint)w->shadow_width, (uint)w->shadow_height);
|
||||||
|
|
||||||
// Mask out the body of the window from the shadow if
|
// Mask out the body of the window from the shadow if
|
||||||
// needed Doing it here instead of in make_shadow() for
|
// needed Doing it here instead of in make_shadow() for
|
||||||
|
@ -958,6 +962,8 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
ps->vsync_wait(ps);
|
ps->vsync_wait(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto rwidth = to_u16_checked(ps->root_width);
|
||||||
|
auto rheight = to_u16_checked(ps->root_height);
|
||||||
switch (ps->o.backend) {
|
switch (ps->o.backend) {
|
||||||
case BKEND_XRENDER:
|
case BKEND_XRENDER:
|
||||||
if (ps->o.monitor_repaint) {
|
if (ps->o.monitor_repaint) {
|
||||||
|
@ -969,16 +975,16 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
// to it
|
// to it
|
||||||
auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis);
|
auto pictfmt = x_get_pictform_for_visual(ps->c, ps->vis);
|
||||||
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
|
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
|
||||||
ps->c, ps->root, ps->root_width, ps->root_height, pictfmt, 0, NULL);
|
ps->c, ps->root, rwidth, rheight, pictfmt, 0, NULL);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||||
ps->tgt_buffer.pict, XCB_NONE, new_pict, 0, 0,
|
ps->tgt_buffer.pict, XCB_NONE, new_pict, 0,
|
||||||
0, 0, 0, 0, ps->root_width, ps->root_height);
|
0, 0, 0, 0, 0, rwidth, rheight);
|
||||||
|
|
||||||
// Next, we set the region of paint and highlight it
|
// Next, we set the region of paint and highlight it
|
||||||
x_set_picture_clip_region(ps->c, new_pict, 0, 0, ®ion);
|
x_set_picture_clip_region(ps->c, new_pict, 0, 0, ®ion);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
|
||||||
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, 0,
|
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0,
|
||||||
0, 0, 0, 0, ps->root_width, ps->root_height);
|
0, 0, 0, 0, 0, rwidth, rheight);
|
||||||
|
|
||||||
// Finally, clear clip regions of new_pict and the screen, and put
|
// Finally, clear clip regions of new_pict and the screen, and put
|
||||||
// the whole thing on screen
|
// the whole thing on screen
|
||||||
|
@ -986,12 +992,12 @@ void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
x_set_picture_clip_region(ps->c, ps->tgt_picture, 0, 0, &ps->screen_reg);
|
x_set_picture_clip_region(ps->c, ps->tgt_picture, 0, 0, &ps->screen_reg);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict,
|
||||||
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
||||||
ps->root_width, ps->root_height);
|
rwidth, rheight);
|
||||||
xcb_render_free_picture(ps->c, new_pict);
|
xcb_render_free_picture(ps->c, new_pict);
|
||||||
} else
|
} else
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||||
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
ps->tgt_buffer.pict, XCB_NONE, ps->tgt_picture,
|
||||||
ps->root_width, ps->root_height);
|
0, 0, 0, 0, 0, 0, rwidth, rheight);
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
case BKEND_XR_GLX_HYBRID:
|
case BKEND_XR_GLX_HYBRID:
|
||||||
|
@ -1151,7 +1157,7 @@ bool init_render(session_t *ps) {
|
||||||
|
|
||||||
// Generates another Picture for shadows if the color is modified by
|
// Generates another Picture for shadows if the color is modified by
|
||||||
// user
|
// user
|
||||||
if (!ps->o.shadow_red && !ps->o.shadow_green && !ps->o.shadow_blue) {
|
if (ps->o.shadow_red == 0 && ps->o.shadow_green == 0 && ps->o.shadow_blue == 0) {
|
||||||
ps->cshadow_picture = ps->black_picture;
|
ps->cshadow_picture = ps->black_picture;
|
||||||
} else {
|
} else {
|
||||||
ps->cshadow_picture = solid_picture(ps->c, ps->root, true, 1, ps->o.shadow_red,
|
ps->cshadow_picture = solid_picture(ps->c, ps->root, true, 1, ps->o.shadow_red,
|
||||||
|
|
26
src/render.h
26
src/render.h
|
@ -2,9 +2,9 @@
|
||||||
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <xcb/render.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
#include "backend/gl/glx.h"
|
#include "backend/gl/glx.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,24 +16,20 @@ typedef struct win win;
|
||||||
typedef struct session session_t;
|
typedef struct session session_t;
|
||||||
|
|
||||||
typedef struct paint {
|
typedef struct paint {
|
||||||
xcb_pixmap_t pixmap;
|
xcb_pixmap_t pixmap;
|
||||||
xcb_render_picture_t pict;
|
xcb_render_picture_t pict;
|
||||||
glx_texture_t *ptex;
|
glx_texture_t *ptex;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
struct glx_fbconfig_info *fbcfg;
|
struct glx_fbconfig_info *fbcfg;
|
||||||
#endif
|
#endif
|
||||||
} paint_t;
|
} paint_t;
|
||||||
|
|
||||||
void
|
void render(session_t *ps, int x, int y, int dx, int dy, int w, int h, double opacity,
|
||||||
render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
|
bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex,
|
||||||
double opacity, bool argb, bool neg,
|
const region_t *reg_paint, const glx_prog_main_t *pprogram);
|
||||||
xcb_render_picture_t pict, glx_texture_t *ptex,
|
void paint_one(session_t *ps, win *w, const region_t *reg_paint);
|
||||||
const region_t *reg_paint, const glx_prog_main_t *pprogram);
|
|
||||||
void
|
|
||||||
paint_one(session_t *ps, win *w, const region_t *reg_paint);
|
|
||||||
|
|
||||||
void
|
void paint_all(session_t *ps, win *const t, bool ignore_damage);
|
||||||
paint_all(session_t *ps, win * const t, bool ignore_damage);
|
|
||||||
|
|
||||||
void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);
|
void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
#define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1))
|
#define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1))
|
||||||
|
|
||||||
char *mstrjoin(const char *src1, const char *src2);
|
char *mstrjoin(const char *src1, const char *src2);
|
||||||
|
@ -26,7 +28,7 @@ static inline int uitostr(unsigned int n, char *buf) {
|
||||||
|
|
||||||
int pos = ret;
|
int pos = ret;
|
||||||
while (pos--) {
|
while (pos--) {
|
||||||
buf[pos] = n % 10 + '0';
|
buf[pos] = (char)(n % 10 + '0');
|
||||||
n /= 10;
|
n /= 10;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -14,14 +14,6 @@ typedef enum {
|
||||||
UNSET
|
UNSET
|
||||||
} switch_t;
|
} switch_t;
|
||||||
|
|
||||||
/// Structure representing a X geometry.
|
|
||||||
typedef struct {
|
|
||||||
int wid;
|
|
||||||
int hei;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
} geometry_t;
|
|
||||||
|
|
||||||
/// A structure representing margins around a rectangle.
|
/// A structure representing margins around a rectangle.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int top;
|
unsigned int top;
|
||||||
|
|
|
@ -22,7 +22,7 @@ void report_allocation_failure(const char *func, const char *file, unsigned int
|
||||||
{.iov_base = "at ", .iov_len = 3},
|
{.iov_base = "at ", .iov_len = 3},
|
||||||
{.iov_base = (void *)file, .iov_len = strlen(file)},
|
{.iov_base = (void *)file, .iov_len = strlen(file)},
|
||||||
{.iov_base = ":", .iov_len = 1},
|
{.iov_base = ":", .iov_len = 1},
|
||||||
{.iov_base = buf, .iov_len = llen},
|
{.iov_base = buf, .iov_len = (size_t)llen},
|
||||||
{.iov_base = (void *)msg2, .iov_len = sizeof(msg2) - 1},
|
{.iov_base = (void *)msg2, .iov_len = sizeof(msg2) - 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
86
src/utils.h
86
src/utils.h
|
@ -3,6 +3,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -42,13 +43,51 @@ safe_isnan(double a) {
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/// Same as assert, but evaluates the expression even in release builds
|
/// Same as assert, but evaluates the expression even in release builds
|
||||||
#define CHECK(expr) \
|
#define CHECK(expr) \
|
||||||
do { \
|
do { \
|
||||||
__auto_type __tmp = (expr); \
|
__auto_type __tmp = (expr); \
|
||||||
assert(__tmp); \
|
assert(__tmp); \
|
||||||
(void)__tmp; \
|
(void)__tmp; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
// Some macros for checked cast
|
||||||
|
|
||||||
|
#define to_int_checked(val) \
|
||||||
|
({ \
|
||||||
|
auto tmp = (val); \
|
||||||
|
assert(tmp >= INT_MIN && tmp <= INT_MAX); \
|
||||||
|
(int)tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define to_char_checked(val) \
|
||||||
|
({ \
|
||||||
|
auto tmp = (val); \
|
||||||
|
assert(tmp >= CHAR_MIN && tmp <= CHAR_MAX); \
|
||||||
|
(char)tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define to_u16_checked(val) \
|
||||||
|
({ \
|
||||||
|
auto tmp = (val); \
|
||||||
|
assert(tmp >= 0 && tmp <= UINT16_MAX); \
|
||||||
|
(uint16_t) tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define to_i16_checked(val) \
|
||||||
|
({ \
|
||||||
|
auto tmp = (val); \
|
||||||
|
assert(tmp >= INT16_MIN && tmp <= INT16_MAX); \
|
||||||
|
(int16_t) tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define to_u32_checked(val) \
|
||||||
|
({ \
|
||||||
|
auto tmp = (val); \
|
||||||
|
int64_t max = UINT32_MAX; /* silence clang tautological comparison \
|
||||||
|
warning*/ \
|
||||||
|
assert(tmp >= 0 && tmp <= max); \
|
||||||
|
(uint32_t) tmp; \
|
||||||
|
})
|
||||||
/**
|
/**
|
||||||
* Normalize an int value to a specific range.
|
* Normalize an int value to a specific range.
|
||||||
*
|
*
|
||||||
|
@ -65,33 +104,11 @@ static inline int attr_const normalize_i_range(int i, int min, int max) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#define min2(a, b) ((a) > (b) ? (b) : (a))
|
||||||
* Select the larger integer of two.
|
#define max2(a, b) ((a) > (b) ? (a) : (b))
|
||||||
*/
|
|
||||||
static inline int attr_const max_i(int a, int b) {
|
|
||||||
return (a > b ? a : b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/// clamp `val` into interval [min, max]
|
||||||
* Select the smaller integer of two.
|
#define clamp(val, min, max) max2(min2(val, max), min)
|
||||||
*/
|
|
||||||
static inline int attr_const min_i(int a, int b) {
|
|
||||||
return (a > b ? b : a);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select the larger long integer of two.
|
|
||||||
*/
|
|
||||||
static inline long attr_const max_l(long a, long b) {
|
|
||||||
return (a > b ? a : b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select the smaller long integer of two.
|
|
||||||
*/
|
|
||||||
static inline long attr_const min_l(long a, long b) {
|
|
||||||
return (a > b ? b : a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int attr_const popcountl(unsigned long a) {
|
static inline int attr_const popcountl(unsigned long a) {
|
||||||
return __builtin_popcountl(a);
|
return __builtin_popcountl(a);
|
||||||
|
@ -147,11 +164,20 @@ allocchk_(const char *func_name, const char *file, unsigned int line, void *ptr)
|
||||||
#define cvalloc(size) allocchk(malloc(size))
|
#define cvalloc(size) allocchk(malloc(size))
|
||||||
|
|
||||||
/// @brief Wrapper of calloc().
|
/// @brief Wrapper of calloc().
|
||||||
#define ccalloc(nmemb, type) ((type *)allocchk(calloc((nmemb), sizeof(type))))
|
#define ccalloc(nmemb, type) \
|
||||||
|
({ \
|
||||||
|
auto tmp = (nmemb); \
|
||||||
|
assert(tmp >= 0); \
|
||||||
|
((type *)allocchk(calloc((size_t)tmp, sizeof(type)))); \
|
||||||
|
})
|
||||||
|
|
||||||
/// @brief Wrapper of ealloc().
|
/// @brief Wrapper of ealloc().
|
||||||
#define crealloc(ptr, nmemb) \
|
#define crealloc(ptr, nmemb) \
|
||||||
((__typeof__(ptr))allocchk(realloc((ptr), (nmemb) * sizeof(*(ptr)))))
|
({ \
|
||||||
|
auto tmp = (nmemb); \
|
||||||
|
assert(tmp >= 0); \
|
||||||
|
((__typeof__(ptr))allocchk(realloc((ptr), (size_t)tmp * sizeof(*(ptr))))); \
|
||||||
|
})
|
||||||
|
|
||||||
/// RC_TYPE generates a reference counted type from `type`
|
/// RC_TYPE generates a reference counted type from `type`
|
||||||
///
|
///
|
||||||
|
|
|
@ -38,7 +38,7 @@ static int vsync_drm_wait(session_t *ps) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
|
ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
|
||||||
vbl.request.type &= ~_DRM_VBLANK_RELATIVE;
|
vbl.request.type &= ~(uint)_DRM_VBLANK_RELATIVE;
|
||||||
} while (ret && errno == EINTR);
|
} while (ret && errno == EINTR);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -90,9 +90,9 @@ static bool vsync_opengl_oml_init(session_t *ps) {
|
||||||
return glxext.has_GLX_OML_sync_control;
|
return glxext.has_GLX_OML_sync_control;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) {
|
static inline bool vsync_opengl_swc_swap_interval(session_t *ps, int interval) {
|
||||||
if (glxext.has_GLX_MESA_swap_control)
|
if (glxext.has_GLX_MESA_swap_control)
|
||||||
return glXSwapIntervalMESA(interval) == 0;
|
return glXSwapIntervalMESA((uint)interval) == 0;
|
||||||
else if (glxext.has_GLX_SGI_swap_control)
|
else if (glxext.has_GLX_SGI_swap_control)
|
||||||
return glXSwapIntervalSGI(interval) == 0;
|
return glXSwapIntervalSGI(interval) == 0;
|
||||||
else if (glxext.has_GLX_EXT_swap_control) {
|
else if (glxext.has_GLX_EXT_swap_control) {
|
||||||
|
|
51
src/win.c
51
src/win.c
|
@ -110,8 +110,9 @@ static inline bool group_is_focused(session_t *ps, xcb_window_t leader) {
|
||||||
* Get a rectangular region a window occupies, excluding shadow.
|
* Get a rectangular region a window occupies, excluding shadow.
|
||||||
*/
|
*/
|
||||||
static void win_get_region_local(const win *w, region_t *res) {
|
static void win_get_region_local(const win *w, region_t *res) {
|
||||||
|
assert(w->widthb >= 0 && w->heightb >= 0);
|
||||||
pixman_region32_fini(res);
|
pixman_region32_fini(res);
|
||||||
pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb);
|
pixman_region32_init_rect(res, 0, 0, (uint)w->widthb, (uint)w->heightb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,14 +121,15 @@ static void win_get_region_local(const win *w, region_t *res) {
|
||||||
void win_get_region_noframe_local(const win *w, region_t *res) {
|
void win_get_region_noframe_local(const win *w, region_t *res) {
|
||||||
const margin_t extents = win_calc_frame_extents(w);
|
const margin_t extents = win_calc_frame_extents(w);
|
||||||
|
|
||||||
int x = extents.left;
|
int x = (int)extents.left;
|
||||||
int y = extents.top;
|
int y = (int)extents.top;
|
||||||
int width = max_i(w->g.width - extents.left - extents.right, 0);
|
int width = max2(w->g.width - (int)(extents.left + extents.right), 0);
|
||||||
int height = max_i(w->g.height - extents.top - extents.bottom, 0);
|
int height = max2(w->g.height - (int)(extents.top + extents.bottom), 0);
|
||||||
|
|
||||||
pixman_region32_fini(res);
|
pixman_region32_fini(res);
|
||||||
if (width > 0 && height > 0)
|
if (width > 0 && height > 0) {
|
||||||
pixman_region32_init_rect(res, x, y, width, height);
|
pixman_region32_init_rect(res, x, y, (uint)width, (uint)height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_by_val(win_get_region_noframe_local);
|
gen_by_val(win_get_region_noframe_local);
|
||||||
|
@ -139,13 +141,13 @@ void win_get_region_frame_local(const win *w, region_t *res) {
|
||||||
res,
|
res,
|
||||||
(rect_t[]){
|
(rect_t[]){
|
||||||
// top
|
// top
|
||||||
{.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = extents.top},
|
{.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = (int)extents.top},
|
||||||
// bottom
|
// bottom
|
||||||
{.x1 = 0, .y1 = w->g.height - extents.bottom, .x2 = w->g.width, .y2 = w->g.height},
|
{.x1 = 0, .y1 = (int)(w->g.height - extents.bottom), .x2 = w->g.width, .y2 = w->g.height},
|
||||||
// left
|
// left
|
||||||
{.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height},
|
{.x1 = 0, .y1 = 0, .x2 = (int)extents.left, .y2 = w->g.height},
|
||||||
// right
|
// right
|
||||||
{.x1 = w->g.width - extents.right, .y1 = 0, .x2 = w->g.width, .y2 = w->g.height},
|
{.x1 = (int)(w->g.width - extents.right), .y1 = 0, .x2 = w->g.width, .y2 = w->g.height},
|
||||||
},
|
},
|
||||||
4);
|
4);
|
||||||
|
|
||||||
|
@ -208,8 +210,9 @@ _win_bind_image(session_t *ps, win *w, void **win_image, void **shadow_image) {
|
||||||
}
|
}
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
*shadow_image = ps->backend_data->ops->render_shadow(
|
*shadow_image = ps->backend_data->ops->render_shadow(
|
||||||
ps->backend_data, w->widthb, w->heightb, ps->gaussian_map, ps->o.shadow_red,
|
ps->backend_data, w->widthb, w->heightb, ps->gaussian_map,
|
||||||
ps->o.shadow_green, ps->o.shadow_blue, ps->o.shadow_opacity);
|
ps->o.shadow_red, ps->o.shadow_green, ps->o.shadow_blue,
|
||||||
|
ps->o.shadow_opacity);
|
||||||
if (!*shadow_image) {
|
if (!*shadow_image) {
|
||||||
log_error("Failed to bind shadow image");
|
log_error("Failed to bind shadow image");
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, *win_image);
|
ps->backend_data->ops->release_image(ps->backend_data, *win_image);
|
||||||
|
@ -249,10 +252,10 @@ static bool attr_pure win_has_rounded_corners(const win *w) {
|
||||||
|
|
||||||
// Determine the minimum width/height of a rectangle that could mark
|
// Determine the minimum width/height of a rectangle that could mark
|
||||||
// a window as having rounded corners
|
// a window as having rounded corners
|
||||||
unsigned short minwidth =
|
auto minwidth =
|
||||||
max_i(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS);
|
(uint16_t)max2(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS);
|
||||||
unsigned short minheight =
|
auto minheight =
|
||||||
max_i(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS);
|
(uint16_t)max2(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS);
|
||||||
|
|
||||||
// Get the rectangles in the bounding region
|
// Get the rectangles in the bounding region
|
||||||
int nrects = 0;
|
int nrects = 0;
|
||||||
|
@ -461,7 +464,7 @@ bool win_should_dim(session_t *ps, const win *w) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps->o.inactive_dim && !(w->focused)) {
|
if (ps->o.inactive_dim > 0 && !(w->focused)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -644,7 +647,7 @@ void win_update_opacity_rule(session_t *ps, win *w) {
|
||||||
if (!is_set)
|
if (!is_set)
|
||||||
wid_rm_opacity_prop(ps, w->id);
|
wid_rm_opacity_prop(ps, w->id);
|
||||||
else
|
else
|
||||||
wid_set_opacity_prop(ps, w->id, opacity * OPAQUE);
|
wid_set_opacity_prop(ps, w->id, (opacity_t)(opacity * OPAQUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1241,12 +1244,14 @@ void win_set_focused(session_t *ps, win *w, bool focused) {
|
||||||
*/
|
*/
|
||||||
void win_extents(const win *w, region_t *res) {
|
void win_extents(const win *w, region_t *res) {
|
||||||
pixman_region32_clear(res);
|
pixman_region32_clear(res);
|
||||||
pixman_region32_union_rect(res, res, w->g.x, w->g.y, w->widthb, w->heightb);
|
pixman_region32_union_rect(res, res, w->g.x, w->g.y, (uint)w->widthb, (uint)w->heightb);
|
||||||
|
|
||||||
if (w->shadow)
|
if (w->shadow) {
|
||||||
|
assert(w->shadow_width >= 0 && w->shadow_height >= 0);
|
||||||
pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx,
|
pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx,
|
||||||
w->g.y + w->shadow_dy, w->shadow_width,
|
w->g.y + w->shadow_dy, (uint)w->shadow_width,
|
||||||
w->shadow_height);
|
(uint)w->shadow_height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_by_val(win_extents);
|
gen_by_val(win_extents);
|
||||||
|
|
|
@ -425,10 +425,10 @@ static inline region_t win_get_bounding_shape_global_by_val(win *w) {
|
||||||
*/
|
*/
|
||||||
static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
|
static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
|
||||||
margin_t result = w->frame_extents;
|
margin_t result = w->frame_extents;
|
||||||
result.top = max_i(result.top, w->g.border_width);
|
result.top = max2(result.top, w->g.border_width);
|
||||||
result.left = max_i(result.left, w->g.border_width);
|
result.left = max2(result.left, w->g.border_width);
|
||||||
result.bottom = max_i(result.bottom, w->g.border_width);
|
result.bottom = max2(result.bottom, w->g.border_width);
|
||||||
result.right = max_i(result.right, w->g.border_width);
|
result.right = max2(result.right, w->g.border_width);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
79
src/x.c
79
src/x.c
|
@ -38,18 +38,21 @@
|
||||||
* and number of items. A blank one on failure.
|
* and number of items. A blank one on failure.
|
||||||
*/
|
*/
|
||||||
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
|
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
|
||||||
long offset, long length, xcb_atom_t rtype, int rformat) {
|
int offset, int length, xcb_atom_t rtype, int rformat) {
|
||||||
xcb_get_property_reply_t *r = xcb_get_property_reply(
|
xcb_get_property_reply_t *r = xcb_get_property_reply(
|
||||||
ps->c, xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL);
|
ps->c,
|
||||||
|
xcb_get_property(ps->c, 0, w, atom, rtype, to_u32_checked(offset),
|
||||||
|
to_u32_checked(length)),
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (r && xcb_get_property_value_length(r) &&
|
if (r && xcb_get_property_value_length(r) &&
|
||||||
(rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) &&
|
(rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) &&
|
||||||
(!rformat || r->format == rformat) &&
|
(!rformat || r->format == rformat) &&
|
||||||
(r->format == 8 || r->format == 16 || r->format == 32)) {
|
(r->format == 8 || r->format == 16 || r->format == 32)) {
|
||||||
int len = xcb_get_property_value_length(r);
|
auto len = xcb_get_property_value_length(r);
|
||||||
return (winprop_t){
|
return (winprop_t){
|
||||||
.ptr = xcb_get_property_value(r),
|
.ptr = xcb_get_property_value(r),
|
||||||
.nitems = len / (r->format / 8),
|
.nitems = (ulong)(len / (r->format / 8)),
|
||||||
.type = r->type,
|
.type = r->type,
|
||||||
.format = r->format,
|
.format = r->format,
|
||||||
.r = r,
|
.r = r,
|
||||||
|
@ -73,7 +76,7 @@ xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t apr
|
||||||
|
|
||||||
// Return it
|
// Return it
|
||||||
if (prop.nitems) {
|
if (prop.nitems) {
|
||||||
p = *prop.p32;
|
p = (xcb_window_t)*prop.p32;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_winprop(&prop);
|
free_winprop(&prop);
|
||||||
|
@ -182,7 +185,7 @@ int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
|
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
|
||||||
const xcb_render_pictforminfo_t *pictfmt,
|
const xcb_render_pictforminfo_t *pictfmt,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr) {
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
if (attr) {
|
if (attr) {
|
||||||
|
@ -208,7 +211,7 @@ x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual,
|
x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr) {
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
|
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
|
||||||
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
|
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
|
||||||
|
@ -216,7 +219,7 @@ x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visu
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard,
|
x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr) {
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
x_get_server_pictfmts(c);
|
x_get_server_pictfmts(c);
|
||||||
|
|
||||||
|
@ -229,12 +232,12 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard
|
||||||
* Create an picture.
|
* Create an picture.
|
||||||
*/
|
*/
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, int hei,
|
x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
|
||||||
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
|
const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr) {
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
int depth = pictfmt->depth;
|
uint8_t depth = pictfmt->depth;
|
||||||
|
|
||||||
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, wid, hei);
|
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, w, h);
|
||||||
if (!tmp_pixmap)
|
if (!tmp_pixmap)
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
|
|
||||||
|
@ -248,7 +251,7 @@ x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, in
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
|
x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
|
||||||
xcb_visualid_t visual, unsigned long valuemask,
|
xcb_visualid_t visual, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr) {
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
||||||
return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
|
return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
|
||||||
|
@ -279,21 +282,22 @@ bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_
|
||||||
}
|
}
|
||||||
|
|
||||||
void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
|
void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
|
||||||
int clip_x_origin, int clip_y_origin, const region_t *reg) {
|
int16_t clip_x_origin, int16_t clip_y_origin,
|
||||||
|
const region_t *reg) {
|
||||||
int nrects;
|
int nrects;
|
||||||
const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects);
|
const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects);
|
||||||
auto xrects = ccalloc(nrects, xcb_rectangle_t);
|
auto xrects = ccalloc(nrects, xcb_rectangle_t);
|
||||||
for (int i = 0; i < nrects; i++)
|
for (int i = 0; i < nrects; i++)
|
||||||
xrects[i] = (xcb_rectangle_t){
|
xrects[i] = (xcb_rectangle_t){
|
||||||
.x = rects[i].x1,
|
.x = to_i16_checked(rects[i].x1),
|
||||||
.y = rects[i].y1,
|
.y = to_i16_checked(rects[i].y1),
|
||||||
.width = rects[i].x2 - rects[i].x1,
|
.width = to_u16_checked(rects[i].x2 - rects[i].x1),
|
||||||
.height = rects[i].y2 - rects[i].y1,
|
.height = to_u16_checked(rects[i].y2 - rects[i].y1),
|
||||||
};
|
};
|
||||||
|
|
||||||
xcb_generic_error_t *e =
|
xcb_generic_error_t *e = xcb_request_check(
|
||||||
xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(
|
c, xcb_render_set_picture_clip_rectangles_checked(
|
||||||
c, pict, clip_x_origin, clip_y_origin, nrects, xrects));
|
c, pict, clip_x_origin, clip_y_origin, to_u32_checked(nrects), xrects));
|
||||||
if (e)
|
if (e)
|
||||||
log_error("Failed to set clip region");
|
log_error("Failed to set clip region");
|
||||||
free(e);
|
free(e);
|
||||||
|
@ -321,7 +325,7 @@ enum { XSyncBadCounter = 0,
|
||||||
*
|
*
|
||||||
* XXX consider making this error to string
|
* XXX consider making this error to string
|
||||||
*/
|
*/
|
||||||
void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) {
|
void x_print_error(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_code) {
|
||||||
session_t *const ps = ps_g;
|
session_t *const ps = ps_g;
|
||||||
|
|
||||||
int o = 0;
|
int o = 0;
|
||||||
|
@ -405,10 +409,10 @@ void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t e
|
||||||
* Create a pixmap and check that creation succeeded.
|
* Create a pixmap and check that creation succeeded.
|
||||||
*/
|
*/
|
||||||
xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable,
|
xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable,
|
||||||
uint16_t width, uint16_t height) {
|
int width, int height) {
|
||||||
xcb_pixmap_t pix = xcb_generate_id(c);
|
xcb_pixmap_t pix = xcb_generate_id(c);
|
||||||
xcb_void_cookie_t cookie =
|
xcb_void_cookie_t cookie = xcb_create_pixmap_checked(
|
||||||
xcb_create_pixmap_checked(c, depth, pix, drawable, width, height);
|
c, depth, pix, drawable, to_u16_checked(width), to_u16_checked(height));
|
||||||
xcb_generic_error_t *err = xcb_request_check(c, cookie);
|
xcb_generic_error_t *err = xcb_request_check(c, cookie);
|
||||||
if (err == NULL)
|
if (err == NULL)
|
||||||
return pix;
|
return pix;
|
||||||
|
@ -456,7 +460,7 @@ xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) {
|
||||||
winprop_t prop =
|
winprop_t prop =
|
||||||
wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32);
|
wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32);
|
||||||
if (prop.nitems) {
|
if (prop.nitems) {
|
||||||
pixmap = *prop.p32;
|
pixmap = (xcb_pixmap_t)*prop.p32;
|
||||||
free_winprop(&prop);
|
free_winprop(&prop);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -523,10 +527,10 @@ bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) {
|
||||||
* @param[inout] size size of the array pointed to by `ret`, in number of elements
|
* @param[inout] size size of the array pointed to by `ret`, in number of elements
|
||||||
* @return number of elements filled into `*ret`
|
* @return number of elements filled into `*ret`
|
||||||
*/
|
*/
|
||||||
size_t x_picture_filter_from_conv(const conv *kernel, double center,
|
int x_picture_filter_from_conv(const conv *kernel, double center,
|
||||||
xcb_render_fixed_t **ret, size_t *size) {
|
xcb_render_fixed_t **ret, size_t *size) {
|
||||||
if (*size < (size_t)(kernel->w * kernel->h + 2)) {
|
if (*size < (size_t)(kernel->w * kernel->h + 2)) {
|
||||||
*size = kernel->w * kernel->h + 2;
|
*size = (size_t)(kernel->w * kernel->h + 2);
|
||||||
*ret = crealloc(*ret, *size);
|
*ret = crealloc(*ret, *size);
|
||||||
}
|
}
|
||||||
auto buf = *ret;
|
auto buf = *ret;
|
||||||
|
@ -550,18 +554,18 @@ size_t x_picture_filter_from_conv(const conv *kernel, double center,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a search criteria for fbconfig from a X visual.
|
/// Generate a search criteria for fbconfig from a X visual.
|
||||||
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
/// Returns {-1, -1, -1, -1, -1, 0} on failure
|
||||||
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
|
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
||||||
auto depth = x_get_visual_depth(c, visual);
|
auto depth = x_get_visual_depth(c, visual);
|
||||||
if (!pictfmt || depth == -1) {
|
if (!pictfmt || depth == -1) {
|
||||||
log_error("Invalid visual %#03x", visual);
|
log_error("Invalid visual %#03x", visual);
|
||||||
return (struct xvisual_info){-1, -1, -1, -1, -1, -1};
|
return (struct xvisual_info){-1, -1, -1, -1, -1, 0};
|
||||||
}
|
}
|
||||||
if (pictfmt->type != XCB_RENDER_PICT_TYPE_DIRECT) {
|
if (pictfmt->type != XCB_RENDER_PICT_TYPE_DIRECT) {
|
||||||
log_error("compton cannot handle non-DirectColor visuals. Report an "
|
log_error("compton cannot handle non-DirectColor visuals. Report an "
|
||||||
"issue if you see this error message.");
|
"issue if you see this error message.");
|
||||||
return (struct xvisual_info){-1, -1, -1, -1, -1, -1};
|
return (struct xvisual_info){-1, -1, -1, -1, -1, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
int red_size = popcountl(pictfmt->direct.red_mask),
|
int red_size = popcountl(pictfmt->direct.red_mask),
|
||||||
|
@ -578,3 +582,14 @@ struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual
|
||||||
.visual = visual,
|
.visual = visual,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) {
|
||||||
|
xcb_screen_iterator_t iter;
|
||||||
|
|
||||||
|
iter = xcb_setup_roots_iterator(xcb_get_setup(c));
|
||||||
|
for (; iter.rem; --screen, xcb_screen_next(&iter))
|
||||||
|
if (screen == 0)
|
||||||
|
return iter.data;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
30
src/x.h
30
src/x.h
|
@ -88,13 +88,13 @@ static inline void x_sync(xcb_connection_t *c) {
|
||||||
* and number of items. A blank one on failure.
|
* and number of items. A blank one on failure.
|
||||||
*/
|
*/
|
||||||
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
|
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
|
||||||
long offset, long length, xcb_atom_t rtype, int rformat);
|
int offset, int length, xcb_atom_t rtype, int rformat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper of wid_get_prop_adv().
|
* Wrapper of wid_get_prop_adv().
|
||||||
*/
|
*/
|
||||||
static inline winprop_t wid_get_prop(const session_t *ps, xcb_window_t wid, xcb_atom_t atom,
|
static inline winprop_t wid_get_prop(const session_t *ps, xcb_window_t wid, xcb_atom_t atom,
|
||||||
long length, xcb_atom_t rtype, int rformat) {
|
int length, xcb_atom_t rtype, int rformat) {
|
||||||
return wid_get_prop_adv(ps, wid, atom, 0L, length, rtype, rformat);
|
return wid_get_prop_adv(ps, wid, atom, 0L, length, rtype, rformat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,19 +118,19 @@ int x_get_visual_depth(xcb_connection_t *, xcb_visualid_t);
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *,
|
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *,
|
||||||
const xcb_render_pictforminfo_t *pictfmt,
|
const xcb_render_pictforminfo_t *pictfmt,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
attr_nonnull(1, 2);
|
attr_nonnull(1, 2);
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual_and_pixmap(xcb_connection_t *, xcb_visualid_t visual,
|
x_create_picture_with_visual_and_pixmap(xcb_connection_t *, xcb_visualid_t visual,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
attr_nonnull(1);
|
attr_nonnull(1);
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_t standard,
|
x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_t standard,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
attr_nonnull(1);
|
attr_nonnull(1);
|
||||||
|
|
||||||
|
@ -138,22 +138,22 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_
|
||||||
* Create an picture.
|
* Create an picture.
|
||||||
*/
|
*/
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei,
|
x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int w, int h,
|
||||||
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
|
const xcb_render_pictforminfo_t *pictfmt, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
attr_nonnull(1, 5);
|
attr_nonnull(1, 5);
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h,
|
x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h,
|
||||||
xcb_visualid_t visual, unsigned long valuemask,
|
xcb_visualid_t visual, uint32_t valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
attr_nonnull(1);
|
attr_nonnull(1);
|
||||||
|
|
||||||
/// Fetch a X region and store it in a pixman region
|
/// Fetch a X region and store it in a pixman region
|
||||||
bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res);
|
bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res);
|
||||||
|
|
||||||
void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t,
|
void x_set_picture_clip_region(xcb_connection_t *, xcb_render_picture_t, int16_t clip_x_origin,
|
||||||
int clip_x_origin, int clip_y_origin, const region_t *);
|
int16_t clip_y_origin, const region_t *);
|
||||||
|
|
||||||
void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict);
|
void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict);
|
||||||
|
|
||||||
|
@ -162,10 +162,10 @@ void x_clear_picture_clip_region(xcb_connection_t *, xcb_render_picture_t pict);
|
||||||
*
|
*
|
||||||
* XXX consider making this error to string
|
* XXX consider making this error to string
|
||||||
*/
|
*/
|
||||||
void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code);
|
void x_print_error(unsigned long serial, uint8_t major, uint16_t minor, uint8_t error_code);
|
||||||
|
|
||||||
xcb_pixmap_t x_create_pixmap(xcb_connection_t *, uint8_t depth, xcb_drawable_t drawable,
|
xcb_pixmap_t x_create_pixmap(xcb_connection_t *, uint8_t depth, xcb_drawable_t drawable,
|
||||||
uint16_t width, uint16_t height);
|
int width, int height);
|
||||||
|
|
||||||
bool x_validate_pixmap(xcb_connection_t *, xcb_pixmap_t pxmap);
|
bool x_validate_pixmap(xcb_connection_t *, xcb_pixmap_t pxmap);
|
||||||
|
|
||||||
|
@ -202,11 +202,13 @@ bool x_fence_sync(xcb_connection_t *, xcb_sync_fence_t);
|
||||||
* will be allocated, and `*ret` will be updated.
|
* will be allocated, and `*ret` will be updated.
|
||||||
* @param[inout] size size of the array pointed to by `ret`.
|
* @param[inout] size size of the array pointed to by `ret`.
|
||||||
*/
|
*/
|
||||||
size_t x_picture_filter_from_conv(const conv *kernel, double center,
|
int x_picture_filter_from_conv(const conv *kernel, double center,
|
||||||
xcb_render_fixed_t **ret, size_t *size);
|
xcb_render_fixed_t **ret, size_t *size);
|
||||||
|
|
||||||
/// Generate a search criteria for fbconfig from a X visual.
|
/// Generate a search criteria for fbconfig from a X visual.
|
||||||
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
||||||
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
|
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
|
||||||
|
|
||||||
xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
|
xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
|
||||||
|
|
||||||
|
xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen);
|
||||||
|
|
Loading…
Reference in New Issue