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:
parent
7845673734
commit
22da17630f
1115
src/common.h
1115
src/common.h
File diff suppressed because it is too large
Load Diff
4594
src/compton.c
4594
src/compton.c
File diff suppressed because it is too large
Load Diff
117
src/compton.h
117
src/compton.h
|
@ -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 :
|
||||||
|
|
667
src/config.c
667
src/config.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
17
src/config.h
17
src/config.h
|
@ -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 *);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
1869
src/dbus.c
1869
src/dbus.c
File diff suppressed because it is too large
Load Diff
1800
src/opengl.c
1800
src/opengl.c
File diff suppressed because it is too large
Load Diff
185
src/opengl.h
185
src/opengl.h
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
25
src/types.h
25
src/types.h
|
@ -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 }
|
||||||
|
|
230
src/vsync.c
230
src/vsync.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
429
src/win.h
429
src/win.h
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
761
src/x.c
761
src/x.c
|
@ -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) {
|
||||||
|
|
25
src/x.h
25
src/x.h
|
@ -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);
|
|
||||||
|
|
|
@ -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);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue