Run clang-format

Now we have a consistent style across the codebase.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2019-03-10 12:35:38 +00:00
parent 7845673734
commit 22da17630f
20 changed files with 8594 additions and 9013 deletions
+1155 -1242
View File
File diff suppressed because it is too large Load Diff
+531 -584
View File
File diff suppressed because it is too large Load Diff
+2240 -2354
View File
File diff suppressed because it is too large Load Diff
+55 -62
View File
@@ -6,24 +6,24 @@
// === Includes === // === Includes ===
#include <stdlib.h>
#include <stdbool.h>
#include <locale.h> #include <locale.h>
#include <stdbool.h>
#include <stdlib.h>
#include <xcb/xproto.h> #include <xcb/xproto.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include "common.h"
#include "backend/backend.h" #include "backend/backend.h"
#include "win.h"
#include "x.h"
#include "c2.h" #include "c2.h"
#include "log.h" // XXX clean up #include "common.h"
#include "region.h"
#include "compiler.h" #include "compiler.h"
#include "config.h"
#include "log.h" // XXX clean up
#include "region.h"
#include "render.h"
#include "types.h" #include "types.h"
#include "utils.h" #include "utils.h"
#include "render.h" #include "win.h"
#include "config.h" #include "x.h"
// == Functions == // == Functions ==
// TODO move static inline functions that are only used in compton.c, into // TODO move static inline functions that are only used in compton.c, into
@@ -36,21 +36,19 @@ void add_damage(session_t *ps, const region_t *damage);
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode); long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
xcb_window_t xcb_window_t find_client_win(session_t *ps, xcb_window_t w);
find_client_win(session_t *ps, xcb_window_t w);
win *find_toplevel2(session_t *ps, xcb_window_t wid); win *find_toplevel2(session_t *ps, xcb_window_t wid);
/** /**
* Set a <code>switch_t</code> array of all unset wintypes to true. * Set a <code>switch_t</code> array of all unset wintypes to true.
*/ */
static inline void static inline void wintype_arr_enable_unset(switch_t arr[]) {
wintype_arr_enable_unset(switch_t arr[]) { wintype_t i;
wintype_t i;
for (i = 0; i < NUM_WINTYPES; ++i) for (i = 0; i < NUM_WINTYPES; ++i)
if (UNSET == arr[i]) if (UNSET == arr[i])
arr[i] = ON; arr[i] = ON;
} }
/** /**
@@ -60,81 +58,76 @@ wintype_arr_enable_unset(switch_t arr[]) {
* @param count amount of elements in the array * @param count amount of elements in the array
* @param wid window ID to search for * @param wid window ID to search for
*/ */
static inline bool static inline bool array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) {
array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) { while (count--) {
while (count--) { if (arr[count] == wid) {
if (arr[count] == wid) { return true;
return true; }
} }
}
return false; return false;
} }
/** /**
* Destroy a condition list. * Destroy a condition list.
*/ */
static inline void static inline void free_wincondlst(c2_lptr_t **pcondlst) {
free_wincondlst(c2_lptr_t **pcondlst) { while ((*pcondlst = c2_free_lptr(*pcondlst)))
while ((*pcondlst = c2_free_lptr(*pcondlst))) continue;
continue;
} }
#ifndef CONFIG_OPENGL #ifndef CONFIG_OPENGL
static inline void static inline void free_paint_glx(session_t *ps, paint_t *p) {
free_paint_glx(session_t *ps, paint_t *p) {} }
static inline void static inline void free_win_res_glx(session_t *ps, win *w) {
free_win_res_glx(session_t *ps, win *w) {} }
#endif #endif
/** /**
* Create a XTextProperty of a single string. * Create a XTextProperty of a single string.
*/ */
static inline XTextProperty * static inline XTextProperty *make_text_prop(session_t *ps, char *str) {
make_text_prop(session_t *ps, char *str) { XTextProperty *pprop = ccalloc(1, XTextProperty);
XTextProperty *pprop = ccalloc(1, XTextProperty);
if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) { if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) {
cxfree(pprop->value); cxfree(pprop->value);
free(pprop); free(pprop);
pprop = NULL; pprop = NULL;
} }
return pprop; return pprop;
} }
/** /**
* Set a single-string text property on a window. * Set a single-string text property on a window.
*/ */
static inline bool static inline bool
wid_set_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop_atom, char *str) { wid_set_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop_atom, char *str) {
XTextProperty *pprop = make_text_prop(ps, str); XTextProperty *pprop = make_text_prop(ps, str);
if (!pprop) { if (!pprop) {
log_error("Failed to make text property: %s.", str); log_error("Failed to make text property: %s.", str);
return false; return false;
} }
XSetTextProperty(ps->dpy, wid, pprop, prop_atom); XSetTextProperty(ps->dpy, wid, pprop, prop_atom);
cxfree(pprop->value); cxfree(pprop->value);
cxfree(pprop); cxfree(pprop);
return true; return true;
} }
/** /**
* Dump an drawable's info. * Dump an drawable's info.
*/ */
static inline void static inline void dump_drawable(session_t *ps, xcb_drawable_t drawable) {
dump_drawable(session_t *ps, xcb_drawable_t drawable) { auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL);
auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL); if (!r) {
if (!r) { log_trace("Drawable %#010x: Failed", drawable);
log_trace("Drawable %#010x: Failed", drawable); return;
return; }
} log_trace("Drawable %#010x: x = %u, y = %u, wid = %u, hei = %d, b = %u, d = %u",
log_trace("Drawable %#010x: x = %u, y = %u, wid = %u, hei = %d, b = %u, d = %u", drawable, r->x, r->y, r->width, r->height, r->border_width, r->depth);
drawable, r->x, r->y, r->width, r->height, r->border_width, r->depth); free(r);
free(r);
} }
// vim: set et sw=2 : // vim: set et sw=2 :
+351 -316
View File
@@ -2,22 +2,22 @@
// Copyright (c) 2011-2013, Christopher Jeffrey // Copyright (c) 2011-2013, Christopher Jeffrey
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com> // Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <xcb/render.h> // for xcb_render_fixed_t, XXX #include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
#include "compiler.h"
#include "common.h"
#include "utils.h"
#include "c2.h" #include "c2.h"
#include "string_utils.h" #include "common.h"
#include "compiler.h"
#include "kernel.h"
#include "log.h" #include "log.h"
#include "region.h" #include "region.h"
#include "string_utils.h"
#include "types.h" #include "types.h"
#include "kernel.h" #include "utils.h"
#include "win.h" #include "win.h"
#include "config.h" #include "config.h"
@@ -25,22 +25,21 @@
/** /**
* Parse a long number. * Parse a long number.
*/ */
bool bool parse_long(const char *s, long *dest) {
parse_long(const char *s, long *dest) { const char *endptr = NULL;
const char *endptr = NULL; long val = strtol(s, (char **)&endptr, 0);
long val = strtol(s, (char **) &endptr, 0); if (!endptr || endptr == s) {
if (!endptr || endptr == s) { log_error("Invalid number: %s", s);
log_error("Invalid number: %s", s); return false;
return false; }
} while (isspace(*endptr))
while (isspace(*endptr)) ++endptr;
++endptr; if (*endptr) {
if (*endptr) { log_error("Trailing characters: %s", s);
log_error("Trailing characters: %s", s); return false;
return false; }
} *dest = val;
*dest = val; return true;
return true;
} }
/** /**
@@ -51,19 +50,18 @@ parse_long(const char *s, long *dest) {
* @param[out] dest return the number parsed from the string * @param[out] dest return the number parsed from the string
* @return pointer to the last character parsed * @return pointer to the last character parsed
*/ */
const char * const char *parse_readnum(const char *src, double *dest) {
parse_readnum(const char *src, double *dest) { const char *pc = NULL;
const char *pc = NULL; double val = strtod_simple(src, &pc);
double val = strtod_simple(src, &pc); if (!pc || pc == src) {
if (!pc || pc == src) { log_error("No number found: %s", src);
log_error("No number found: %s", src); return src;
return src; }
} while (*pc && (isspace(*pc) || *pc == ',')) {
while (*pc && (isspace(*pc) || *pc == ',')) { ++pc;
++pc; }
} *dest = val;
*dest = val; return pc;
return pc;
} }
/** /**
@@ -73,93 +71,92 @@ parse_readnum(const char *src, double *dest) {
* @param[out] endptr return where the end of kernel is in the string * @param[out] endptr return where the end of kernel is in the string
* @param[out] hasneg whether the kernel has negative values * @param[out] hasneg whether the kernel has negative values
*/ */
conv * conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
parse_blur_kern(const char *src, const char **endptr, bool *hasneg) { int width = 0, height = 0;
int width = 0, height = 0; *hasneg = false;
*hasneg = false;
const char *pc = NULL; const char *pc = NULL;
// Get matrix width and height // Get matrix width and height
double val = 0.0; double val = 0.0;
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 = 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 = val;
// Validate matrix width and height // Validate matrix width and height
if (width <= 0 || height <= 0) { if (width <= 0 || height <= 0) {
log_error("Blue kernel width/height can't be negative."); log_error("Blue kernel width/height can't be negative.");
goto err1; goto err1;
} }
if (!(width % 2 && height % 2)) { if (!(width % 2 && height % 2)) {
log_error("Blur kernel width/height must be odd."); log_error("Blur kernel width/height must be odd.");
goto err1; goto err1;
} }
if (width > 16 || height > 16) if (width > 16 || height > 16)
log_warn("Blur kernel width/height too large, may slow down" log_warn("Blur kernel width/height too large, may slow down"
"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) + width * height * sizeof(double));
// Read elements // Read elements
int skip = height / 2 * width + width / 2; int skip = height / 2 * width + width / 2;
for (int i = 0; i < width * height; ++i) { for (int i = 0; i < width * height; ++i) {
// Ignore the center element // Ignore the center element
if (i == skip) { if (i == skip) {
matrix->data[i] = 0; matrix->data[i] = 0;
continue; continue;
} }
if (src == (pc = parse_readnum(src, &val))) { if (src == (pc = parse_readnum(src, &val))) {
goto err2; goto err2;
} }
src = pc; src = pc;
if (val < 0) { if (val < 0) {
*hasneg = true; *hasneg = true;
} }
matrix->data[i] = val; matrix->data[i] = val;
} }
// Detect trailing characters // Detect trailing characters
for (;*pc && *pc != ';'; pc++) { for (; *pc && *pc != ';'; pc++) {
if (!isspace(*pc) && *pc != ',') { if (!isspace(*pc) && *pc != ',') {
// TODO isspace is locale aware, be careful // TODO isspace is locale aware, be careful
log_error("Trailing characters in blur kernel string."); log_error("Trailing characters in blur kernel string.");
goto err2; goto err2;
} }
} }
// Jump over spaces after ';' // Jump over spaces after ';'
if (*pc == ';') { if (*pc == ';') {
pc++; pc++;
while (*pc && isspace(*pc)) { while (*pc && isspace(*pc)) {
++pc; ++pc;
} }
} }
// Require an end of string if endptr is not provided, otherwise // Require an end of string if endptr is not provided, otherwise
// copy end pointer to endptr // copy end pointer to endptr
if (endptr) { if (endptr) {
*endptr = pc; *endptr = pc;
} else if (*pc) { } else if (*pc) {
log_error("Only one blur kernel expected."); log_error("Only one blur kernel expected.");
goto err2; goto err2;
} }
// Fill in width and height // Fill in width and height
matrix->w = width; matrix->w = width;
matrix->h = height; matrix->h = height;
return matrix; return matrix;
err2: err2:
free(matrix); free(matrix);
err1: err1:
return NULL; return NULL;
} }
/** /**
@@ -172,63 +169,104 @@ err1:
* @param[out] hasneg whether any of the kernels have negative values * @param[out] hasneg whether any of the kernels have negative values
* @return if the `src` string is a valid kernel list string * @return if the `src` string is a valid kernel list string
*/ */
bool bool parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) { // TODO just return a predefined kernels, not parse predefined strings...
// TODO just return a predefined kernels, not parse predefined strings... static const struct {
static const struct { const char *name;
const char *name; const char *kern_str;
const char *kern_str; } CONV_KERN_PREDEF[] = {
} CONV_KERN_PREDEF[] = { {"3x3box", "3,3,1,1,1,1,1,1,1,1,"},
{ "3x3box", "3,3,1,1,1,1,1,1,1,1," }, {"5x5box", "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"},
{ "5x5box", "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," }, {"7x7box", "7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"
{ "7x7box", "7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," }, "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"},
{ "3x3gaussian", "3,3,0.243117,0.493069,0.243117,0.493069,0.493069,0.243117,0.493069,0.243117," }, {"3x3gaussian", "3,3,0.243117,0.493069,0.243117,0.493069,0.493069,0.243117,0."
{ "5x5gaussian", "5,5,0.003493,0.029143,0.059106,0.029143,0.003493,0.029143,0.243117,0.493069,0.243117,0.029143,0.059106,0.493069,0.493069,0.059106,0.029143,0.243117,0.493069,0.243117,0.029143,0.003493,0.029143,0.059106,0.029143,0.003493," }, "493069,0.243117,"},
{ "7x7gaussian", "7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003," }, {"5x5gaussian", "5,5,0.003493,0.029143,0.059106,0.029143,0.003493,0.029143,0."
{ "9x9gaussian", "9,9,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000012,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000," }, "243117,0.493069,0.243117,0.029143,0.059106,0.493069,0."
{ "11x11gaussian", "11,11,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000012,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000," }, "493069,0.059106,0.029143,0.243117,0.493069,0.243117,0."
}; "029143,0.003493,0.029143,0.059106,0.029143,0.003493,"},
{"7x7gaussian", "7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0."
"000003,0.000102,0.003493,0.029143,0.059106,0.029143,0."
"003493,0.000102,0.000849,0.029143,0.243117,0.493069,0."
"243117,0.029143,0.000849,0.001723,0.059106,0.493069,0."
"493069,0.059106,0.001723,0.000849,0.029143,0.243117,0."
"493069,0.243117,0.029143,0.000849,0.000102,0.003493,0."
"029143,0.059106,0.029143,0.003493,0.000102,0.000003,0."
"000102,0.000849,0.001723,0.000849,0.000102,0.000003,"},
{"9x9gaussian",
"9,9,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0."
"000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0."
"000102,0.000003,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0."
"029143,0.003493,0.000102,0.000001,0.000006,0.000849,0.029143,0.243117,0."
"493069,0.243117,0.029143,0.000849,0.000006,0.000012,0.001723,0.059106,0."
"493069,0.493069,0.059106,0.001723,0.000012,0.000006,0.000849,0.029143,0."
"243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000001,0.000102,0."
"003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0."
"000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0."
"000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0."
"000000,"},
{"11x11gaussian",
"11,11,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0."
"000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0."
"000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0."
"000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0."
"000000,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0."
"029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000006,0.000849,0."
"029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0."
"000000,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0."
"000012,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0."
"243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000001,0.000102,0."
"003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0."
"000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0."
"000003,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0."
"000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0."
"000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0."
"000000,"},
};
*hasneg = false; *hasneg = false;
for (unsigned int i = 0; for (unsigned int i = 0;
i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) { i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) {
if (!strcmp(CONV_KERN_PREDEF[i].name, src)) if (!strcmp(CONV_KERN_PREDEF[i].name, src))
return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest, max, hasneg); return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest,
} max, hasneg);
}
int i = 0; int i = 0;
const char *pc = src; const char *pc = src;
// Free old kernels // Free old kernels
for (i = 0; i < max; ++i) { for (i = 0; i < max; ++i) {
free(dest[i]); free(dest[i]);
dest[i] = NULL; dest[i] = NULL;
} }
// Continue parsing until the end of source string // Continue parsing until the end of source string
i = 0; i = 0;
while (pc && *pc && i < max - 1) { while (pc && *pc && i < max - 1) {
bool tmp_hasneg; bool tmp_hasneg;
dest[i] = parse_blur_kern(pc, &pc, &tmp_hasneg); dest[i] = parse_blur_kern(pc, &pc, &tmp_hasneg);
if (!dest[i]) { if (!dest[i]) {
return false; return false;
} }
i++; i++;
*hasneg |= tmp_hasneg; *hasneg |= tmp_hasneg;
} }
if (i > 1) { if (i > 1) {
log_warn("You are seeing this message because your are using multipassblur. Please " log_warn("You are seeing this message because your are using "
"report an issue to us so we know multipass blur is actually been used. " "multipassblur. Please "
"Otherwise it might be removed in future releases"); "report an issue to us so we know multipass blur is actually "
} "been used. "
"Otherwise it might be removed in future releases");
}
if (*pc) { if (*pc) {
log_error("Too many blur kernels!"); log_error("Too many blur kernels!");
return false; return false;
} }
return true; return true;
} }
/** /**
@@ -236,187 +274,184 @@ parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
* *
* ps->root_width and ps->root_height must be valid * ps->root_width and ps->root_height must be valid
*/ */
bool bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
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 }; geometry_t geom = {.wid = ps->root_width, .hei = ps->root_height, .x = 0, .y = 0};
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; geom.wid = val;
if (geom.wid < 0) { if (geom.wid < 0) {
log_error("Invalid width: %s", src); log_error("Invalid width: %s", src);
return false; return false;
} }
src = endptr; src = endptr;
} }
src = skip_space(src); src = skip_space(src);
} }
// Parse height // Parse height
if ('x' == *src) { if ('x' == *src) {
++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; geom.hei = val;
if (geom.hei < 0) { if (geom.hei < 0) {
log_error("Invalid height: %s", src); log_error("Invalid height: %s", src);
return false; return false;
} }
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; geom.x = val;
if (*src == '-') if (*src == '-')
geom.x += ps->root_width - geom.wid; geom.x += ps->root_width - geom.wid;
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; geom.y = val;
if (*src == '-') if (*src == '-')
geom.y += ps->root_height - geom.hei; geom.y += ps->root_height - geom.hei;
src = endptr; src = endptr;
} }
src = skip_space(src); src = skip_space(src);
} }
if (*src) { if (*src) {
log_error("Trailing characters: %s", src); log_error("Trailing characters: %s", src);
return false; return false;
} }
parse_geometry_end: parse_geometry_end:
pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei); pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei);
return true; return true;
} }
/** /**
* Parse a list of opacity rules. * Parse a list of opacity rules.
*/ */
bool parse_rule_opacity(c2_lptr_t **res, const char *src) { bool parse_rule_opacity(c2_lptr_t **res, const char *src) {
// Find opacity value // Find opacity value
char *endptr = NULL; char *endptr = NULL;
long val = strtol(src, &endptr, 0); long val = strtol(src, &endptr, 0);
if (!endptr || endptr == src) { if (!endptr || endptr == src) {
log_error("No opacity specified: %s", src); log_error("No opacity specified: %s", src);
return false; return false;
} }
if (val > 100 || val < 0) { if (val > 100 || val < 0) {
log_error("Opacity %ld invalid: %s", val, src); log_error("Opacity %ld invalid: %s", val, src);
return false; return false;
} }
// Skip over spaces // Skip over spaces
while (*endptr && isspace(*endptr)) while (*endptr && isspace(*endptr))
++endptr; ++endptr;
if (':' != *endptr) { if (':' != *endptr) {
log_error("Opacity terminator not found: %s", src); log_error("Opacity terminator not found: %s", src);
return false; return false;
} }
++endptr; ++endptr;
// Parse pattern // Parse pattern
// I hope 1-100 is acceptable for (void *) // I hope 1-100 is acceptable for (void *)
return c2_parse(res, endptr, (void *) val); return c2_parse(res, endptr, (void *)val);
} }
/** /**
* Add a pattern to a condition linked list. * Add a pattern to a condition linked list.
*/ */
bool bool condlst_add(c2_lptr_t **pcondlst, const char *pattern) {
condlst_add(c2_lptr_t **pcondlst, const char *pattern) { if (!pattern)
if (!pattern) return false;
return false;
if (!c2_parse(pcondlst, pattern, NULL)) if (!c2_parse(pcondlst, pattern, NULL))
exit(1); exit(1);
return true; return true;
} }
void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_enable, bool fading_enable) { void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_enable,
// Apply default wintype options. bool fading_enable) {
if (!mask[WINTYPE_DESKTOP].shadow) { // Apply default wintype options.
// Desktop windows are always drawn without shadow by default. if (!mask[WINTYPE_DESKTOP].shadow) {
mask[WINTYPE_DESKTOP].shadow = true; // Desktop windows are always drawn without shadow by default.
opt->wintype_option[WINTYPE_DESKTOP].shadow = false; mask[WINTYPE_DESKTOP].shadow = true;
} opt->wintype_option[WINTYPE_DESKTOP].shadow = false;
}
// Focused/unfocused state only apply to a few window types, all other windows // Focused/unfocused state only apply to a few window types, all other windows
// are always considered focused. // are always considered focused.
const wintype_t nofocus_type[] = const wintype_t nofocus_type[] = {WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY};
{ WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY }; for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) {
for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) { if (!mask[nofocus_type[i]].focus) {
if (!mask[nofocus_type[i]].focus) { mask[nofocus_type[i]].focus = true;
mask[nofocus_type[i]].focus = true; opt->wintype_option[nofocus_type[i]].focus = false;
opt->wintype_option[nofocus_type[i]].focus = false; }
} }
} for (unsigned long i = 0; i < NUM_WINTYPES; i++) {
for (unsigned long i = 0; i < NUM_WINTYPES; i++) { if (!mask[i].shadow) {
if (!mask[i].shadow) { mask[i].shadow = true;
mask[i].shadow = true; opt->wintype_option[i].shadow = shadow_enable;
opt->wintype_option[i].shadow = shadow_enable; }
} if (!mask[i].fade) {
if (!mask[i].fade) { mask[i].fade = true;
mask[i].fade = true; opt->wintype_option[i].fade = fading_enable;
opt->wintype_option[i].fade = fading_enable; }
} if (!mask[i].focus) {
if (!mask[i].focus) { mask[i].focus = true;
mask[i].focus = true; opt->wintype_option[i].focus = true;
opt->wintype_option[i].focus = true; }
} if (!mask[i].full_shadow) {
if (!mask[i].full_shadow) { mask[i].full_shadow = true;
mask[i].full_shadow = true; opt->wintype_option[i].full_shadow = false;
opt->wintype_option[i].full_shadow = false; }
} if (!mask[i].redir_ignore) {
if (!mask[i].redir_ignore) { mask[i].redir_ignore = true;
mask[i].redir_ignore = true; opt->wintype_option[i].redir_ignore = false;
opt->wintype_option[i].redir_ignore = false; }
} if (!mask[i].opacity) {
if (!mask[i].opacity) { mask[i].opacity = true;
mask[i].opacity = true; // Opacity is not set to a concrete number here because the
// Opacity is not set to a concrete number here because the opacity logic // opacity logic is complicated, and needs an "unset" state
// is complicated, and needs an "unset" state opt->wintype_option[i].opacity = NAN;
opt->wintype_option[i].opacity = NAN; }
} }
}
} }
char *parse_config(options_t *opt, const char *config_file, char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
bool *shadow_enable, bool *fading_enable, bool *hasneg, bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask) {
win_option_mask_t *winopt_mask) { char *ret = NULL;
char *ret = NULL;
#ifdef CONFIG_LIBCONFIG #ifdef CONFIG_LIBCONFIG
ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable, ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable,
hasneg, winopt_mask); hasneg, winopt_mask);
#endif #endif
return ret; return ret;
} }
+8 -9
View File
@@ -7,24 +7,24 @@
/// Common functions and definitions for configuration parsing /// Common functions and definitions for configuration parsing
/// Used for command line arguments and config files /// Used for command line arguments and config files
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
#include <xcb/xfixes.h> #include <xcb/xfixes.h>
#ifdef CONFIG_LIBCONFIG #ifdef CONFIG_LIBCONFIG
#include <libconfig.h> #include <libconfig.h>
#endif #endif
#include "region.h"
#include "log.h"
#include "compiler.h" #include "compiler.h"
#include "win.h"
#include "types.h"
#include "kernel.h" #include "kernel.h"
#include "log.h"
#include "region.h"
#include "types.h"
#include "win.h"
typedef struct session session_t; typedef struct session session_t;
@@ -242,8 +242,7 @@ extern const char *const VSYNC_STRS[NUM_VSYNC + 1];
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 *); attr_warn_unused_result bool parse_long(const char *, long *);
attr_warn_unused_result bool attr_warn_unused_result bool parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *); attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *);
attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *); attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *);
+390 -400
View File
@@ -1,22 +1,22 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright (c) 2012-2014 Richard Grenville <pyxlcy@gmail.com> // Copyright (c) 2012-2014 Richard Grenville <pyxlcy@gmail.com>
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <libconfig.h>
#include <basedir_fs.h> #include <basedir_fs.h>
#include <libconfig.h>
#include <libgen.h>
#include "err.h"
#include "common.h" #include "common.h"
#include "compiler.h" #include "compiler.h"
#include "config.h" #include "config.h"
#include "string_utils.h" #include "err.h"
#include "options.h"
#include "log.h" #include "log.h"
#include "options.h"
#include "string_utils.h"
#include "utils.h" #include "utils.h"
#include "win.h" #include "win.h"
@@ -27,37 +27,32 @@
* *
* So it takes a pointer to bool. * So it takes a pointer to bool.
*/ */
static inline int static inline int lcfg_lookup_bool(const config_t *config, const char *path, bool *value) {
lcfg_lookup_bool(const config_t *config, const char *path, bool *value) { int ival;
int ival;
int ret = config_lookup_bool(config, path, &ival); int ret = config_lookup_bool(config, path, &ival);
if (ret) if (ret)
*value = ival; *value = ival;
return ret; return ret;
} }
/// Search for config file under a base directory /// Search for config file under a base directory
FILE * FILE *open_config_file_at(const char *base, char **out_path) {
open_config_file_at(const char *base, char **out_path) { static const char *config_paths[] = {"/compton.conf", "/compton/compton.conf"};
static const char *config_paths[] = { for (size_t i = 0; i < ARR_SIZE(config_paths); i++) {
"/compton.conf", char *path = mstrjoin(base, config_paths[i]);
"/compton/compton.conf" FILE *ret = fopen(path, "r");
}; if (ret && out_path) {
for (size_t i = 0; i < ARR_SIZE(config_paths); i++) { *out_path = path;
char *path = mstrjoin(base, config_paths[i]); } else {
FILE *ret = fopen(path, "r"); free(path);
if (ret && out_path) { }
*out_path = path; if (ret) {
} else { return ret;
free(path); }
} }
if (ret) { return NULL;
return ret;
}
}
return NULL;
} }
/** /**
@@ -65,73 +60,71 @@ open_config_file_at(const char *base, char **out_path) {
* *
* Follows the XDG specification to search for the configuration file. * Follows the XDG specification to search for the configuration file.
*/ */
FILE * FILE *open_config_file(const char *cpath, char **ppath) {
open_config_file(const char *cpath, char **ppath) { static const char config_filename_legacy[] = "/.compton.conf";
static const char config_filename_legacy[] = "/.compton.conf";
if (cpath) { if (cpath) {
FILE *ret = fopen(cpath, "r"); FILE *ret = fopen(cpath, "r");
if (ret && ppath) if (ret && ppath)
*ppath = strdup(cpath); *ppath = strdup(cpath);
return ret; return ret;
} }
// First search for config file in user config directory // First search for config file in user config directory
auto config_home = xdgConfigHome(NULL); auto config_home = xdgConfigHome(NULL);
auto ret = open_config_file_at(config_home, ppath); auto ret = open_config_file_at(config_home, ppath);
free((void *)config_home); free((void *)config_home);
if (ret) { if (ret) {
return ret; return ret;
} }
// Fall back to legacy config file in user home directory // Fall back to legacy config file in user home directory
const char *home = getenv("HOME"); const char *home = getenv("HOME");
if (home && strlen(home)) { if (home && strlen(home)) {
auto path = mstrjoin(home, config_filename_legacy); auto path = mstrjoin(home, config_filename_legacy);
ret = fopen(path, "r"); ret = fopen(path, "r");
if (ret && ppath) { if (ret && ppath) {
*ppath = path; *ppath = path;
} else { } else {
free(path); free(path);
} }
if (ret) { if (ret) {
return ret; return ret;
} }
} }
// Fall back to config file in system config directory // Fall back to config file in system config directory
auto config_dirs = xdgConfigDirectories(NULL); auto config_dirs = xdgConfigDirectories(NULL);
for (int i = 0; config_dirs[i]; i++) { for (int i = 0; config_dirs[i]; i++) {
ret = open_config_file_at(config_dirs[i], ppath); ret = open_config_file_at(config_dirs[i], ppath);
if (ret) { if (ret) {
free((void *)config_dirs); free((void *)config_dirs);
return ret; return ret;
} }
} }
free((void *)config_dirs); free((void *)config_dirs);
return NULL; return NULL;
} }
/** /**
* Parse a condition list in configuration file. * Parse a condition list in configuration file.
*/ */
void void parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, const char *name) {
parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, config_setting_t *setting = config_lookup(pcfg, name);
const char *name) { if (setting) {
config_setting_t *setting = config_lookup(pcfg, name); // Parse an array of options
if (setting) { if (config_setting_is_array(setting)) {
// Parse an array of options int i = config_setting_length(setting);
if (config_setting_is_array(setting)) { while (i--)
int i = config_setting_length(setting); condlst_add(pcondlst,
while (i--) config_setting_get_string_elem(setting, i));
condlst_add(pcondlst, config_setting_get_string_elem(setting, i)); }
} // Treat it as a single pattern if it's a string
// Treat it as a single pattern if it's a string else if (CONFIG_TYPE_STRING == config_setting_type(setting)) {
else if (CONFIG_TYPE_STRING == config_setting_type(setting)) { condlst_add(pcondlst, config_setting_get_string(setting));
condlst_add(pcondlst, config_setting_get_string(setting)); }
} }
}
} }
/** /**
@@ -139,22 +132,24 @@ parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst,
*/ */
static inline void static inline void
parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) { parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
config_setting_t *setting = config_lookup(pcfg, name); config_setting_t *setting = config_lookup(pcfg, name);
if (setting) { if (setting) {
// Parse an array of options // Parse an array of options
if (config_setting_is_array(setting)) { if (config_setting_is_array(setting)) {
int i = config_setting_length(setting); int i = config_setting_length(setting);
while (i--) while (i--)
if (!parse_rule_opacity(&opt->opacity_rules, if (!parse_rule_opacity(
config_setting_get_string_elem(setting, i))) &opt->opacity_rules,
exit(1); config_setting_get_string_elem(setting, i)))
} exit(1);
// Treat it as a single pattern if it's a string }
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) { // Treat it as a single pattern if it's a string
if (!parse_rule_opacity(&opt->opacity_rules, config_setting_get_string(setting))) else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
exit(1); if (!parse_rule_opacity(&opt->opacity_rules,
} config_setting_get_string(setting)))
} exit(1);
}
}
} }
/** /**
@@ -163,316 +158,311 @@ parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
* Returns the actually config_file name * Returns the actually config_file name
*/ */
char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shadow_enable, char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shadow_enable,
bool *fading_enable, bool *conv_kern_hasneg, win_option_mask_t *winopt_mask) bool *fading_enable, bool *conv_kern_hasneg,
{ win_option_mask_t *winopt_mask) {
char *path = NULL; char *path = NULL;
FILE *f; FILE *f;
config_t cfg; config_t cfg;
int ival = 0; int ival = 0;
bool bval; bool bval;
double dval = 0.0; double dval = 0.0;
// libconfig manages string memory itself, so no need to manually free // libconfig manages string memory itself, so no need to manually free
// anything // anything
const char *sval = NULL; const char *sval = NULL;
f = open_config_file(config_file, &path); f = open_config_file(config_file, &path);
if (!f) { if (!f) {
free(path); free(path);
if (config_file) { if (config_file) {
log_fatal("Failed to read configuration file \"%s\".", config_file); log_fatal("Failed to read configuration file \"%s\".", config_file);
return ERR_PTR(-1); return ERR_PTR(-1);
} }
return NULL; return NULL;
} }
config_init(&cfg); config_init(&cfg);
{ {
// dirname() could modify the original string, thus we must pass a // dirname() could modify the original string, thus we must pass a
// copy // copy
char *path2 = strdup(path); char *path2 = strdup(path);
char *parent = dirname(path2); char *parent = dirname(path2);
if (parent) if (parent)
config_set_include_dir(&cfg, parent); config_set_include_dir(&cfg, parent);
free(path2); free(path2);
} }
{ {
int read_result = config_read(&cfg, f); int read_result = config_read(&cfg, f);
fclose(f); fclose(f);
f = NULL; f = NULL;
if (read_result == CONFIG_FALSE) { if (read_result == CONFIG_FALSE) {
log_fatal("Error when reading configuration file \"%s\", line %d: %s", log_fatal("Error when reading configuration file \"%s\", line "
path, config_error_line(&cfg), config_error_text(&cfg)); "%d: %s",
goto err; path, config_error_line(&cfg), config_error_text(&cfg));
} goto err;
} }
config_set_auto_convert(&cfg, 1); }
config_set_auto_convert(&cfg, 1);
// Get options from the configuration file. We don't do range checking // Get options from the configuration file. We don't do range checking
// right now. It will be done later // right now. It will be done later
// -D (fade_delta) // -D (fade_delta)
if (config_lookup_int(&cfg, "fade-delta", &ival)) if (config_lookup_int(&cfg, "fade-delta", &ival))
opt->fade_delta = ival; opt->fade_delta = ival;
// -I (fade_in_step) // -I (fade_in_step)
if (config_lookup_float(&cfg, "fade-in-step", &dval)) if (config_lookup_float(&cfg, "fade-in-step", &dval))
opt->fade_in_step = normalize_d(dval); opt->fade_in_step = normalize_d(dval);
// -O (fade_out_step) // -O (fade_out_step)
if (config_lookup_float(&cfg, "fade-out-step", &dval)) if (config_lookup_float(&cfg, "fade-out-step", &dval))
opt->fade_out_step = normalize_d(dval); opt->fade_out_step = normalize_d(dval);
// -r (shadow_radius) // -r (shadow_radius)
config_lookup_int(&cfg, "shadow-radius", &opt->shadow_radius); config_lookup_int(&cfg, "shadow-radius", &opt->shadow_radius);
// -o (shadow_opacity) // -o (shadow_opacity)
config_lookup_float(&cfg, "shadow-opacity", &opt->shadow_opacity); config_lookup_float(&cfg, "shadow-opacity", &opt->shadow_opacity);
// -l (shadow_offset_x) // -l (shadow_offset_x)
config_lookup_int(&cfg, "shadow-offset-x", &opt->shadow_offset_x); config_lookup_int(&cfg, "shadow-offset-x", &opt->shadow_offset_x);
// -t (shadow_offset_y) // -t (shadow_offset_y)
config_lookup_int(&cfg, "shadow-offset-y", &opt->shadow_offset_y); config_lookup_int(&cfg, "shadow-offset-y", &opt->shadow_offset_y);
// -i (inactive_opacity) // -i (inactive_opacity)
if (config_lookup_float(&cfg, "inactive-opacity", &dval)) if (config_lookup_float(&cfg, "inactive-opacity", &dval))
opt->inactive_opacity = normalize_d(dval); opt->inactive_opacity = normalize_d(dval);
// --active_opacity // --active_opacity
if (config_lookup_float(&cfg, "active-opacity", &dval)) if (config_lookup_float(&cfg, "active-opacity", &dval))
opt->active_opacity = normalize_d(dval); opt->active_opacity = normalize_d(dval);
// -e (frame_opacity) // -e (frame_opacity)
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity); config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
// -c (shadow_enable) // -c (shadow_enable)
if (config_lookup_bool(&cfg, "shadow", &ival)) if (config_lookup_bool(&cfg, "shadow", &ival))
*shadow_enable = ival; *shadow_enable = ival;
// -C (no_dock_shadow) // -C (no_dock_shadow)
if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) { if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) {
log_warn("Option `no-dock-shadow` is deprecated, and will be removed." log_warn("Option `no-dock-shadow` is deprecated, and will be removed."
" Please use the wintype option `shadow` of `dock` instead."); " Please use the wintype option `shadow` of `dock` instead.");
opt->wintype_option[WINTYPE_DOCK].shadow = false; opt->wintype_option[WINTYPE_DOCK].shadow = false;
winopt_mask[WINTYPE_DOCK].shadow = true; winopt_mask[WINTYPE_DOCK].shadow = true;
} }
// -G (no_dnd_shadow) // -G (no_dnd_shadow)
if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) { if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) {
log_warn("Option `no-dnd-shadow` is deprecated, and will be removed." log_warn("Option `no-dnd-shadow` is deprecated, and will be removed."
" Please use the wintype option `shadow` of `dnd` instead."); " Please use the wintype option `shadow` of `dnd` instead.");
opt->wintype_option[WINTYPE_DND].shadow = false; opt->wintype_option[WINTYPE_DND].shadow = false;
winopt_mask[WINTYPE_DND].shadow = true; winopt_mask[WINTYPE_DND].shadow = true;
}; };
// -m (menu_opacity) // -m (menu_opacity)
if (config_lookup_float(&cfg, "menu-opacity", &dval)) { if (config_lookup_float(&cfg, "menu-opacity", &dval)) {
log_warn("Option `menu-opacity` is deprecated, and will be removed.Please use the " log_warn("Option `menu-opacity` is deprecated, and will be "
"wintype option `opacity` of `popup_menu` and `dropdown_menu` instead."); "removed.Please use the "
opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval; "wintype option `opacity` of `popup_menu` and `dropdown_menu` "
opt->wintype_option[WINTYPE_POPUP_MENU].opacity = dval; "instead.");
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval;
winopt_mask[WINTYPE_POPUP_MENU].opacity = true; opt->wintype_option[WINTYPE_POPUP_MENU].opacity = dval;
} winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
// -f (fading_enable) winopt_mask[WINTYPE_POPUP_MENU].opacity = true;
if (config_lookup_bool(&cfg, "fading", &ival)) }
*fading_enable = ival; // -f (fading_enable)
// --no-fading-open-close if (config_lookup_bool(&cfg, "fading", &ival))
lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose); *fading_enable = ival;
// --no-fading-destroyed-argb // --no-fading-open-close
lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb", lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose);
&opt->no_fading_destroyed_argb); // --no-fading-destroyed-argb
// --shadow-red lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb", &opt->no_fading_destroyed_argb);
config_lookup_float(&cfg, "shadow-red", &opt->shadow_red); // --shadow-red
// --shadow-green config_lookup_float(&cfg, "shadow-red", &opt->shadow_red);
config_lookup_float(&cfg, "shadow-green", &opt->shadow_green); // --shadow-green
// --shadow-blue config_lookup_float(&cfg, "shadow-green", &opt->shadow_green);
config_lookup_float(&cfg, "shadow-blue", &opt->shadow_blue); // --shadow-blue
// --shadow-exclude-reg config_lookup_float(&cfg, "shadow-blue", &opt->shadow_blue);
if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval)) // --shadow-exclude-reg
opt->shadow_exclude_reg_str = strdup(sval); if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval))
// --inactive-opacity-override opt->shadow_exclude_reg_str = strdup(sval);
lcfg_lookup_bool(&cfg, "inactive-opacity-override", // --inactive-opacity-override
&opt->inactive_opacity_override); lcfg_lookup_bool(&cfg, "inactive-opacity-override", &opt->inactive_opacity_override);
// --inactive-dim // --inactive-dim
config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim); config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim);
// --mark-wmwin-focused // --mark-wmwin-focused
lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused); lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused);
// --mark-ovredir-focused // --mark-ovredir-focused
lcfg_lookup_bool(&cfg, "mark-ovredir-focused", lcfg_lookup_bool(&cfg, "mark-ovredir-focused", &opt->mark_ovredir_focused);
&opt->mark_ovredir_focused); // --shadow-ignore-shaped
// --shadow-ignore-shaped lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", &opt->shadow_ignore_shaped);
lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", // --detect-rounded-corners
&opt->shadow_ignore_shaped); lcfg_lookup_bool(&cfg, "detect-rounded-corners", &opt->detect_rounded_corners);
// --detect-rounded-corners // --xinerama-shadow-crop
lcfg_lookup_bool(&cfg, "detect-rounded-corners", lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", &opt->xinerama_shadow_crop);
&opt->detect_rounded_corners); // --detect-client-opacity
// --xinerama-shadow-crop lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity);
lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", // --refresh-rate
&opt->xinerama_shadow_crop); config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate);
// --detect-client-opacity // --vsync
lcfg_lookup_bool(&cfg, "detect-client-opacity", if (config_lookup_string(&cfg, "vsync", &sval)) {
&opt->detect_client_opacity); opt->vsync = parse_vsync(sval);
// --refresh-rate if (opt->vsync >= NUM_VSYNC) {
config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate); log_fatal("Cannot parse vsync");
// --vsync goto err;
if (config_lookup_string(&cfg, "vsync", &sval)) { }
opt->vsync = parse_vsync(sval); }
if (opt->vsync >= NUM_VSYNC) { // --backend
log_fatal("Cannot parse vsync"); if (config_lookup_string(&cfg, "backend", &sval)) {
goto err; opt->backend = parse_backend(sval);
} if (opt->backend >= NUM_BKEND) {
} log_fatal("Cannot parse backend");
// --backend goto err;
if (config_lookup_string(&cfg, "backend", &sval)) { }
opt->backend = parse_backend(sval); }
if (opt->backend >= NUM_BKEND) { // --log-level
log_fatal("Cannot parse backend"); if (config_lookup_string(&cfg, "log-level", &sval)) {
goto err; auto level = string_to_log_level(sval);
} if (level == LOG_LEVEL_INVALID) {
} log_warn("Invalid log level, defaults to WARN");
// --log-level } else {
if (config_lookup_string(&cfg, "log-level", &sval)) { log_set_level_tls(level);
auto level = string_to_log_level(sval); }
if (level == LOG_LEVEL_INVALID) { }
log_warn("Invalid log level, defaults to WARN"); // --log-file
} else { if (config_lookup_string(&cfg, "log-file", &sval)) {
log_set_level_tls(level); if (*sval != '/') {
} log_warn("The log-file in your configuration file is not an "
} "absolute path");
// --log-file }
if (config_lookup_string(&cfg, "log-file", &sval)) { opt->logpath = strdup(sval);
if (*sval != '/') { }
log_warn("The log-file in your configuration file is not an absolute path"); // --sw-opti
} lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti);
opt->logpath = strdup(sval); // --use-ewmh-active-win
} lcfg_lookup_bool(&cfg, "use-ewmh-active-win", &opt->use_ewmh_active_win);
// --sw-opti // --unredir-if-possible
lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti); lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible);
// --use-ewmh-active-win // --unredir-if-possible-delay
lcfg_lookup_bool(&cfg, "use-ewmh-active-win", if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival))
&opt->use_ewmh_active_win); opt->unredir_if_possible_delay = ival;
// --unredir-if-possible // --inactive-dim-fixed
lcfg_lookup_bool(&cfg, "unredir-if-possible", lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed);
&opt->unredir_if_possible); // --detect-transient
// --unredir-if-possible-delay lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient);
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) // --detect-client-leader
opt->unredir_if_possible_delay = ival; lcfg_lookup_bool(&cfg, "detect-client-leader", &opt->detect_client_leader);
// --inactive-dim-fixed // --shadow-exclude
lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed); parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude");
// --detect-transient // --fade-exclude
lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient); parse_cfg_condlst(&cfg, &opt->fade_blacklist, "fade-exclude");
// --detect-client-leader // --focus-exclude
lcfg_lookup_bool(&cfg, "detect-client-leader", parse_cfg_condlst(&cfg, &opt->focus_blacklist, "focus-exclude");
&opt->detect_client_leader); // --invert-color-include
// --shadow-exclude parse_cfg_condlst(&cfg, &opt->invert_color_list, "invert-color-include");
parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude"); // --blur-background-exclude
// --fade-exclude parse_cfg_condlst(&cfg, &opt->blur_background_blacklist, "blur-background-exclude");
parse_cfg_condlst(&cfg, &opt->fade_blacklist, "fade-exclude"); // --opacity-rule
// --focus-exclude parse_cfg_condlst_opct(opt, &cfg, "opacity-rule");
parse_cfg_condlst(&cfg, &opt->focus_blacklist, "focus-exclude"); // --unredir-if-possible-exclude
// --invert-color-include parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist,
parse_cfg_condlst(&cfg, &opt->invert_color_list, "invert-color-include"); "unredir-if-possible-exclude");
// --blur-background-exclude // --blur-background
parse_cfg_condlst(&cfg, &opt->blur_background_blacklist, "blur-background-exclude"); lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background);
// --opacity-rule // --blur-background-frame
parse_cfg_condlst_opct(opt, &cfg, "opacity-rule"); lcfg_lookup_bool(&cfg, "blur-background-frame", &opt->blur_background_frame);
// --unredir-if-possible-exclude // --blur-background-fixed
parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist, "unredir-if-possible-exclude"); lcfg_lookup_bool(&cfg, "blur-background-fixed", &opt->blur_background_fixed);
// --blur-background // --blur-kern
lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background); if (config_lookup_string(&cfg, "blur-kern", &sval) &&
// --blur-background-frame !parse_blur_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) {
lcfg_lookup_bool(&cfg, "blur-background-frame", log_fatal("Cannot parse \"blur-kern\"");
&opt->blur_background_frame); goto err;
// --blur-background-fixed }
lcfg_lookup_bool(&cfg, "blur-background-fixed", // --resize-damage
&opt->blur_background_fixed); config_lookup_int(&cfg, "resize-damage", &opt->resize_damage);
// --blur-kern // --glx-no-stencil
if (config_lookup_string(&cfg, "blur-kern", &sval) && lcfg_lookup_bool(&cfg, "glx-no-stencil", &opt->glx_no_stencil);
!parse_blur_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) { // --glx-no-rebind-pixmap
log_fatal("Cannot parse \"blur-kern\""); lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &opt->glx_no_rebind_pixmap);
goto err; // --glx-swap-method
} if (config_lookup_string(&cfg, "glx-swap-method", &sval)) {
// --resize-damage opt->glx_swap_method = parse_glx_swap_method(sval);
config_lookup_int(&cfg, "resize-damage", &opt->resize_damage); if (opt->glx_swap_method == -2) {
// --glx-no-stencil log_fatal("Cannot parse \"glx-swap-method\"");
lcfg_lookup_bool(&cfg, "glx-no-stencil", &opt->glx_no_stencil); goto err;
// --glx-no-rebind-pixmap }
lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &opt->glx_no_rebind_pixmap); }
// --glx-swap-method // --glx-use-gpushader4
if (config_lookup_string(&cfg, "glx-swap-method", &sval)) { if (config_lookup_bool(&cfg, "glx-use-gpushader4", &ival) && ival) {
opt->glx_swap_method = parse_glx_swap_method(sval); log_warn("glx-use-gpushader4 is deprecated since v6, please remove it "
if (opt->glx_swap_method == -2) { "from"
log_fatal("Cannot parse \"glx-swap-method\""); "your config file");
goto err; }
} // --xrender-sync
} if (config_lookup_bool(&cfg, "xrender-sync", &ival) && ival) {
// --glx-use-gpushader4 log_warn("Please use xrender-sync-fence instead of xrender-sync.");
if (config_lookup_bool(&cfg, "glx-use-gpushader4", &ival) && ival) { opt->xrender_sync_fence = true;
log_warn("glx-use-gpushader4 is deprecated since v6, please remove it from" }
"your config file"); // --xrender-sync-fence
} lcfg_lookup_bool(&cfg, "xrender-sync-fence", &opt->xrender_sync_fence);
// --xrender-sync
if (config_lookup_bool(&cfg, "xrender-sync", &ival) && ival) {
log_warn("Please use xrender-sync-fence instead of xrender-sync.");
opt->xrender_sync_fence = true;
}
// --xrender-sync-fence
lcfg_lookup_bool(&cfg, "xrender-sync-fence", &opt->xrender_sync_fence);
if (lcfg_lookup_bool(&cfg, "clear-shadow", &bval)) if (lcfg_lookup_bool(&cfg, "clear-shadow", &bval))
log_warn("\"clear-shadow\" is removed as an option, and is always" log_warn("\"clear-shadow\" is removed as an option, and is always"
" enabled now. Consider removing it from your config file"); " enabled now. Consider removing it from your config file");
if (lcfg_lookup_bool(&cfg, "paint-on-overlay", &bval)) if (lcfg_lookup_bool(&cfg, "paint-on-overlay", &bval))
log_warn("\"paint-on-overlay\" has been removed as an option, and " log_warn("\"paint-on-overlay\" has been removed as an option, and "
"is enabled whenever possible"); "is enabled whenever possible");
if (config_lookup_float(&cfg, "alpha-step", &dval)) if (config_lookup_float(&cfg, "alpha-step", &dval))
log_warn("\"alpha-step\" has been removed, compton now tries to make use" log_warn("\"alpha-step\" has been removed, compton now tries to make use"
" of all alpha values"); " of all alpha values");
const char *deprecation_message = "has been removed. If you encounter problems " const char *deprecation_message =
"without this feature, please feel free to open a bug report"; "has been removed. If you encounter problems "
if (lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &bval) && bval) "without this feature, please feel free to open a bug report";
log_warn("\"glx-use-copysubbuffermesa\" %s", deprecation_message); if (lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &bval) && bval)
if (lcfg_lookup_bool(&cfg, "glx-copy-from-front", &bval) && bval) log_warn("\"glx-use-copysubbuffermesa\" %s", deprecation_message);
log_warn("\"glx-copy-from-front\" %s", deprecation_message); if (lcfg_lookup_bool(&cfg, "glx-copy-from-front", &bval) && bval)
log_warn("\"glx-copy-from-front\" %s", deprecation_message);
// Wintype settings // Wintype settings
// XXX ! Refactor all the wintype_* arrays into a struct // XXX ! Refactor all the wintype_* arrays into a struct
for (wintype_t i = 0; i < NUM_WINTYPES; ++i) { for (wintype_t i = 0; i < NUM_WINTYPES; ++i) {
char *str = mstrjoin("wintypes.", WINTYPES[i]); char *str = mstrjoin("wintypes.", WINTYPES[i]);
config_setting_t *setting = config_lookup(&cfg, str); config_setting_t *setting = config_lookup(&cfg, str);
free(str); free(str);
win_option_t *o = &opt->wintype_option[i]; win_option_t *o = &opt->wintype_option[i];
win_option_mask_t *mask = &winopt_mask[i]; win_option_mask_t *mask = &winopt_mask[i];
if (setting) { if (setting) {
if (config_setting_lookup_bool(setting, "shadow", &ival)) { if (config_setting_lookup_bool(setting, "shadow", &ival)) {
o->shadow = ival; o->shadow = ival;
mask->shadow = true; mask->shadow = true;
} }
if (config_setting_lookup_bool(setting, "fade", &ival)) { if (config_setting_lookup_bool(setting, "fade", &ival)) {
o->fade = ival; o->fade = ival;
mask->fade = true; mask->fade = true;
} }
if (config_setting_lookup_bool(setting, "focus", &ival)) { if (config_setting_lookup_bool(setting, "focus", &ival)) {
o->focus = ival; o->focus = ival;
mask->focus = true; mask->focus = true;
} }
if (config_setting_lookup_bool(setting, "full-shadow", &ival)) { if (config_setting_lookup_bool(setting, "full-shadow", &ival)) {
o->full_shadow = ival; o->full_shadow = ival;
mask->full_shadow = true; mask->full_shadow = true;
} }
if (config_setting_lookup_bool(setting, "redir-ignore", &ival)) { if (config_setting_lookup_bool(setting, "redir-ignore", &ival)) {
o->redir_ignore = ival; o->redir_ignore = ival;
mask->redir_ignore = true; mask->redir_ignore = true;
} }
double fval; double fval;
if (config_setting_lookup_float(setting, "opacity", &fval)) { if (config_setting_lookup_float(setting, "opacity", &fval)) {
o->opacity = normalize_d(fval); o->opacity = normalize_d(fval);
mask->opacity = true; mask->opacity = true;
} }
} }
} }
config_destroy(&cfg); config_destroy(&cfg);
return path; return path;
err: err:
config_destroy(&cfg); config_destroy(&cfg);
free(path); free(path);
return ERR_PTR(-1); return ERR_PTR(-1);
} }
+900 -969
View File
File diff suppressed because it is too large Load Diff
+894 -906
View File
File diff suppressed because it is too large Load Diff
+76 -109
View File
@@ -12,193 +12,160 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#include "compiler.h"
#include "log.h"
#include "region.h" #include "region.h"
#include "render.h" #include "render.h"
#include "compiler.h"
#include "win.h" #include "win.h"
#include "log.h"
#include <xcb/xcb.h> #include <GL/gl.h>
#include <xcb/render.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <locale.h> #include <locale.h>
#include <GL/gl.h> #include <stdlib.h>
#include <string.h>
#include <xcb/render.h>
#include <xcb/xcb.h>
bool bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, GLfloat factor, const region_t *reg_tgt);
GLfloat factor, const region_t *reg_tgt);
bool bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy,
glx_render(session_t *ps, const glx_texture_t *ptex, int width, int height, int z, double opacity, bool argb, bool neg,
int x, int y, int dx, int dy, int width, int height, int z, const region_t *reg_tgt, const glx_prog_main_t *pprogram);
double opacity, bool argb, bool neg,
const region_t *reg_tgt,
const glx_prog_main_t *pprogram);
bool bool glx_init(session_t *ps, bool need_render);
glx_init(session_t *ps, bool need_render);
void void glx_destroy(session_t *ps);
glx_destroy(session_t *ps);
void void glx_on_root_change(session_t *ps);
glx_on_root_change(session_t *ps);
bool bool glx_init_blur(session_t *ps);
glx_init_blur(session_t *ps);
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
bool bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str,
glx_load_prog_main(session_t *ps, glx_prog_main_t *pprogram);
const char *vshader_str, const char *fshader_str,
glx_prog_main_t *pprogram);
#endif #endif
bool bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width,
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned height, bool repeat, const struct glx_fbconfig_info *);
unsigned width, unsigned height, bool repeat, const struct glx_fbconfig_info *);
void void glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
void glx_paint_pre(session_t *ps, region_t *preg) void glx_paint_pre(session_t *ps, region_t *preg) attr_nonnull(1, 2);
attr_nonnull(1, 2);
/** /**
* Check if a texture is binded, or is binded to the given pixmap. * Check if a texture is binded, or is binded to the given pixmap.
*/ */
static inline bool static inline bool glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) {
glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) { return ptex && ptex->glpixmap && ptex->texture && (!pixmap || pixmap == ptex->pixmap);
return ptex && ptex->glpixmap && ptex->texture
&& (!pixmap || pixmap == ptex->pixmap);
} }
void void glx_set_clip(session_t *ps, const region_t *reg);
glx_set_clip(session_t *ps, const region_t *reg);
bool bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, GLfloat factor_center, const region_t *reg_tgt, glx_blur_cache_t *pbc);
GLfloat factor_center,
const region_t *reg_tgt,
glx_blur_cache_t *pbc);
GLuint GLuint glx_create_shader(GLenum shader_type, const char *shader_str);
glx_create_shader(GLenum shader_type, const char *shader_str);
GLuint GLuint glx_create_program(const GLuint *const shaders, int nshaders);
glx_create_program(const GLuint * const shaders, int nshaders);
GLuint GLuint glx_create_program_from_str(const char *vert_shader_str, const char *frag_shader_str);
glx_create_program_from_str(const char *vert_shader_str,
const char *frag_shader_str);
unsigned char * unsigned char *glx_take_screenshot(session_t *ps, int *out_length);
glx_take_screenshot(session_t *ps, int *out_length);
/** /**
* Check if there's a GLX context. * Check if there's a GLX context.
*/ */
static inline bool static inline bool glx_has_context(session_t *ps) {
glx_has_context(session_t *ps) { return ps->psglx && ps->psglx->context;
return ps->psglx && ps->psglx->context;
} }
/** /**
* Ensure we have a GLX context. * Ensure we have a GLX context.
*/ */
static inline bool static inline bool ensure_glx_context(session_t *ps) {
ensure_glx_context(session_t *ps) { // Create GLX context
// Create GLX context if (!glx_has_context(ps))
if (!glx_has_context(ps)) glx_init(ps, false);
glx_init(ps, false);
return ps->psglx->context; return ps->psglx->context;
} }
/** /**
* Free a GLX texture. * Free a GLX texture.
*/ */
static inline void static inline void free_texture_r(session_t *ps, GLuint *ptexture) {
free_texture_r(session_t *ps, GLuint *ptexture) { if (*ptexture) {
if (*ptexture) { assert(glx_has_context(ps));
assert(glx_has_context(ps)); glDeleteTextures(1, ptexture);
glDeleteTextures(1, ptexture); *ptexture = 0;
*ptexture = 0; }
}
} }
/** /**
* Free a GLX Framebuffer object. * Free a GLX Framebuffer object.
*/ */
static inline void static inline void free_glx_fbo(session_t *ps, GLuint *pfbo) {
free_glx_fbo(session_t *ps, GLuint *pfbo) { if (*pfbo) {
if (*pfbo) { glDeleteFramebuffers(1, pfbo);
glDeleteFramebuffers(1, pfbo); *pfbo = 0;
*pfbo = 0; }
} assert(!*pfbo);
assert(!*pfbo);
} }
/** /**
* Free data in glx_blur_cache_t on resize. * Free data in glx_blur_cache_t on resize.
*/ */
static inline void static inline void free_glx_bc_resize(session_t *ps, glx_blur_cache_t *pbc) {
free_glx_bc_resize(session_t *ps, glx_blur_cache_t *pbc) { free_texture_r(ps, &pbc->textures[0]);
free_texture_r(ps, &pbc->textures[0]); free_texture_r(ps, &pbc->textures[1]);
free_texture_r(ps, &pbc->textures[1]); pbc->width = 0;
pbc->width = 0; pbc->height = 0;
pbc->height = 0;
} }
/** /**
* Free a glx_blur_cache_t * Free a glx_blur_cache_t
*/ */
static inline void static inline void free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) {
free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) { free_glx_fbo(ps, &pbc->fbo);
free_glx_fbo(ps, &pbc->fbo); free_glx_bc_resize(ps, pbc);
free_glx_bc_resize(ps, pbc);
} }
/** /**
* Free a glx_texture_t. * Free a glx_texture_t.
*/ */
static inline void static inline void free_texture(session_t *ps, glx_texture_t **pptex) {
free_texture(session_t *ps, glx_texture_t **pptex) { glx_texture_t *ptex = *pptex;
glx_texture_t *ptex = *pptex;
// Quit if there's nothing // Quit if there's nothing
if (!ptex) if (!ptex)
return; return;
glx_release_pixmap(ps, ptex); glx_release_pixmap(ps, ptex);
free_texture_r(ps, &ptex->texture); free_texture_r(ps, &ptex->texture);
// Free structure itself // Free structure itself
free(ptex); free(ptex);
*pptex = NULL; *pptex = NULL;
assert(!*pptex); assert(!*pptex);
} }
/** /**
* Free GLX part of paint_t. * Free GLX part of paint_t.
*/ */
static inline void static inline void free_paint_glx(session_t *ps, paint_t *ppaint) {
free_paint_glx(session_t *ps, paint_t *ppaint) { free_texture(ps, &ppaint->ptex);
free_texture(ps, &ppaint->ptex);
} }
/** /**
* Free GLX part of win. * Free GLX part of win.
*/ */
static inline void static inline void free_win_res_glx(session_t *ps, win *w) {
free_win_res_glx(session_t *ps, win *w) { free_paint_glx(ps, &w->paint);
free_paint_glx(ps, &w->paint); free_paint_glx(ps, &w->shadow_paint);
free_paint_glx(ps, &w->shadow_paint);
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
free_glx_bc(ps, &w->glx_blur_cache); free_glx_bc(ps, &w->glx_blur_cache);
free(w->paint.fbcfg); free(w->paint.fbcfg);
#endif #endif
} }
+24 -24
View File
@@ -55,31 +55,31 @@ void mstrextend(char **psrc1, const char *src2) {
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*) /// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
double strtod_simple(const char *src, const char **end) { double strtod_simple(const char *src, const char **end) {
double neg = 1; double neg = 1;
if (*src == '-') { if (*src == '-') {
neg = -1; neg = -1;
src++; src++;
} else if (*src == '+') { } else if (*src == '+') {
src++; src++;
} }
double ret = 0; double ret = 0;
while (*src >= '0' && *src <= '9') { while (*src >= '0' && *src <= '9') {
ret = ret * 10 + (*src - '0'); ret = ret * 10 + (*src - '0');
src++; src++;
} }
if (*src == '.') { if (*src == '.') {
double frac = 0, mult = 0.1; double frac = 0, mult = 0.1;
src++; src++;
while (*src >= '0' && *src <= '9') { while (*src >= '0' && *src <= '9') {
frac += mult * (*src - '0'); frac += mult * (*src - '0');
mult *= 0.1; mult *= 0.1;
src++; src++;
} }
ret += frac; ret += frac;
} }
*end = src; *end = src;
return ret * neg; return ret * neg;
} }
+29 -34
View File
@@ -7,51 +7,46 @@
#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);
char * char *mstrjoin3(const char *src1, const char *src2, const char *src3);
mstrjoin3(const char *src1, const char *src2, const char *src3);
void mstrextend(char **psrc1, const char *src2); void mstrextend(char **psrc1, const char *src2);
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*) /// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
double strtod_simple(const char *, const char **); double strtod_simple(const char *, const char **);
static inline int uitostr(unsigned int n, char *buf) { static inline int uitostr(unsigned int n, char *buf) {
int ret = 0; int ret = 0;
unsigned int tmp = n; unsigned int tmp = n;
while (tmp > 0) { while (tmp > 0) {
tmp /= 10; tmp /= 10;
ret++; ret++;
} }
if (ret == 0) if (ret == 0)
ret = 1; ret = 1;
int pos = ret; int pos = ret;
while (pos--) { while (pos--) {
buf[pos] = n%10 + '0'; buf[pos] = n % 10 + '0';
n /= 10; n /= 10;
} }
return ret; return ret;
} }
static inline const char * static inline const char *skip_space_const(const char *src) {
skip_space_const(const char *src) { if (!src)
if (!src) return NULL;
return NULL; while (*src && isspace(*src))
while (*src && isspace(*src)) src++;
src++; return src;
return src;
} }
static inline char * static inline char *skip_space_mut(char *src) {
skip_space_mut(char *src) { if (!src)
if (!src) return NULL;
return NULL; while (*src && isspace(*src))
while (*src && isspace(*src)) src++;
src++; return src;
return src;
} }
#define skip_space(x) _Generic((x), \ #define skip_space(x) \
char *: skip_space_mut, \ _Generic((x), char * : skip_space_mut, const char * : skip_space_const)(x)
const char *: skip_space_const \
)(x)
+13 -12
View File
@@ -9,27 +9,28 @@
/// Enumeration type to represent switches. /// Enumeration type to represent switches.
typedef enum { typedef enum {
OFF = 0, // false OFF = 0, // false
ON, // true ON, // true
UNSET UNSET
} switch_t; } switch_t;
/// Structure representing a X geometry. /// Structure representing a X geometry.
typedef struct { typedef struct {
int wid; int wid;
int hei; int hei;
int x; int x;
int y; int y;
} geometry_t; } 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;
unsigned int left; unsigned int left;
unsigned int bottom; unsigned int bottom;
unsigned int right; unsigned int right;
} margin_t; } margin_t;
typedef uint32_t opacity_t; typedef uint32_t opacity_t;
#define MARGIN_INIT { 0, 0, 0, 0 } #define MARGIN_INIT \
{ 0, 0, 0, 0 }
+108 -122
View File
@@ -12,12 +12,12 @@
#endif #endif
#ifdef CONFIG_VSYNC_DRM #ifdef CONFIG_VSYNC_DRM
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <drm.h> #include <drm.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif #endif
#include "config.h" #include "config.h"
@@ -27,26 +27,24 @@
/** /**
* Wait for next VSync, DRM method. * Wait for next VSync, DRM method.
* *
* Stolen from: https://github.com/MythTV/mythtv/blob/master/mythtv/libs/libmythtv/vsync.cpp * Stolen from:
* https://github.com/MythTV/mythtv/blob/master/mythtv/libs/libmythtv/vsync.cpp
*/ */
static int static int vsync_drm_wait(session_t *ps) {
vsync_drm_wait(session_t *ps) { int ret = -1;
int ret = -1; drm_wait_vblank_t vbl;
drm_wait_vblank_t vbl;
vbl.request.type = _DRM_VBLANK_RELATIVE, vbl.request.type = _DRM_VBLANK_RELATIVE, vbl.request.sequence = 1;
vbl.request.sequence = 1;
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 &= ~_DRM_VBLANK_RELATIVE;
} while (ret && errno == EINTR); } while (ret && errno == EINTR);
if (ret) if (ret)
log_error("VBlank ioctl did not work, unimplemented in this drmver?"); log_error("VBlank ioctl did not work, unimplemented in this drmver?");
return ret;
return ret;
} }
#endif #endif
@@ -55,126 +53,120 @@ vsync_drm_wait(session_t *ps) {
* *
* @return true for success, false otherwise * @return true for success, false otherwise
*/ */
static bool static bool vsync_drm_init(session_t *ps) {
vsync_drm_init(session_t *ps) {
#ifdef CONFIG_VSYNC_DRM #ifdef CONFIG_VSYNC_DRM
// Should we always open card0? // Should we always open card0?
if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) { if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) {
log_error("Failed to open device."); log_error("Failed to open device.");
return false; return false;
} }
if (vsync_drm_wait(ps)) if (vsync_drm_wait(ps))
return false; return false;
return true; return true;
#else #else
log_error("compton is not compiled with DRM VSync support."); log_error("compton is not compiled with DRM VSync support.");
return false; return false;
#endif #endif
} }
/** /**
* Initialize OpenGL VSync. * Initialize OpenGL VSync.
* *
* Stolen from: http://git.tuxfamily.org/?p=ccm/cairocompmgr.git;a=commitdiff;h=efa4ceb97da501e8630ca7f12c99b1dce853c73e * Stolen from:
* http://git.tuxfamily.org/?p=ccm/cairocompmgr.git;a=commitdiff;h=efa4ceb97da501e8630ca7f12c99b1dce853c73e
* Possible original source: http://www.inb.uni-luebeck.de/~boehme/xvideo_sync.html * Possible original source: http://www.inb.uni-luebeck.de/~boehme/xvideo_sync.html
* *
* @return true for success, false otherwise * @return true for success, false otherwise
*/ */
static bool static bool vsync_opengl_init(session_t *ps) {
vsync_opengl_init(session_t *ps) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (!ensure_glx_context(ps)) if (!ensure_glx_context(ps))
return false; return false;
return glxext.has_GLX_SGI_video_sync; return glxext.has_GLX_SGI_video_sync;
#else #else
log_error("compton is not compiled with OpenGL VSync support."); log_error("compton is not compiled with OpenGL VSync support.");
return false; return false;
#endif #endif
} }
static bool static bool vsync_opengl_oml_init(session_t *ps) {
vsync_opengl_oml_init(session_t *ps) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (!ensure_glx_context(ps)) if (!ensure_glx_context(ps))
return false; return false;
return glxext.has_GLX_OML_sync_control; return glxext.has_GLX_OML_sync_control;
#else #else
log_error("compton is not compiled with OpenGL VSync support."); log_error("compton is not compiled with OpenGL VSync support.");
return false; return false;
#endif #endif
} }
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
static inline bool static inline bool vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) {
vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) { if (glxext.has_GLX_MESA_swap_control)
if (glxext.has_GLX_MESA_swap_control) return glXSwapIntervalMESA(interval) == 0;
return glXSwapIntervalMESA(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) { GLXDrawable d = glXGetCurrentDrawable();
GLXDrawable d = glXGetCurrentDrawable(); if (d == None) {
if (d == None) { // We don't have a context??
// We don't have a context?? return false;
return false; }
} glXSwapIntervalEXT(ps->dpy, glXGetCurrentDrawable(), interval);
glXSwapIntervalEXT(ps->dpy, glXGetCurrentDrawable(), interval); return true;
return true; }
} return false;
return false;
} }
#endif #endif
static bool static bool vsync_opengl_swc_init(session_t *ps) {
vsync_opengl_swc_init(session_t *ps) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (!bkend_use_glx(ps)) { if (!bkend_use_glx(ps)) {
log_warn("OpenGL swap control requires the GLX backend."); log_warn("OpenGL swap control requires the GLX backend.");
return false; return false;
} }
if (!vsync_opengl_swc_swap_interval(ps, 1)) { if (!vsync_opengl_swc_swap_interval(ps, 1)) {
log_error("Failed to load a swap control extension."); log_error("Failed to load a swap control extension.");
return false; return false;
} }
return true; return true;
#else #else
log_error("compton is not compiled with OpenGL VSync support."); log_error("compton is not compiled with OpenGL VSync support.");
return false; return false;
#endif #endif
} }
static bool static bool vsync_opengl_mswc_init(session_t *ps) {
vsync_opengl_mswc_init(session_t *ps) { log_warn("opengl-mswc is deprecated, please use opengl-swc instead.");
log_warn("opengl-mswc is deprecated, please use opengl-swc instead."); return vsync_opengl_swc_init(ps);
return vsync_opengl_swc_init(ps);
} }
bool (*const VSYNC_FUNCS_INIT[NUM_VSYNC])(session_t *ps) = { bool (*const VSYNC_FUNCS_INIT[NUM_VSYNC])(session_t *ps) = {
[VSYNC_DRM ] = vsync_drm_init, [VSYNC_DRM] = vsync_drm_init,
[VSYNC_OPENGL ] = vsync_opengl_init, [VSYNC_OPENGL] = vsync_opengl_init,
[VSYNC_OPENGL_OML ] = vsync_opengl_oml_init, [VSYNC_OPENGL_OML] = vsync_opengl_oml_init,
[VSYNC_OPENGL_SWC ] = vsync_opengl_swc_init, [VSYNC_OPENGL_SWC] = vsync_opengl_swc_init,
[VSYNC_OPENGL_MSWC ] = vsync_opengl_mswc_init, [VSYNC_OPENGL_MSWC] = vsync_opengl_mswc_init,
}; };
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
/** /**
* Wait for next VSync, OpenGL method. * Wait for next VSync, OpenGL method.
*/ */
static int static int vsync_opengl_wait(session_t *ps) {
vsync_opengl_wait(session_t *ps) { unsigned vblank_count = 0;
unsigned vblank_count = 0;
glXGetVideoSyncSGI(&vblank_count); glXGetVideoSyncSGI(&vblank_count);
glXWaitVideoSyncSGI(2, (vblank_count + 1) % 2, &vblank_count); glXWaitVideoSyncSGI(2, (vblank_count + 1) % 2, &vblank_count);
// I see some code calling glXSwapIntervalSGI(1) afterwards, is it required? // I see some code calling glXSwapIntervalSGI(1) afterwards, is it required?
return 0; return 0;
} }
/** /**
@@ -182,15 +174,13 @@ vsync_opengl_wait(session_t *ps) {
* *
* https://mail.gnome.org/archives/clutter-list/2012-November/msg00031.html * https://mail.gnome.org/archives/clutter-list/2012-November/msg00031.html
*/ */
static int static int vsync_opengl_oml_wait(session_t *ps) {
vsync_opengl_oml_wait(session_t *ps) { int64_t ust = 0, msc = 0, sbc = 0;
int64_t ust = 0, msc = 0, sbc = 0;
glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc); glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc);
glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2, glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2, &ust, &msc, &sbc);
&ust, &msc, &sbc);
return 0; return 0;
} }
#endif #endif
@@ -198,27 +188,25 @@ vsync_opengl_oml_wait(session_t *ps) {
/// Function pointers to wait for VSync. /// Function pointers to wait for VSync.
int (*const VSYNC_FUNCS_WAIT[NUM_VSYNC])(session_t *ps) = { int (*const VSYNC_FUNCS_WAIT[NUM_VSYNC])(session_t *ps) = {
#ifdef CONFIG_VSYNC_DRM #ifdef CONFIG_VSYNC_DRM
[VSYNC_DRM ] = vsync_drm_wait, [VSYNC_DRM] = vsync_drm_wait,
#endif #endif
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
[VSYNC_OPENGL ] = vsync_opengl_wait, [VSYNC_OPENGL] = vsync_opengl_wait,
[VSYNC_OPENGL_OML ] = vsync_opengl_oml_wait, [VSYNC_OPENGL_OML] = vsync_opengl_oml_wait,
#endif #endif
}; };
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
static void static void vsync_opengl_swc_deinit(session_t *ps) {
vsync_opengl_swc_deinit(session_t *ps) { vsync_opengl_swc_swap_interval(ps, 0);
vsync_opengl_swc_swap_interval(ps, 0);
} }
#endif #endif
/// Function pointers to deinitialize VSync. /// Function pointers to deinitialize VSync.
void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = { void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
[VSYNC_OPENGL_SWC ] = vsync_opengl_swc_deinit, [VSYNC_OPENGL_SWC] = vsync_opengl_swc_deinit,
[VSYNC_OPENGL_MSWC ] = vsync_opengl_swc_deinit, [VSYNC_OPENGL_MSWC] = vsync_opengl_swc_deinit,
#endif #endif
}; };
@@ -226,36 +214,34 @@ void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = {
* Initialize current VSync method. * Initialize current VSync method.
*/ */
bool vsync_init(session_t *ps) { bool vsync_init(session_t *ps) {
// Mesa turns on swap control by default, undo that // Mesa turns on swap control by default, undo that
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (bkend_use_glx(ps)) if (bkend_use_glx(ps))
vsync_opengl_swc_swap_interval(ps, 0); vsync_opengl_swc_swap_interval(ps, 0);
#endif #endif
if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) {
&& !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) { ps->o.vsync = VSYNC_NONE;
ps->o.vsync = VSYNC_NONE; return false;
return false; } else
} return true;
else
return true;
} }
/** /**
* Wait for next VSync. * Wait for next VSync.
*/ */
void vsync_wait(session_t *ps) { void vsync_wait(session_t *ps) {
if (!ps->o.vsync) if (!ps->o.vsync)
return; return;
if (VSYNC_FUNCS_WAIT[ps->o.vsync]) if (VSYNC_FUNCS_WAIT[ps->o.vsync])
VSYNC_FUNCS_WAIT[ps->o.vsync](ps); VSYNC_FUNCS_WAIT[ps->o.vsync](ps);
} }
/** /**
* Deinitialize current VSync method. * Deinitialize current VSync method.
*/ */
void vsync_deinit(session_t *ps) { void vsync_deinit(session_t *ps) {
if (ps->o.vsync && VSYNC_FUNCS_DEINIT[ps->o.vsync]) if (ps->o.vsync && VSYNC_FUNCS_DEINIT[ps->o.vsync])
VSYNC_FUNCS_DEINIT[ps->o.vsync](ps); VSYNC_FUNCS_DEINIT[ps->o.vsync](ps);
} }
+1173 -1177
View File
File diff suppressed because it is too large Load Diff
+211 -218
View File
@@ -3,22 +3,22 @@
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com> // Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
#include <xcb/xcb.h>
#include <xcb/render.h>
#include <xcb/damage.h> #include <xcb/damage.h>
#include <xcb/render.h>
#include <xcb/xcb.h>
// FIXME shouldn't need this // FIXME shouldn't need this
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
#include <GL/gl.h> #include <GL/gl.h>
#endif #endif
#include "x.h" #include "c2.h"
#include "compiler.h" #include "compiler.h"
#include "region.h" #include "region.h"
#include "types.h"
#include "c2.h"
#include "render.h" #include "render.h"
#include "types.h"
#include "utils.h" #include "utils.h"
#include "x.h"
typedef struct session session_t; typedef struct session session_t;
typedef struct _glx_texture glx_texture_t; typedef struct _glx_texture glx_texture_t;
@@ -27,41 +27,41 @@ typedef struct _glx_texture glx_texture_t;
// FIXME this type should be in opengl.h // FIXME this type should be in opengl.h
// it is very unideal for it to be here // it is very unideal for it to be here
typedef struct { typedef struct {
/// Framebuffer used for blurring. /// Framebuffer used for blurring.
GLuint fbo; GLuint fbo;
/// Textures used for blurring. /// Textures used for blurring.
GLuint textures[2]; GLuint textures[2];
/// Width of the textures. /// Width of the textures.
int width; int width;
/// Height of the textures. /// Height of the textures.
int height; int height;
} glx_blur_cache_t; } glx_blur_cache_t;
#endif #endif
typedef enum { typedef enum {
WINTYPE_UNKNOWN, WINTYPE_UNKNOWN,
WINTYPE_DESKTOP, WINTYPE_DESKTOP,
WINTYPE_DOCK, WINTYPE_DOCK,
WINTYPE_TOOLBAR, WINTYPE_TOOLBAR,
WINTYPE_MENU, WINTYPE_MENU,
WINTYPE_UTILITY, WINTYPE_UTILITY,
WINTYPE_SPLASH, WINTYPE_SPLASH,
WINTYPE_DIALOG, WINTYPE_DIALOG,
WINTYPE_NORMAL, WINTYPE_NORMAL,
WINTYPE_DROPDOWN_MENU, WINTYPE_DROPDOWN_MENU,
WINTYPE_POPUP_MENU, WINTYPE_POPUP_MENU,
WINTYPE_TOOLTIP, WINTYPE_TOOLTIP,
WINTYPE_NOTIFY, WINTYPE_NOTIFY,
WINTYPE_COMBO, WINTYPE_COMBO,
WINTYPE_DND, WINTYPE_DND,
NUM_WINTYPES NUM_WINTYPES
} wintype_t; } wintype_t;
/// Enumeration type of window painting mode. /// Enumeration type of window painting mode.
typedef enum { typedef enum {
WMODE_TRANS, // The window body is (potentially) transparent WMODE_TRANS, // The window body is (potentially) transparent
WMODE_FRAME_TRANS, // The window body is opaque, but the frame is not WMODE_FRAME_TRANS, // The window body is opaque, but the frame is not
WMODE_SOLID, // The window is opaque including the frame WMODE_SOLID, // The window is opaque including the frame
} winmode_t; } winmode_t;
/// Transition table: /// Transition table:
@@ -90,18 +90,18 @@ typedef enum {
/// | |unmapped |destroyed | |change | | | | /// | |unmapped |destroyed | |change | | | |
/// +-------------+---------+----------+-------+-------+--------+--------+---------+ /// +-------------+---------+----------+-------+-------+--------+--------+---------+
typedef enum { typedef enum {
// The window is being faded out because it's unmapped. // The window is being faded out because it's unmapped.
WSTATE_UNMAPPING, WSTATE_UNMAPPING,
// The window is being faded out because it's destroyed, // The window is being faded out because it's destroyed,
WSTATE_DESTROYING, WSTATE_DESTROYING,
// The window is being faded in // The window is being faded in
WSTATE_MAPPING, WSTATE_MAPPING,
// Window opacity is not at the target level // Window opacity is not at the target level
WSTATE_FADING, WSTATE_FADING,
// The window is mapped, no fading is in progress. // The window is mapped, no fading is in progress.
WSTATE_MAPPED, WSTATE_MAPPED,
// The window is unmapped, no fading is in progress. // The window is unmapped, no fading is in progress.
WSTATE_UNMAPPED, WSTATE_UNMAPPED,
} winstate_t; } winstate_t;
/** /**
@@ -118,167 +118,167 @@ typedef enum {
/// Structure representing a top-level window compton manages. /// Structure representing a top-level window compton manages.
typedef struct win win; typedef struct win win;
struct win { struct win {
/// backend data attached to this window. Only available when /// backend data attached to this window. Only available when
/// `state` is not UNMAPPED /// `state` is not UNMAPPED
void *win_image; void *win_image;
void *shadow_image; void *shadow_image;
/// Pointer to the next lower window in window stack. /// Pointer to the next lower window in window stack.
win *next; win *next;
/// Pointer to the next higher window to paint. /// Pointer to the next higher window to paint.
win *prev_trans; win *prev_trans;
// TODO rethink reg_ignore // TODO rethink reg_ignore
// Core members // Core members
/// ID of the top-level frame window. /// ID of the top-level frame window.
xcb_window_t id; xcb_window_t id;
/// The "mapped state" of this window, doesn't necessary /// The "mapped state" of this window, doesn't necessary
/// match X mapped state, because of fading. /// match X mapped state, because of fading.
winstate_t state; winstate_t state;
/// Window attributes. /// Window attributes.
xcb_get_window_attributes_reply_t a; xcb_get_window_attributes_reply_t a;
xcb_get_geometry_reply_t g; xcb_get_geometry_reply_t g;
/// Xinerama screen this window is on. /// Xinerama screen this window is on.
int xinerama_scr; int xinerama_scr;
/// Window visual pict format; /// Window visual pict format;
const xcb_render_pictforminfo_t *pictfmt; const xcb_render_pictforminfo_t *pictfmt;
/// Window painting mode. /// Window painting mode.
winmode_t mode; winmode_t mode;
/// Whether the window has been damaged at least once. /// Whether the window has been damaged at least once.
bool ever_damaged; bool ever_damaged;
/// Whether the window was damaged after last paint. /// Whether the window was damaged after last paint.
bool pixmap_damaged; bool pixmap_damaged;
/// Damage of the window. /// Damage of the window.
xcb_damage_damage_t damage; xcb_damage_damage_t damage;
/// Paint info of the window. /// Paint info of the window.
paint_t paint; paint_t paint;
/// Bounding shape of the window. In local coordinates. /// Bounding shape of the window. In local coordinates.
/// See above about coordinate systems. /// See above about coordinate systems.
region_t bounding_shape; region_t bounding_shape;
/// Window flags. Definitions above. /// Window flags. Definitions above.
int_fast16_t flags; int_fast16_t flags;
/// Whether there's a pending <code>ConfigureNotify</code> happening /// Whether there's a pending <code>ConfigureNotify</code> happening
/// when the window is unmapped. /// when the window is unmapped.
bool need_configure; bool need_configure;
/// Queued <code>ConfigureNotify</code> when the window is unmapped. /// Queued <code>ConfigureNotify</code> when the window is unmapped.
xcb_configure_notify_event_t queue_configure; xcb_configure_notify_event_t queue_configure;
/// The region of screen that will be obscured when windows above is painted, /// The region of screen that will be obscured when windows above is painted,
/// in global coordinates. /// in global coordinates.
/// We use this to reduce the pixels that needed to be paint when painting /// We use this to reduce the pixels that needed to be paint when painting
/// this window and anything underneath. Depends on window frame /// this window and anything underneath. Depends on window frame
/// opacity state, window geometry, window mapped/unmapped state, /// opacity state, window geometry, window mapped/unmapped state,
/// window mode of the windows above. DOES NOT INCLUDE the body of THIS WINDOW. /// window mode of the windows above. DOES NOT INCLUDE the body of THIS WINDOW.
/// NULL means reg_ignore has not been calculated for this window. /// NULL means reg_ignore has not been calculated for this window.
rc_region_t *reg_ignore; rc_region_t *reg_ignore;
/// Whether the reg_ignore of all windows beneath this window are valid /// Whether the reg_ignore of all windows beneath this window are valid
bool reg_ignore_valid; bool reg_ignore_valid;
/// Cached width/height of the window including border. /// Cached width/height of the window including border.
int widthb, heightb; int widthb, heightb;
/// Whether the window is bounding-shaped. /// Whether the window is bounding-shaped.
bool bounding_shaped; bool bounding_shaped;
/// Whether the window just have rounded corners. /// Whether the window just have rounded corners.
bool rounded_corners; bool rounded_corners;
/// Whether this window is to be painted. /// Whether this window is to be painted.
bool to_paint; bool to_paint;
/// Whether the window is painting excluded. /// Whether the window is painting excluded.
bool paint_excluded; bool paint_excluded;
/// Whether the window is unredirect-if-possible excluded. /// Whether the window is unredirect-if-possible excluded.
bool unredir_if_possible_excluded; bool unredir_if_possible_excluded;
/// Whether this window is in open/close state. /// Whether this window is in open/close state.
bool in_openclose; bool in_openclose;
// Client window related members // Client window related members
/// ID of the top-level client window of the window. /// ID of the top-level client window of the window.
xcb_window_t client_win; xcb_window_t client_win;
/// Type of the window. /// Type of the window.
wintype_t window_type; wintype_t window_type;
/// Whether it looks like a WM window. We consider a window WM window if /// Whether it looks like a WM window. We consider a window WM window if
/// it does not have a decedent with WM_STATE and it is not override- /// it does not have a decedent with WM_STATE and it is not override-
/// redirected itself. /// redirected itself.
bool wmwin; bool wmwin;
/// Leader window ID of the window. /// Leader window ID of the window.
xcb_window_t leader; xcb_window_t leader;
/// Cached topmost window ID of the window. /// Cached topmost window ID of the window.
xcb_window_t cache_leader; xcb_window_t cache_leader;
// Focus-related members // Focus-related members
/// Whether the window is to be considered focused. /// Whether the window is to be considered focused.
bool focused; bool focused;
/// Override value of window focus state. Set by D-Bus method calls. /// Override value of window focus state. Set by D-Bus method calls.
switch_t focused_force; switch_t focused_force;
// Blacklist related members // Blacklist related members
/// Name of the window. /// Name of the window.
char *name; char *name;
/// Window instance class of the window. /// Window instance class of the window.
char *class_instance; char *class_instance;
/// Window general class of the window. /// Window general class of the window.
char *class_general; char *class_general;
/// <code>WM_WINDOW_ROLE</code> value of the window. /// <code>WM_WINDOW_ROLE</code> value of the window.
char *role; char *role;
// Opacity-related members // Opacity-related members
/// Current window opacity. /// Current window opacity.
double opacity; double opacity;
/// Target window opacity. /// Target window opacity.
double opacity_tgt; double opacity_tgt;
/// true if window (or client window, for broken window managers /// true if window (or client window, for broken window managers
/// not transferring client window's _NET_WM_OPACITY value) has opacity prop /// not transferring client window's _NET_WM_OPACITY value) has opacity prop
bool has_opacity_prop; bool has_opacity_prop;
/// Cached value of opacity window attribute. /// Cached value of opacity window attribute.
opacity_t opacity_prop; opacity_t opacity_prop;
/// true if opacity is set by some rules /// true if opacity is set by some rules
bool opacity_is_set; bool opacity_is_set;
/// Last window opacity value we set. /// Last window opacity value we set.
double opacity_set; double opacity_set;
// Fading-related members // Fading-related members
/// Override value of window fade state. Set by D-Bus method calls. /// Override value of window fade state. Set by D-Bus method calls.
switch_t fade_force; switch_t fade_force;
// Frame-opacity-related members // Frame-opacity-related members
/// Current window frame opacity. Affected by window opacity. /// Current window frame opacity. Affected by window opacity.
double frame_opacity; double frame_opacity;
/// Frame extents. Acquired from _NET_FRAME_EXTENTS. /// Frame extents. Acquired from _NET_FRAME_EXTENTS.
margin_t frame_extents; margin_t frame_extents;
// Shadow-related members // Shadow-related members
/// Whether a window has shadow. Calculated. /// Whether a window has shadow. Calculated.
bool shadow; bool shadow;
/// Override value of window shadow state. Set by D-Bus method calls. /// Override value of window shadow state. Set by D-Bus method calls.
switch_t shadow_force; switch_t shadow_force;
/// Opacity of the shadow. Affected by window opacity and frame opacity. /// Opacity of the shadow. Affected by window opacity and frame opacity.
double shadow_opacity; double shadow_opacity;
/// X offset of shadow. Affected by commandline argument. /// X offset of shadow. Affected by commandline argument.
int shadow_dx; int shadow_dx;
/// Y offset of shadow. Affected by commandline argument. /// Y offset of shadow. Affected by commandline argument.
int shadow_dy; int shadow_dy;
/// Width of shadow. Affected by window size and commandline argument. /// Width of shadow. Affected by window size and commandline argument.
int shadow_width; int shadow_width;
/// Height of shadow. Affected by window size and commandline argument. /// Height of shadow. Affected by window size and commandline argument.
int shadow_height; int shadow_height;
/// Picture to render shadow. Affected by window size. /// Picture to render shadow. Affected by window size.
paint_t shadow_paint; paint_t shadow_paint;
/// The value of _COMPTON_SHADOW attribute of the window. Below 0 for /// The value of _COMPTON_SHADOW attribute of the window. Below 0 for
/// none. /// none.
long prop_shadow; long prop_shadow;
// Dim-related members // Dim-related members
/// Whether the window is to be dimmed. /// Whether the window is to be dimmed.
bool dim; bool dim;
/// Whether to invert window color. /// Whether to invert window color.
bool invert_color; bool invert_color;
/// Override value of window color inversion state. Set by D-Bus method /// Override value of window color inversion state. Set by D-Bus method
/// calls. /// calls.
switch_t invert_color_force; switch_t invert_color_force;
/// Whether to blur window background. /// Whether to blur window background.
bool blur_background; bool blur_background;
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
/// Textures and FBO background blur use. /// Textures and FBO background blur use.
glx_blur_cache_t glx_blur_cache; glx_blur_cache_t glx_blur_cache;
#endif #endif
}; };
@@ -363,8 +363,7 @@ region_t win_get_region_frame_local_by_val(const win *w);
/** /**
* Retrieve frame extents from a window. * Retrieve frame extents from a window.
*/ */
void void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client);
win_update_frame_extents(session_t *ps, win *w, xcb_window_t client);
void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev); void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev);
/// Unmap or destroy a window /// Unmap or destroy a window
void unmap_win(session_t *ps, win **, bool destroy); void unmap_win(session_t *ps, win **, bool destroy);
@@ -375,8 +374,7 @@ void map_win_by_id(session_t *ps, xcb_window_t id);
/** /**
* Execute fade callback of a window if fading finished. * Execute fade callback of a window if fading finished.
*/ */
void void win_check_fade_finished(session_t *ps, win **_w);
win_check_fade_finished(session_t *ps, win **_w);
// Stop receiving events (except ConfigureNotify, XXX why?) from a window // Stop receiving events (except ConfigureNotify, XXX why?) from a window
void win_ev_stop(session_t *ps, const win *w); void win_ev_stop(session_t *ps, const win *w);
@@ -390,9 +388,8 @@ void win_skip_fading(session_t *ps, win **_w);
* *
* This function updates w->cache_leader if necessary. * This function updates w->cache_leader if necessary.
*/ */
static inline xcb_window_t static inline xcb_window_t win_get_leader(session_t *ps, win *w) {
win_get_leader(session_t *ps, win *w) { return win_get_leader_raw(ps, w, 0);
return win_get_leader_raw(ps, w, 0);
} }
/// check if window has ARGB visual /// check if window has ARGB visual
@@ -404,35 +401,31 @@ bool attr_pure win_is_region_ignore_valid(session_t *ps, const win *w);
/// Free all resources in a struct win /// Free all resources in a struct win
void free_win_res(session_t *ps, win *w); void free_win_res(session_t *ps, win *w);
static inline region_t static inline region_t win_get_bounding_shape_global_by_val(win *w) {
win_get_bounding_shape_global_by_val(win *w) { region_t ret;
region_t ret; pixman_region32_init(&ret);
pixman_region32_init(&ret); pixman_region32_copy(&ret, &w->bounding_shape);
pixman_region32_copy(&ret, &w->bounding_shape); pixman_region32_translate(&ret, w->g.x, w->g.y);
pixman_region32_translate(&ret, w->g.x, w->g.y); return ret;
return ret;
} }
/** /**
* Calculate the extents of the frame of the given window based on EWMH * Calculate the extents of the frame of the given window based on EWMH
* _NET_FRAME_EXTENTS and the X window border width. * _NET_FRAME_EXTENTS and the X window border width.
*/ */
static inline margin_t attr_pure static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
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 = max_i(result.top, w->g.border_width); result.left = max_i(result.left, w->g.border_width);
result.left = max_i(result.left, w->g.border_width); result.bottom = max_i(result.bottom, w->g.border_width);
result.bottom = max_i(result.bottom, w->g.border_width); result.right = max_i(result.right, w->g.border_width);
result.right = max_i(result.right, w->g.border_width); return result;
return result;
} }
/** /**
* Check whether a window has WM frames. * Check whether a window has WM frames.
*/ */
static inline bool attr_pure static inline bool attr_pure win_has_frame(const win *w) {
win_has_frame(const win *w) { return w->g.border_width || w->frame_extents.top || w->frame_extents.left ||
return w->g.border_width w->frame_extents.right || w->frame_extents.bottom;
|| w->frame_extents.top || w->frame_extents.left
|| w->frame_extents.right || w->frame_extents.bottom;
} }
+366 -395
View File
@@ -4,23 +4,23 @@
#include <stdlib.h> #include <stdlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <xcb/xcb.h> #include <pixman.h>
#include <xcb/xcb_renderutil.h>
#include <xcb/xfixes.h>
#include <xcb/sync.h>
#include <xcb/composite.h> #include <xcb/composite.h>
#include <xcb/damage.h> #include <xcb/damage.h>
#include <xcb/render.h> #include <xcb/render.h>
#include <pixman.h> #include <xcb/sync.h>
#include <xcb/xcb.h>
#include <xcb/xcb_renderutil.h>
#include <xcb/xfixes.h>
#include "utils.h"
#include "region.h"
#include "compiler.h"
#include "common.h"
#include "kernel.h"
#include "x.h"
#include "log.h"
#include "backend/gl/glx.h" #include "backend/gl/glx.h"
#include "common.h"
#include "compiler.h"
#include "kernel.h"
#include "log.h"
#include "region.h"
#include "utils.h"
#include "x.h"
/** /**
* Get a specific attribute of a window. * Get a specific attribute of a window.
@@ -37,34 +37,28 @@
* @return a <code>winprop_t</code> structure containing the attribute * @return a <code>winprop_t</code> structure containing the attribute
* and number of items. A blank one on failure. * and number of items. A blank one on failure.
*/ */
winprop_t winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, long offset, long offset, long length, xcb_atom_t rtype, int rformat) {
long 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, ps->c, xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL);
xcb_get_property(ps->c, 0, w, atom, rtype, offset, 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);
int 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 = len/(r->format/8), .type = r->type,
.type = r->type, .format = r->format,
.format = r->format, .r = r,
.r = r, };
}; }
}
free(r); free(r);
return (winprop_t) { return (winprop_t){
.ptr = NULL, .ptr = NULL, .nitems = 0, .type = XCB_GET_PROPERTY_TYPE_ANY, .format = 0};
.nitems = 0,
.type = XCB_GET_PROPERTY_TYPE_ANY,
.format = 0
};
} }
/** /**
@@ -72,44 +66,42 @@ wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, long offs
* *
* @return the value if successful, 0 otherwise * @return the value if successful, 0 otherwise
*/ */
xcb_window_t xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) {
wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) { // Get the attribute
// Get the attribute xcb_window_t p = XCB_NONE;
xcb_window_t p = XCB_NONE; winprop_t prop = wid_get_prop(ps, wid, aprop, 1L, XCB_ATOM_WINDOW, 32);
winprop_t prop = wid_get_prop(ps, wid, aprop, 1L, XCB_ATOM_WINDOW, 32);
// Return it // Return it
if (prop.nitems) { if (prop.nitems) {
p = *prop.p32; p = *prop.p32;
} }
free_winprop(&prop); free_winprop(&prop);
return p; return p;
} }
/** /**
* Get the value of a text property of a window. * Get the value of a text property of a window.
*/ */
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
char ***pstrlst, int *pnstr) { int *pnstr) {
XTextProperty text_prop = { NULL, XCB_NONE, 0, 0 }; XTextProperty text_prop = {NULL, XCB_NONE, 0, 0};
if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value)) if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value))
return false; return false;
if (Success != if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr) ||
XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr) !*pnstr) {
|| !*pnstr) { *pnstr = 0;
*pnstr = 0; if (*pstrlst)
if (*pstrlst) XFreeStringList(*pstrlst);
XFreeStringList(*pstrlst); cxfree(text_prop.value);
cxfree(text_prop.value); return false;
return false; }
}
cxfree(text_prop.value); cxfree(text_prop.value);
return true; return true;
} }
// A cache of pict formats. We assume they don't change during the lifetime // A cache of pict formats. We assume they don't change during the lifetime
@@ -117,128 +109,120 @@ bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop,
static thread_local xcb_render_query_pict_formats_reply_t *g_pictfmts = NULL; static thread_local xcb_render_query_pict_formats_reply_t *g_pictfmts = NULL;
static inline void x_get_server_pictfmts(xcb_connection_t *c) { static inline void x_get_server_pictfmts(xcb_connection_t *c) {
if (g_pictfmts) if (g_pictfmts)
return; return;
xcb_generic_error_t *e = NULL; xcb_generic_error_t *e = NULL;
// Get window picture format // Get window picture format
g_pictfmts = g_pictfmts =
xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats(c), &e);
xcb_render_query_pict_formats(c), &e); if (e || !g_pictfmts) {
if (e || !g_pictfmts) { log_fatal("failed to get pict formats\n");
log_fatal("failed to get pict formats\n"); abort();
abort(); }
}
} }
const xcb_render_pictforminfo_t * const xcb_render_pictforminfo_t *
x_get_pictform_for_visual(xcb_connection_t *c, xcb_visualid_t visual) { x_get_pictform_for_visual(xcb_connection_t *c, xcb_visualid_t visual) {
x_get_server_pictfmts(c); x_get_server_pictfmts(c);
xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual); xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual);
for(xcb_render_pictforminfo_iterator_t i = for (xcb_render_pictforminfo_iterator_t i =
xcb_render_query_pict_formats_formats_iterator(g_pictfmts); i.rem; xcb_render_query_pict_formats_formats_iterator(g_pictfmts);
xcb_render_pictforminfo_next(&i)) { i.rem; xcb_render_pictforminfo_next(&i)) {
if (i.data->id == pv->format) { if (i.data->id == pv->format) {
return i.data; return i.data;
} }
} }
return NULL; return NULL;
} }
static xcb_visualid_t attr_pure static xcb_visualid_t attr_pure x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r,
x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r, xcb_render_pictformat_t fmt) {
xcb_render_pictformat_t fmt) { for (auto screen = xcb_render_query_pict_formats_screens_iterator(r); screen.rem;
for (auto screen = xcb_render_query_pict_formats_screens_iterator(r); xcb_render_pictscreen_next(&screen)) {
screen.rem; xcb_render_pictscreen_next(&screen)) { for (auto depth = xcb_render_pictscreen_depths_iterator(screen.data);
for (auto depth = xcb_render_pictscreen_depths_iterator(screen.data); depth.rem; xcb_render_pictdepth_next(&depth)) {
depth.rem; xcb_render_pictdepth_next(&depth)) { for (auto pv = xcb_render_pictdepth_visuals_iterator(depth.data);
for (auto pv = xcb_render_pictdepth_visuals_iterator(depth.data); pv.rem; pv.rem; xcb_render_pictvisual_next(&pv)) {
xcb_render_pictvisual_next(&pv)) { if (pv.data->format == fmt) {
if (pv.data->format == fmt) { return pv.data->visual;
return pv.data->visual; }
} }
} }
} }
} return XCB_NONE;
return XCB_NONE;
} }
xcb_visualid_t xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) {
x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) { x_get_server_pictfmts(c);
x_get_server_pictfmts(c);
auto pictfmt = auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, std);
xcb_render_util_find_standard_format(g_pictfmts, std);
return x_get_visual_for_pictfmt(g_pictfmts, pictfmt->id); return x_get_visual_for_pictfmt(g_pictfmts, pictfmt->id);
} }
int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) { int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
auto setup = xcb_get_setup(c); auto setup = xcb_get_setup(c);
for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; xcb_screen_next(&screen)) { for (auto screen = xcb_setup_roots_iterator(setup); screen.rem;
for (auto depth = xcb_screen_allowed_depths_iterator(screen.data); depth.rem; xcb_depth_next(&depth)) { xcb_screen_next(&screen)) {
const int len = xcb_depth_visuals_length(depth.data); for (auto depth = xcb_screen_allowed_depths_iterator(screen.data);
const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data); depth.rem; xcb_depth_next(&depth)) {
for (int i = 0; i < len; i++) { const int len = xcb_depth_visuals_length(depth.data);
if (visual == visuals[i].visual_id) { const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data);
return depth.data->depth; for (int i = 0; i < len; i++) {
} if (visual == visuals[i].visual_id) {
} return depth.data->depth;
} }
} }
return -1; }
}
return -1;
} }
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_pictfmt_and_pixmap( x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
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, unsigned long 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) { xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr);
xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr); if (!buf) {
if (!buf) { log_error("failed to serialize picture attributes");
log_error("failed to serialize picture attributes"); return XCB_NONE;
return XCB_NONE; }
} }
}
xcb_render_picture_t tmp_picture = xcb_generate_id(c); xcb_render_picture_t tmp_picture = xcb_generate_id(c);
xcb_generic_error_t *e = xcb_generic_error_t *e =
xcb_request_check(c, xcb_render_create_picture_checked(c, tmp_picture, xcb_request_check(c, xcb_render_create_picture_checked(
pixmap, pictfmt->id, valuemask, buf)); c, tmp_picture, pixmap, pictfmt->id, valuemask, buf));
free(buf); free(buf);
if (e) { if (e) {
x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code); x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code);
log_error("failed to create picture"); log_error("failed to create picture");
return XCB_NONE; return XCB_NONE;
} }
return tmp_picture; return tmp_picture;
} }
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_visual_and_pixmap( x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual,
xcb_connection_t *c, xcb_visualid_t visual, xcb_pixmap_t pixmap, unsigned long valuemask,
xcb_pixmap_t pixmap, unsigned long 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);
{ return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
} }
xcb_render_picture_t xcb_render_picture_t
x_create_picture_with_standard_and_pixmap( x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard,
xcb_connection_t *c, xcb_pict_standard_t standard, xcb_pixmap_t pixmap, unsigned long valuemask,
xcb_pixmap_t pixmap, unsigned long 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);
auto pictfmt = auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, standard);
xcb_render_util_find_standard_format(g_pictfmts, standard); assert(pictfmt);
assert(pictfmt); 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);
} }
/** /**
@@ -246,98 +230,90 @@ x_create_picture_with_standard_and_pixmap(
*/ */
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 wid, int hei,
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr) const xcb_render_create_picture_value_list_t *attr) {
{ int depth = pictfmt->depth;
int 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, wid, hei);
if (!tmp_pixmap) if (!tmp_pixmap)
return XCB_NONE; return XCB_NONE;
xcb_render_picture_t picture = xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap(
x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, tmp_pixmap, valuemask, attr); c, pictfmt, tmp_pixmap, valuemask, attr);
xcb_free_pixmap(c, tmp_pixmap); xcb_free_pixmap(c, tmp_pixmap);
return picture; return picture;
} }
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, unsigned long 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);
} }
bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_t *res) { bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_t *res) {
xcb_generic_error_t *e = NULL; xcb_generic_error_t *e = NULL;
xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c, xcb_xfixes_fetch_region_reply_t *xr =
xcb_xfixes_fetch_region(c, r), &e); xcb_xfixes_fetch_region_reply(c, xcb_xfixes_fetch_region(c, r), &e);
if (!xr) { if (!xr) {
log_error("Failed to fetch rectangles"); log_error("Failed to fetch rectangles");
return false; return false;
} }
int nrect = xcb_xfixes_fetch_region_rectangles_length(xr); int nrect = xcb_xfixes_fetch_region_rectangles_length(xr);
auto b = ccalloc(nrect, pixman_box32_t); auto b = ccalloc(nrect, pixman_box32_t);
xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr); xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr);
for (int i = 0; i < nrect; i++) { for (int i = 0; i < nrect; i++) {
b[i] = (pixman_box32_t) { b[i] = (pixman_box32_t){.x1 = xrect[i].x,
.x1 = xrect[i].x, .y1 = xrect[i].y,
.y1 = xrect[i].y, .x2 = xrect[i].x + xrect[i].width,
.x2 = xrect[i].x + xrect[i].width, .y2 = xrect[i].y + xrect[i].height};
.y2 = xrect[i].y + xrect[i].height }
}; bool ret = pixman_region32_init_rects(res, b, nrect);
} free(b);
bool ret = pixman_region32_init_rects(res, b, nrect); free(xr);
free(b); return ret;
free(xr);
return ret;
} }
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) { int clip_x_origin, int 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 = rects[i].x1,
.y = rects[i].y1, .y = rects[i].y1,
.width = rects[i].x2 - rects[i].x1, .width = rects[i].x2 - rects[i].x1,
.height = rects[i].y2 - rects[i].y1, .height = rects[i].y2 - rects[i].y1,
}; };
xcb_generic_error_t *e = xcb_generic_error_t *e =
xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(c, pict, xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(
clip_x_origin, clip_y_origin, nrects, xrects)); c, pict, clip_x_origin, clip_y_origin, nrects, xrects));
if (e) if (e)
log_error("Failed to set clip region"); log_error("Failed to set clip region");
free(e); free(e);
free(xrects); free(xrects);
return; return;
} }
void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict) { void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict) {
xcb_render_change_picture_value_list_t v = { xcb_render_change_picture_value_list_t v = {.clipmask = XCB_NONE};
.clipmask = XCB_NONE xcb_generic_error_t *e = xcb_request_check(
}; c, xcb_render_change_picture(c, pict, XCB_RENDER_CP_CLIP_MASK, &v));
xcb_generic_error_t *e = if (e)
xcb_request_check(c, xcb_render_change_picture(c, pict, log_error("failed to clear clip region");
XCB_RENDER_CP_CLIP_MASK, &v)); free(e);
if (e) return;
log_error("failed to clear clip region");
free(e);
return;
} }
enum { enum { XSyncBadCounter = 0,
XSyncBadCounter = 0, XSyncBadAlarm = 1,
XSyncBadAlarm = 1, XSyncBadFence = 2,
XSyncBadFence = 2,
}; };
/** /**
@@ -345,106 +321,102 @@ enum {
* *
* XXX consider making this error to string * XXX consider making this error to string
*/ */
void void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) {
x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) { session_t *const ps = ps_g;
session_t * const ps = ps_g;
int o = 0; int o = 0;
const char *name = "Unknown"; const char *name = "Unknown";
if (major == ps->composite_opcode if (major == ps->composite_opcode && minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) {
&& minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) { log_fatal("Another composite manager is already running "
log_fatal("Another composite manager is already running " "(and does not handle _NET_WM_CM_Sn correctly)");
"(and does not handle _NET_WM_CM_Sn correctly)"); exit(1);
exit(1); }
}
#define CASESTRRET2(s) case s: name = #s; break #define CASESTRRET2(s) \
case s: name = #s; break
o = error_code - ps->xfixes_error; o = error_code - ps->xfixes_error;
switch (o) { switch (o) { CASESTRRET2(XCB_XFIXES_BAD_REGION); }
CASESTRRET2(XCB_XFIXES_BAD_REGION);
}
o = error_code - ps->damage_error; o = error_code - ps->damage_error;
switch (o) { switch (o) { CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE); }
CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE);
}
o = error_code - ps->render_error; o = error_code - ps->render_error;
switch (o) { switch (o) {
CASESTRRET2(XCB_RENDER_PICT_FORMAT); CASESTRRET2(XCB_RENDER_PICT_FORMAT);
CASESTRRET2(XCB_RENDER_PICTURE); CASESTRRET2(XCB_RENDER_PICTURE);
CASESTRRET2(XCB_RENDER_PICT_OP); CASESTRRET2(XCB_RENDER_PICT_OP);
CASESTRRET2(XCB_RENDER_GLYPH_SET); CASESTRRET2(XCB_RENDER_GLYPH_SET);
CASESTRRET2(XCB_RENDER_GLYPH); CASESTRRET2(XCB_RENDER_GLYPH);
} }
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (ps->glx_exists) { if (ps->glx_exists) {
o = error_code - ps->glx_error; o = error_code - ps->glx_error;
switch (o) { switch (o) {
CASESTRRET2(GLX_BAD_SCREEN); CASESTRRET2(GLX_BAD_SCREEN);
CASESTRRET2(GLX_BAD_ATTRIBUTE); CASESTRRET2(GLX_BAD_ATTRIBUTE);
CASESTRRET2(GLX_NO_EXTENSION); CASESTRRET2(GLX_NO_EXTENSION);
CASESTRRET2(GLX_BAD_VISUAL); CASESTRRET2(GLX_BAD_VISUAL);
CASESTRRET2(GLX_BAD_CONTEXT); CASESTRRET2(GLX_BAD_CONTEXT);
CASESTRRET2(GLX_BAD_VALUE); CASESTRRET2(GLX_BAD_VALUE);
CASESTRRET2(GLX_BAD_ENUM); CASESTRRET2(GLX_BAD_ENUM);
} }
} }
#endif #endif
if (ps->xsync_exists) { if (ps->xsync_exists) {
o = error_code - ps->xsync_error; o = error_code - ps->xsync_error;
switch (o) { switch (o) {
CASESTRRET2(XSyncBadCounter); CASESTRRET2(XSyncBadCounter);
CASESTRRET2(XSyncBadAlarm); CASESTRRET2(XSyncBadAlarm);
CASESTRRET2(XSyncBadFence); CASESTRRET2(XSyncBadFence);
} }
} }
switch (error_code) { switch (error_code) {
CASESTRRET2(BadAccess); CASESTRRET2(BadAccess);
CASESTRRET2(BadAlloc); CASESTRRET2(BadAlloc);
CASESTRRET2(BadAtom); CASESTRRET2(BadAtom);
CASESTRRET2(BadColor); CASESTRRET2(BadColor);
CASESTRRET2(BadCursor); CASESTRRET2(BadCursor);
CASESTRRET2(BadDrawable); CASESTRRET2(BadDrawable);
CASESTRRET2(BadFont); CASESTRRET2(BadFont);
CASESTRRET2(BadGC); CASESTRRET2(BadGC);
CASESTRRET2(BadIDChoice); CASESTRRET2(BadIDChoice);
CASESTRRET2(BadImplementation); CASESTRRET2(BadImplementation);
CASESTRRET2(BadLength); CASESTRRET2(BadLength);
CASESTRRET2(BadMatch); CASESTRRET2(BadMatch);
CASESTRRET2(BadName); CASESTRRET2(BadName);
CASESTRRET2(BadPixmap); CASESTRRET2(BadPixmap);
CASESTRRET2(BadRequest); CASESTRRET2(BadRequest);
CASESTRRET2(BadValue); CASESTRRET2(BadValue);
CASESTRRET2(BadWindow); CASESTRRET2(BadWindow);
} }
#undef CASESTRRET2 #undef CASESTRRET2
log_debug("X error %d %s request %d minor %d serial %lu", log_debug("X error %d %s request %d minor %d serial %lu", error_code, name, major,
error_code, name, major, minor, serial); minor, serial);
} }
/** /**
* Create a pixmap and check that creation succeeded. * Create a pixmap and check that creation succeeded.
*/ */
xcb_pixmap_t xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable,
x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height) { uint16_t width, uint16_t height) {
xcb_pixmap_t pix = xcb_generate_id(c); xcb_pixmap_t pix = xcb_generate_id(c);
xcb_void_cookie_t cookie = xcb_create_pixmap_checked(c, depth, pix, drawable, width, height); xcb_void_cookie_t cookie =
xcb_generic_error_t *err = xcb_request_check(c, cookie); xcb_create_pixmap_checked(c, depth, pix, drawable, width, height);
if (err == NULL) xcb_generic_error_t *err = xcb_request_check(c, cookie);
return pix; if (err == NULL)
return pix;
log_error("Failed to create pixmap:"); log_error("Failed to create pixmap:");
x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code); x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code);
free(err); free(err);
return XCB_NONE; return XCB_NONE;
} }
/** /**
@@ -453,55 +425,54 @@ x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, uin
* Detect whether the pixmap is valid with XGetGeometry. Well, maybe there * Detect whether the pixmap is valid with XGetGeometry. Well, maybe there
* are better ways. * are better ways.
*/ */
bool bool x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) {
x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) { if (pixmap == XCB_NONE) {
if (pixmap == XCB_NONE) { return false;
return false; }
}
auto r = xcb_get_geometry_reply(c, xcb_get_geometry(c, pixmap), NULL); auto r = xcb_get_geometry_reply(c, xcb_get_geometry(c, pixmap), NULL);
if (!r) { if (!r) {
return false; return false;
} }
bool ret = r->width && r->height; bool ret = r->width && r->height;
free(r); free(r);
return ret; return ret;
} }
/// Names of root window properties that could point to a pixmap of /// Names of root window properties that could point to a pixmap of
/// background. /// background.
static const char *background_props_str[] = { static const char *background_props_str[] = {
"_XROOTPMAP_ID", "_XROOTPMAP_ID",
"_XSETROOT_ID", "_XSETROOT_ID",
0, 0,
}; };
xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) { xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) {
xcb_pixmap_t pixmap = XCB_NONE; xcb_pixmap_t pixmap = XCB_NONE;
// Get the values of background attributes // Get the values of background attributes
for (int p = 0; background_props_str[p]; p++) { for (int p = 0; background_props_str[p]; p++) {
xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]);
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 = *prop.p32;
free_winprop(&prop); free_winprop(&prop);
break; break;
} }
free_winprop(&prop); free_winprop(&prop);
} }
return pixmap; return pixmap;
} }
bool x_is_root_back_pixmap_atom(session_t *ps, xcb_atom_t atom) { bool x_is_root_back_pixmap_atom(session_t *ps, xcb_atom_t atom) {
for (int p = 0; background_props_str[p]; p++) { for (int p = 0; background_props_str[p]; p++) {
xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]);
if (prop_atom == atom) if (prop_atom == atom)
return true; return true;
} }
return false; return false;
} }
/** /**
@@ -509,36 +480,36 @@ bool x_is_root_back_pixmap_atom(session_t *ps, xcb_atom_t atom) {
* are completed. * are completed.
*/ */
bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) { bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) {
// TODO(richardgv): If everybody just follows the rules stated in X Sync // TODO(richardgv): If everybody just follows the rules stated in X Sync
// prototype, we need only one fence per screen, but let's stay a bit // prototype, we need only one fence per screen, but let's stay a bit
// cautious right now // cautious right now
auto e = xcb_request_check(c, xcb_sync_trigger_fence_checked(c, f)); auto e = xcb_request_check(c, xcb_sync_trigger_fence_checked(c, f));
if (e) { if (e) {
log_error("Failed to trigger the fence."); log_error("Failed to trigger the fence.");
free(e); free(e);
return false; return false;
} }
e = xcb_request_check(c, xcb_sync_await_fence_checked(c, 1, &f)); e = xcb_request_check(c, xcb_sync_await_fence_checked(c, 1, &f));
if (e) { if (e) {
log_error("Failed to await on a fence."); log_error("Failed to await on a fence.");
free(e); free(e);
return false; return false;
} }
e = xcb_request_check(c, xcb_sync_reset_fence_checked(c, f)); e = xcb_request_check(c, xcb_sync_reset_fence_checked(c, f));
if (e) { if (e) {
log_error("Failed to reset the fence."); log_error("Failed to reset the fence.");
free(e); free(e);
return false; return false;
} }
return true; return true;
} }
// xcb-render specific macros // xcb-render specific macros
#define XFIXED_TO_DOUBLE(value) (((double) (value)) / 65536) #define XFIXED_TO_DOUBLE(value) (((double)(value)) / 65536)
#define DOUBLE_TO_XFIXED(value) ((xcb_render_fixed_t) (((double) (value)) * 65536)) #define DOUBLE_TO_XFIXED(value) ((xcb_render_fixed_t)(((double)(value)) * 65536))
/** /**
* Convert a struct conv to a X picture convolution filter, normalizing the kernel * Convert a struct conv to a X picture convolution filter, normalizing the kernel
@@ -552,35 +523,35 @@ 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, xcb_render_fixed_t **ret, size_t x_picture_filter_from_conv(const conv *kernel, double center,
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 = kernel->w * kernel->h + 2;
*ret = crealloc(*ret, *size); *ret = crealloc(*ret, *size);
} }
auto buf = *ret; auto buf = *ret;
buf[0] = DOUBLE_TO_XFIXED(kernel->w); buf[0] = DOUBLE_TO_XFIXED(kernel->w);
buf[1] = DOUBLE_TO_XFIXED(kernel->h); buf[1] = DOUBLE_TO_XFIXED(kernel->h);
double sum = center; double sum = center;
for (int i = 0; i < kernel->w * kernel->h; i++) { for (int i = 0; i < kernel->w * kernel->h; i++) {
sum += kernel->data[i]; sum += kernel->data[i];
} }
// Note for floating points a / b != a * (1 / b), but this shouldn't have any real // Note for floating points a / b != a * (1 / b), but this shouldn't have any real
// impact on the result // impact on the result
double factor = sum != 0 ? 1.0 / sum : 1; double factor = sum != 0 ? 1.0 / sum : 1;
for (int i = 0; i < kernel->w * kernel->h; i++) { for (int i = 0; i < kernel->w * kernel->h; i++) {
buf[i + 2] = DOUBLE_TO_XFIXED(kernel->data[i] * factor); buf[i + 2] = DOUBLE_TO_XFIXED(kernel->data[i] * factor);
} }
buf[kernel->h / 2 * kernel->w + kernel->w / 2 + 2] = DOUBLE_TO_XFIXED(center * factor); buf[kernel->h / 2 * kernel->w + kernel->w / 2 + 2] =
return kernel->w * kernel->h + 2; DOUBLE_TO_XFIXED(center * factor);
return kernel->w * kernel->h + 2;
} }
/// 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 struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
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) {
+12 -13
View File
@@ -137,16 +137,17 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_
/** /**
* Create an picture. * Create an picture.
*/ */
xcb_render_picture_t attr_nonnull(1, 5) 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 wid, int hei,
const xcb_render_pictforminfo_t *pictfmt, const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
unsigned long valuemask, const xcb_render_create_picture_value_list_t *attr)
const xcb_render_create_picture_value_list_t *attr); attr_nonnull(1, 5);
xcb_render_picture_t attr_nonnull(1) 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, unsigned long valuemask,
const xcb_render_create_picture_value_list_t *attr); const xcb_render_create_picture_value_list_t *attr)
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);
@@ -206,8 +207,6 @@ 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, -1} on failure
struct xvisual_info struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
xcb_visualid_t xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
+32 -38
View File
@@ -8,64 +8,58 @@
static xrc_xid_record_t *gs_xid_records = NULL; static xrc_xid_record_t *gs_xid_records = NULL;
#define HASH_ADD_XID(head, xidfield, add) \ #define HASH_ADD_XID(head, xidfield, add) HASH_ADD(hh, head, xidfield, sizeof(xid), add)
HASH_ADD(hh, head, xidfield, sizeof(xid), add)
#define HASH_FIND_XID(head, findxid, out) \ #define HASH_FIND_XID(head, findxid, out) HASH_FIND(hh, head, findxid, sizeof(xid), out)
HASH_FIND(hh, head, findxid, sizeof(xid), out)
#define M_CPY_POS_DATA(prec) \ #define M_CPY_POS_DATA(prec) \
prec->file = file; \ prec->file = file; \
prec->func = func; \ prec->func = func; \
prec->line = line; \ prec->line = line;
/** /**
* @brief Add a record of given XID to the allocation table. * @brief Add a record of given XID to the allocation table.
*/ */
void void xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) {
xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) { auto prec = ccalloc(1, xrc_xid_record_t);
auto prec = ccalloc(1, xrc_xid_record_t); prec->xid = xid;
prec->xid = xid; prec->type = type;
prec->type = type; M_CPY_POS_DATA(prec);
M_CPY_POS_DATA(prec);
HASH_ADD_XID(gs_xid_records, xid, prec); HASH_ADD_XID(gs_xid_records, xid, prec);
} }
/** /**
* @brief Delete a record of given XID in the allocation table. * @brief Delete a record of given XID in the allocation table.
*/ */
void void xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) {
xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) { xrc_xid_record_t *prec = NULL;
xrc_xid_record_t *prec = NULL; HASH_FIND_XID(gs_xid_records, &xid, prec);
HASH_FIND_XID(gs_xid_records, &xid, prec); if (!prec) {
if (!prec) { log_error("XRC: %s:%d %s(): Can't find XID %#010lx we want to delete.",
log_error("XRC: %s:%d %s(): Can't find XID %#010lx we want to delete.", file, line, func, xid);
file, line, func, xid); return;
return; }
} HASH_DEL(gs_xid_records, prec);
HASH_DEL(gs_xid_records, prec); free(prec);
free(prec);
} }
/** /**
* @brief Report about issues found in the XID allocation table. * @brief Report about issues found in the XID allocation table.
*/ */
void void xrc_report_xid(void) {
xrc_report_xid(void) { for (xrc_xid_record_t *prec = gs_xid_records; prec; prec = prec->hh.next)
for (xrc_xid_record_t *prec = gs_xid_records; prec; prec = prec->hh.next) log_trace("XRC: %s:%d %s(): %#010lx (%s) not freed.\n", prec->file,
log_trace("XRC: %s:%d %s(): %#010lx (%s) not freed.\n", prec->line, prec->func, prec->xid, prec->type);
prec->file, prec->line, prec->func, prec->xid, prec->type);
} }
/** /**
* @brief Clear the XID allocation table. * @brief Clear the XID allocation table.
*/ */
void void xrc_clear_xid(void) {
xrc_clear_xid(void) { xrc_xid_record_t *prec = NULL, *ptmp = NULL;
xrc_xid_record_t *prec = NULL, *ptmp = NULL; HASH_ITER(hh, gs_xid_records, prec, ptmp) {
HASH_ITER(hh, gs_xid_records, prec, ptmp) { HASH_DEL(gs_xid_records, prec);
HASH_DEL(gs_xid_records, prec); free(prec);
free(prec); }
}
} }
+26 -29
View File
@@ -6,60 +6,57 @@
#include "uthash.h" #include "uthash.h"
typedef struct { typedef struct {
XID xid; XID xid;
const char *type; const char *type;
const char *file; const char *file;
const char *func; const char *func;
int line; int line;
UT_hash_handle hh; UT_hash_handle hh;
} xrc_xid_record_t; } xrc_xid_record_t;
#define M_POS_DATA_PARAMS const char *file, int line, const char *func #define M_POS_DATA_PARAMS const char *file, int line, const char *func
#define M_POS_DATA_PASSTHROUGH file, line, func #define M_POS_DATA_PASSTHROUGH file, line, func
#define M_POS_DATA __FILE__, __LINE__, __func__ #define M_POS_DATA __FILE__, __LINE__, __func__
void void xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS);
xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS);
#define xrc_add_xid(xid, type) xrc_add_xid_(xid, type, M_POS_DATA) #define xrc_add_xid(xid, type) xrc_add_xid_(xid, type, M_POS_DATA)
void void xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS);
xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS);
#define xrc_delete_xid(xid) xrc_delete_xid_(xid, M_POS_DATA) #define xrc_delete_xid(xid) xrc_delete_xid_(xid, M_POS_DATA)
void void xrc_report_xid(void);
xrc_report_xid(void);
void void xrc_clear_xid(void);
xrc_clear_xid(void);
// Pixmap // Pixmap
static inline void static inline void xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth,
xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth, xcb_pixmap_t pixmap, xcb_pixmap_t pixmap, xcb_drawable_t drawable,
xcb_drawable_t drawable, uint16_t width, uint16_t height, M_POS_DATA_PARAMS) { uint16_t width, uint16_t height, M_POS_DATA_PARAMS) {
xcb_create_pixmap(c, depth, pixmap, drawable, width, height); xcb_create_pixmap(c, depth, pixmap, drawable, width, height);
xrc_add_xid_(pixmap, "Pixmap", M_POS_DATA_PASSTHROUGH); xrc_add_xid_(pixmap, "Pixmap", M_POS_DATA_PASSTHROUGH);
} }
#define xcb_create_pixmap(c, depth, pixmap, drawable, width, height) \ #define xcb_create_pixmap(c, depth, pixmap, drawable, width, height) \
xcb_create_pixmap_(c, depth, pixmap, drawable, width, height, M_POS_DATA) xcb_create_pixmap_(c, depth, pixmap, drawable, width, height, M_POS_DATA)
static inline xcb_void_cookie_t static inline xcb_void_cookie_t
xcb_composite_name_window_pixmap_(xcb_connection_t *c, xcb_window_t window, xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) { xcb_composite_name_window_pixmap_(xcb_connection_t *c, xcb_window_t window,
xcb_void_cookie_t ret = xcb_composite_name_window_pixmap(c, window, pixmap); xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) {
xrc_add_xid_(pixmap, "PixmapC", M_POS_DATA_PASSTHROUGH); xcb_void_cookie_t ret = xcb_composite_name_window_pixmap(c, window, pixmap);
return ret; xrc_add_xid_(pixmap, "PixmapC", M_POS_DATA_PASSTHROUGH);
return ret;
} }
#define xcb_composite_name_window_pixmap(dpy, window, pixmap) \ #define xcb_composite_name_window_pixmap(dpy, window, pixmap) \
xcb_composite_name_window_pixmap_(dpy, window, pixmap, M_POS_DATA) xcb_composite_name_window_pixmap_(dpy, window, pixmap, M_POS_DATA)
static inline void static inline void
xcb_free_pixmap_(xcb_connection_t *c, xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) { xcb_free_pixmap_(xcb_connection_t *c, xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) {
xcb_free_pixmap(c, pixmap); xcb_free_pixmap(c, pixmap);
xrc_delete_xid_(pixmap, M_POS_DATA_PASSTHROUGH); xrc_delete_xid_(pixmap, M_POS_DATA_PASSTHROUGH);
} }
#define xcb_free_pixmap(c, pixmap) xcb_free_pixmap_(c, pixmap, M_POS_DATA); #define xcb_free_pixmap(c, pixmap) xcb_free_pixmap_(c, pixmap, M_POS_DATA);