mirror of https://github.com/yshui/picom.git
Merge pull request #516 from yshui/no-xlib
x: remove the last bit of Xlib dependency
This commit is contained in:
commit
6c6b1afeb3
|
@ -14,3 +14,6 @@ Checks: >
|
||||||
-readability-magic-numbers
|
-readability-magic-numbers
|
||||||
AnalyzeTemporaryDtors: false
|
AnalyzeTemporaryDtors: false
|
||||||
FormatStyle: file
|
FormatStyle: file
|
||||||
|
CheckOptions:
|
||||||
|
- key: readability-magic-numbers.IgnoredIntegerValues
|
||||||
|
value: 4;8;16;24;32;1;2;3;4096
|
||||||
|
|
|
@ -30,7 +30,8 @@ struct atom *init_atoms(xcb_connection_t *c) {
|
||||||
auto atoms = ccalloc(1, struct atom);
|
auto atoms = ccalloc(1, struct atom);
|
||||||
atoms->c = new_cache((void *)c, atom_getter, NULL);
|
atoms->c = new_cache((void *)c, atom_getter, NULL);
|
||||||
#define ATOM_GET(x) atoms->a##x = (xcb_atom_t)(intptr_t)cache_get(atoms->c, #x, NULL)
|
#define ATOM_GET(x) atoms->a##x = (xcb_atom_t)(intptr_t)cache_get(atoms->c, #x, NULL)
|
||||||
LIST_APPLY(ATOM_GET, SEP_COLON, ATOM_LIST);
|
LIST_APPLY(ATOM_GET, SEP_COLON, ATOM_LIST1);
|
||||||
|
LIST_APPLY(ATOM_GET, SEP_COLON, ATOM_LIST2);
|
||||||
#undef ATOM_GET
|
#undef ATOM_GET
|
||||||
return atoms;
|
return atoms;
|
||||||
}
|
}
|
||||||
|
|
15
src/atom.h
15
src/atom.h
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// Splitted into 2 lists because of the limitation of our macros
|
// Splitted into 2 lists because of the limitation of our macros
|
||||||
#define ATOM_LIST \
|
#define ATOM_LIST1 \
|
||||||
_NET_WM_WINDOW_OPACITY, \
|
_NET_WM_WINDOW_OPACITY, \
|
||||||
_NET_FRAME_EXTENTS, \
|
_NET_FRAME_EXTENTS, \
|
||||||
WM_STATE, \
|
WM_STATE, \
|
||||||
|
@ -16,12 +16,16 @@
|
||||||
_NET_WM_PID, \
|
_NET_WM_PID, \
|
||||||
WM_NAME, \
|
WM_NAME, \
|
||||||
WM_CLASS, \
|
WM_CLASS, \
|
||||||
|
WM_ICON_NAME, \
|
||||||
WM_TRANSIENT_FOR, \
|
WM_TRANSIENT_FOR, \
|
||||||
WM_WINDOW_ROLE, \
|
WM_WINDOW_ROLE, \
|
||||||
WM_CLIENT_LEADER, \
|
WM_CLIENT_LEADER, \
|
||||||
|
WM_CLIENT_MACHINE, \
|
||||||
_NET_ACTIVE_WINDOW, \
|
_NET_ACTIVE_WINDOW, \
|
||||||
_COMPTON_SHADOW, \
|
_COMPTON_SHADOW, \
|
||||||
_NET_WM_WINDOW_TYPE, \
|
_NET_WM_WINDOW_TYPE
|
||||||
|
|
||||||
|
#define ATOM_LIST2 \
|
||||||
_NET_WM_WINDOW_TYPE_DESKTOP, \
|
_NET_WM_WINDOW_TYPE_DESKTOP, \
|
||||||
_NET_WM_WINDOW_TYPE_DOCK, \
|
_NET_WM_WINDOW_TYPE_DOCK, \
|
||||||
_NET_WM_WINDOW_TYPE_TOOLBAR, \
|
_NET_WM_WINDOW_TYPE_TOOLBAR, \
|
||||||
|
@ -38,14 +42,17 @@
|
||||||
_NET_WM_WINDOW_TYPE_DND, \
|
_NET_WM_WINDOW_TYPE_DND, \
|
||||||
_NET_WM_STATE, \
|
_NET_WM_STATE, \
|
||||||
_NET_WM_STATE_FULLSCREEN, \
|
_NET_WM_STATE_FULLSCREEN, \
|
||||||
_NET_WM_BYPASS_COMPOSITOR
|
_NET_WM_BYPASS_COMPOSITOR, \
|
||||||
|
UTF8_STRING, \
|
||||||
|
C_STRING
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#define ATOM_DEF(x) xcb_atom_t a##x
|
#define ATOM_DEF(x) xcb_atom_t a##x
|
||||||
|
|
||||||
struct atom {
|
struct atom {
|
||||||
struct cache *c;
|
struct cache *c;
|
||||||
LIST_APPLY(ATOM_DEF, SEP_COLON, ATOM_LIST);
|
LIST_APPLY(ATOM_DEF, SEP_COLON, ATOM_LIST1);
|
||||||
|
LIST_APPLY(ATOM_DEF, SEP_COLON, ATOM_LIST2);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct atom *init_atoms(xcb_connection_t *);
|
struct atom *init_atoms(xcb_connection_t *);
|
||||||
|
|
11
src/c2.c
11
src/c2.c
|
@ -1406,8 +1406,9 @@ static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w
|
||||||
tgt_free = strdup(strlst[idx]);
|
tgt_free = strdup(strlst[idx]);
|
||||||
tgt = tgt_free;
|
tgt = tgt_free;
|
||||||
}
|
}
|
||||||
if (strlst)
|
if (strlst) {
|
||||||
XFreeStringList(strlst);
|
free(strlst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tgt) {
|
if (tgt) {
|
||||||
|
@ -1464,10 +1465,7 @@ static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w
|
||||||
|
|
||||||
// Free the string after usage, if necessary
|
// Free the string after usage, if necessary
|
||||||
if (tgt_free) {
|
if (tgt_free) {
|
||||||
if (C2_L_TATOM == pleaf->type)
|
free(tgt_free);
|
||||||
XFree(tgt_free);
|
|
||||||
else
|
|
||||||
free(tgt_free);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
|
@ -1557,6 +1555,7 @@ static bool c2_match_once(session_t *ps, const struct managed_win *w, const c2_p
|
||||||
*/
|
*/
|
||||||
bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condlst,
|
bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condlst,
|
||||||
void **pdata) {
|
void **pdata) {
|
||||||
|
assert(ps->server_grabbed);
|
||||||
// Then go through the whole linked list
|
// Then go through the whole linked list
|
||||||
for (; condlst; condlst = condlst->next) {
|
for (; condlst; condlst = condlst->next) {
|
||||||
if (c2_match_once(ps, w, condlst->ptr)) {
|
if (c2_match_once(ps, w, condlst->ptr)) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <stdc-predef.h>
|
#include <stdc-predef.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
#define auto __auto_type
|
#define auto __auto_type
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
@ -78,6 +79,12 @@
|
||||||
# define attr_malloc
|
# define attr_malloc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __has_attribute(fallthrough)
|
||||||
|
# define fallthrough() __attribute__((fallthrough))
|
||||||
|
#else
|
||||||
|
# define fallthrough()
|
||||||
|
#endif
|
||||||
|
|
||||||
#if __STDC_VERSION__ >= 201112L
|
#if __STDC_VERSION__ >= 201112L
|
||||||
# define attr_noret _Noreturn
|
# define attr_noret _Noreturn
|
||||||
#else
|
#else
|
||||||
|
@ -107,6 +114,7 @@
|
||||||
#else
|
#else
|
||||||
# define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__
|
# define thread_local _Pragma("GCC error \"No thread local storage support\"") __error__
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
typedef unsigned long ulong;
|
typedef unsigned long ulong;
|
||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
|
|
63
src/picom.c
63
src/picom.c
|
@ -13,6 +13,7 @@
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/extensions/sync.h>
|
#include <X11/extensions/sync.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -918,7 +919,7 @@ void opts_set_no_fading_openclose(session_t *ps, bool newval) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register us with the compositor selection (_NET_WM_CM_S)
|
* Setup window properties, then register us with the compositor selection (_NET_WM_CM_S)
|
||||||
*
|
*
|
||||||
* @return 0 if success, 1 if compositor already running, -1 if error.
|
* @return 0 if success, 1 if compositor already running, -1 if error.
|
||||||
*/
|
*/
|
||||||
|
@ -936,15 +937,56 @@ static int register_cm(session_t *ps) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
const xcb_atom_t prop_atoms[] = {
|
||||||
XClassHint *h = XAllocClassHint();
|
ps->atoms->aWM_NAME,
|
||||||
if (h) {
|
ps->atoms->a_NET_WM_NAME,
|
||||||
h->res_name = "picom";
|
ps->atoms->aWM_ICON_NAME,
|
||||||
h->res_class = "picom";
|
};
|
||||||
|
|
||||||
|
const bool prop_is_utf8[] = {false, true, false};
|
||||||
|
|
||||||
|
// Set names and classes
|
||||||
|
for (size_t i = 0; i < ARR_SIZE(prop_atoms); i++) {
|
||||||
|
e = xcb_request_check(
|
||||||
|
ps->c, xcb_change_property_checked(
|
||||||
|
ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, prop_atoms[i],
|
||||||
|
prop_is_utf8[i] ? ps->atoms->aUTF8_STRING : XCB_ATOM_STRING,
|
||||||
|
8, strlen("picom"), "picom"));
|
||||||
|
if (e) {
|
||||||
|
log_error_x_error(e, "Failed to set window property %d",
|
||||||
|
prop_atoms[i]);
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char picom_class[] = "picom\0picom";
|
||||||
|
e = xcb_request_check(
|
||||||
|
ps->c, xcb_change_property_checked(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
|
||||||
|
ps->atoms->aWM_CLASS, XCB_ATOM_STRING, 8,
|
||||||
|
ARR_SIZE(picom_class), picom_class));
|
||||||
|
if (e) {
|
||||||
|
log_error_x_error(e, "Failed to set the WM_CLASS property");
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set WM_CLIENT_MACHINE. As per EWMH, because we set _NET_WM_PID, we must also
|
||||||
|
// set WM_CLIENT_MACHINE.
|
||||||
|
{
|
||||||
|
char hostname[HOST_NAME_MAX];
|
||||||
|
if (gethostname(hostname, sizeof(hostname)) == 0) {
|
||||||
|
e = xcb_request_check(
|
||||||
|
ps->c, xcb_change_property_checked(
|
||||||
|
ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win,
|
||||||
|
ps->atoms->aWM_CLIENT_MACHINE, XCB_ATOM_STRING, 8,
|
||||||
|
(uint32_t)strlen(hostname), hostname));
|
||||||
|
if (e) {
|
||||||
|
log_error_x_error(e, "Failed to set the WM_CLIENT_MACHINE"
|
||||||
|
" property");
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log_error_errno("Failed to get hostname");
|
||||||
}
|
}
|
||||||
Xutf8SetWMProperties(ps->dpy, ps->reg_win, "picom", "picom", NULL, 0,
|
|
||||||
NULL, NULL, h);
|
|
||||||
XFree(h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set _NET_WM_PID
|
// Set _NET_WM_PID
|
||||||
|
@ -997,8 +1039,9 @@ static int register_cm(session_t *ps) {
|
||||||
* Write PID to a file.
|
* Write PID to a file.
|
||||||
*/
|
*/
|
||||||
static inline bool write_pid(session_t *ps) {
|
static inline bool write_pid(session_t *ps) {
|
||||||
if (!ps->o.write_pid_path)
|
if (!ps->o.write_pid_path) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
FILE *f = fopen(ps->o.write_pid_path, "w");
|
FILE *f = fopen(ps->o.write_pid_path, "w");
|
||||||
if (unlikely(!f)) {
|
if (unlikely(!f)) {
|
||||||
|
|
|
@ -1054,7 +1054,7 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
glXWaitX();
|
glXWaitX();
|
||||||
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0, ps->root_width,
|
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0, ps->root_width,
|
||||||
ps->root_height, 0, 1.0, false, false, ®ion, NULL);
|
ps->root_height, 0, 1.0, false, false, ®ion, NULL);
|
||||||
// falls through
|
fallthrough();
|
||||||
case BKEND_GLX: glXSwapBuffers(ps->dpy, get_tgt_window(ps)); break;
|
case BKEND_GLX: glXSwapBuffers(ps->dpy, get_tgt_window(ps)); break;
|
||||||
#endif
|
#endif
|
||||||
default: assert(0);
|
default: assert(0);
|
||||||
|
|
29
src/win.c
29
src/win.c
|
@ -535,28 +535,20 @@ static bool attr_pure win_has_rounded_corners(const struct managed_win *w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int win_update_name(session_t *ps, struct managed_win *w) {
|
int win_update_name(session_t *ps, struct managed_win *w) {
|
||||||
XTextProperty text_prop = {NULL, XCB_NONE, 0, 0};
|
|
||||||
char **strlst = NULL;
|
char **strlst = NULL;
|
||||||
int nstr = 0;
|
int nstr = 0;
|
||||||
|
|
||||||
if (!w->client_win)
|
if (!w->client_win) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(wid_get_text_prop(ps, w->client_win, ps->atoms->a_NET_WM_NAME, &strlst, &nstr))) {
|
if (!(wid_get_text_prop(ps, w->client_win, ps->atoms->a_NET_WM_NAME, &strlst, &nstr))) {
|
||||||
log_trace("(%#010x): _NET_WM_NAME unset, falling back to WM_NAME.",
|
log_trace("(%#010x): _NET_WM_NAME unset, falling back to WM_NAME.",
|
||||||
w->client_win);
|
w->client_win);
|
||||||
|
|
||||||
if (!(XGetWMName(ps->dpy, w->client_win, &text_prop) && text_prop.value)) {
|
if (!wid_get_text_prop(ps, w->client_win, ps->atoms->aWM_NAME, &strlst, &nstr)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, &strlst, &nstr) ||
|
|
||||||
!nstr || !strlst) {
|
|
||||||
if (strlst)
|
|
||||||
XFreeStringList(strlst);
|
|
||||||
XFree(text_prop.value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
XFree(text_prop.value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -566,7 +558,7 @@ int win_update_name(session_t *ps, struct managed_win *w) {
|
||||||
w->name = strdup(strlst[0]);
|
w->name = strdup(strlst[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFreeStringList(strlst);
|
free(strlst);
|
||||||
|
|
||||||
log_trace("(%#010x): client = %#010x, name = \"%s\", "
|
log_trace("(%#010x): client = %#010x, name = \"%s\", "
|
||||||
"ret = %d",
|
"ret = %d",
|
||||||
|
@ -578,8 +570,9 @@ static int win_update_role(session_t *ps, struct managed_win *w) {
|
||||||
char **strlst = NULL;
|
char **strlst = NULL;
|
||||||
int nstr = 0;
|
int nstr = 0;
|
||||||
|
|
||||||
if (!wid_get_text_prop(ps, w->client_win, ps->atoms->aWM_WINDOW_ROLE, &strlst, &nstr))
|
if (!wid_get_text_prop(ps, w->client_win, ps->atoms->aWM_WINDOW_ROLE, &strlst, &nstr)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (!w->role || strcmp(w->role, strlst[0]) != 0) {
|
if (!w->role || strcmp(w->role, strlst[0]) != 0) {
|
||||||
|
@ -588,7 +581,7 @@ static int win_update_role(session_t *ps, struct managed_win *w) {
|
||||||
w->role = strdup(strlst[0]);
|
w->role = strdup(strlst[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFreeStringList(strlst);
|
free(strlst);
|
||||||
|
|
||||||
log_trace("(%#010x): client = %#010x, role = \"%s\", "
|
log_trace("(%#010x): client = %#010x, role = \"%s\", "
|
||||||
"ret = %d",
|
"ret = %d",
|
||||||
|
@ -1577,16 +1570,18 @@ bool win_update_class(session_t *ps, struct managed_win *w) {
|
||||||
w->class_general = NULL;
|
w->class_general = NULL;
|
||||||
|
|
||||||
// Retrieve the property string list
|
// Retrieve the property string list
|
||||||
if (!wid_get_text_prop(ps, w->client_win, ps->atoms->aWM_CLASS, &strlst, &nstr))
|
if (!wid_get_text_prop(ps, w->client_win, ps->atoms->aWM_CLASS, &strlst, &nstr)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy the strings if successful
|
// Copy the strings if successful
|
||||||
w->class_instance = strdup(strlst[0]);
|
w->class_instance = strdup(strlst[0]);
|
||||||
|
|
||||||
if (nstr > 1)
|
if (nstr > 1) {
|
||||||
w->class_general = strdup(strlst[1]);
|
w->class_general = strdup(strlst[1]);
|
||||||
|
}
|
||||||
|
|
||||||
XFreeStringList(strlst);
|
free(strlst);
|
||||||
|
|
||||||
log_trace("(%#010x): client = %#010x, "
|
log_trace("(%#010x): client = %#010x, "
|
||||||
"instance = \"%s\", general = \"%s\"",
|
"instance = \"%s\", general = \"%s\"",
|
||||||
|
|
106
src/x.c
106
src/x.c
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
|
#include <stdalign.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -93,21 +94,79 @@ xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t apr
|
||||||
*/
|
*/
|
||||||
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
|
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
|
||||||
int *pnstr) {
|
int *pnstr) {
|
||||||
XTextProperty text_prop = {NULL, XCB_NONE, 0, 0};
|
assert(ps->server_grabbed);
|
||||||
|
xcb_generic_error_t *e = NULL;
|
||||||
if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value))
|
auto r = xcb_get_property_reply(
|
||||||
return false;
|
ps->c, xcb_get_property(ps->c, 0, wid, prop, XCB_ATOM_ANY, 0, 0), &e);
|
||||||
|
if (!r) {
|
||||||
if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr) ||
|
log_debug_x_error(e, "Failed to get window property for %#010x", wid);
|
||||||
!*pnstr) {
|
free(e);
|
||||||
*pnstr = 0;
|
|
||||||
if (*pstrlst)
|
|
||||||
XFreeStringList(*pstrlst);
|
|
||||||
XFree(text_prop.value);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(text_prop.value);
|
auto type = r->type;
|
||||||
|
auto format = r->format;
|
||||||
|
auto length = r->bytes_after;
|
||||||
|
free(r);
|
||||||
|
|
||||||
|
if (type == XCB_ATOM_NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != XCB_ATOM_STRING && type != ps->atoms->aUTF8_STRING &&
|
||||||
|
type != ps->atoms->aC_STRING) {
|
||||||
|
log_warn("Text property %d of window %#010x has unsupported type: %d",
|
||||||
|
prop, wid, type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != 8) {
|
||||||
|
log_warn("Text property %d of window %#010x has unexpected format: %d",
|
||||||
|
prop, wid, format);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = xcb_get_property_reply(
|
||||||
|
ps->c, xcb_get_property(ps->c, 0, wid, prop, type, 0, length), &e);
|
||||||
|
if (!r) {
|
||||||
|
log_debug_x_error(e, "Failed to get window property for %#010x", wid);
|
||||||
|
free(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(length == (uint32_t)xcb_get_property_value_length(r));
|
||||||
|
|
||||||
|
void *data = xcb_get_property_value(r);
|
||||||
|
unsigned int nstr = 0;
|
||||||
|
uint32_t current_offset = 0;
|
||||||
|
while (current_offset < length) {
|
||||||
|
current_offset +=
|
||||||
|
(uint32_t)strnlen(data + current_offset, length - current_offset) + 1;
|
||||||
|
nstr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the pointers and the strings together
|
||||||
|
void *buf = NULL;
|
||||||
|
if (posix_memalign(&buf, alignof(char *), length + sizeof(char *) * nstr + 1) != 0) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strlst = buf + sizeof(char *) * nstr;
|
||||||
|
memcpy(strlst, xcb_get_property_value(r), length);
|
||||||
|
strlst[length] = '\0'; // X strings aren't guaranteed to be null terminated
|
||||||
|
|
||||||
|
char **ret = buf;
|
||||||
|
current_offset = 0;
|
||||||
|
nstr = 0;
|
||||||
|
while (current_offset < length) {
|
||||||
|
ret[nstr] = strlst + current_offset;
|
||||||
|
current_offset += (uint32_t)strlen(strlst + current_offset) + 1;
|
||||||
|
nstr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pnstr = to_int_checked(nstr);
|
||||||
|
*pstrlst = ret;
|
||||||
|
free(r);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +175,9 @@ bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char **
|
||||||
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 =
|
||||||
|
@ -261,8 +321,9 @@ x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int w, int
|
||||||
uint8_t depth = pictfmt->depth;
|
uint8_t depth = pictfmt->depth;
|
||||||
|
|
||||||
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, w, h);
|
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, w, h);
|
||||||
if (!tmp_pixmap)
|
if (!tmp_pixmap) {
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap(
|
xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap(
|
||||||
c, pictfmt, tmp_pixmap, valuemask, attr);
|
c, pictfmt, tmp_pixmap, valuemask, attr);
|
||||||
|
@ -310,13 +371,14 @@ void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
|
||||||
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 = to_i16_checked(rects[i].x1),
|
.x = to_i16_checked(rects[i].x1),
|
||||||
.y = to_i16_checked(rects[i].y1),
|
.y = to_i16_checked(rects[i].y1),
|
||||||
.width = to_u16_checked(rects[i].x2 - rects[i].x1),
|
.width = to_u16_checked(rects[i].x2 - rects[i].x1),
|
||||||
.height = to_u16_checked(rects[i].y2 - rects[i].y1),
|
.height = to_u16_checked(rects[i].y2 - rects[i].y1),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
xcb_generic_error_t *e = xcb_request_check(
|
xcb_generic_error_t *e = xcb_request_check(
|
||||||
c, xcb_render_set_picture_clip_rectangles_checked(
|
c, xcb_render_set_picture_clip_rectangles_checked(
|
||||||
|
@ -326,7 +388,6 @@ void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
|
||||||
free(e);
|
free(e);
|
||||||
}
|
}
|
||||||
free(xrects);
|
free(xrects);
|
||||||
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) {
|
||||||
|
@ -337,7 +398,6 @@ void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict)
|
||||||
log_error_x_error(e, "failed to clear clip region");
|
log_error_x_error(e, "failed to clear clip region");
|
||||||
free(e);
|
free(e);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { XSyncBadCounter = 0,
|
enum { XSyncBadCounter = 0,
|
||||||
|
@ -469,8 +529,9 @@ xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t
|
||||||
xcb_void_cookie_t cookie = xcb_create_pixmap_checked(
|
xcb_void_cookie_t cookie = xcb_create_pixmap_checked(
|
||||||
c, depth, pix, drawable, to_u16_checked(width), to_u16_checked(height));
|
c, depth, pix, drawable, to_u16_checked(width), to_u16_checked(height));
|
||||||
xcb_generic_error_t *err = xcb_request_check(c, cookie);
|
xcb_generic_error_t *err = xcb_request_check(c, cookie);
|
||||||
if (err == NULL)
|
if (err == NULL) {
|
||||||
return pix;
|
return pix;
|
||||||
|
}
|
||||||
|
|
||||||
log_error_x_error(err, "Failed to create pixmap");
|
log_error_x_error(err, "Failed to create pixmap");
|
||||||
free(err);
|
free(err);
|
||||||
|
@ -526,8 +587,9 @@ xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) {
|
||||||
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->atoms, background_props_str[p]);
|
xcb_atom_t prop_atom = get_atom(ps->atoms, background_props_str[p]);
|
||||||
if (prop_atom == atom)
|
if (prop_atom == atom) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -651,9 +713,11 @@ xcb_screen_t *x_screen_of_display(xcb_connection_t *c, int screen) {
|
||||||
xcb_screen_iterator_t iter;
|
xcb_screen_iterator_t iter;
|
||||||
|
|
||||||
iter = xcb_setup_roots_iterator(xcb_get_setup(c));
|
iter = xcb_setup_roots_iterator(xcb_get_setup(c));
|
||||||
for (; iter.rem; --screen, xcb_screen_next(&iter))
|
for (; iter.rem; --screen, xcb_screen_next(&iter)) {
|
||||||
if (screen == 0)
|
if (screen == 0) {
|
||||||
return iter.data;
|
return iter.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
6
src/x.h
6
src/x.h
|
@ -73,6 +73,8 @@ struct xvisual_info {
|
||||||
__r; \
|
__r; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define log_debug_x_error(e, fmt, ...) \
|
||||||
|
LOG(DEBUG, fmt " (%s)", ##__VA_ARGS__, x_strerror(e))
|
||||||
#define log_error_x_error(e, fmt, ...) \
|
#define log_error_x_error(e, fmt, ...) \
|
||||||
LOG(ERROR, fmt " (%s)", ##__VA_ARGS__, x_strerror(e))
|
LOG(ERROR, fmt " (%s)", ##__VA_ARGS__, x_strerror(e))
|
||||||
#define log_fatal_x_error(e, fmt, ...) \
|
#define log_fatal_x_error(e, fmt, ...) \
|
||||||
|
@ -145,6 +147,10 @@ xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t apr
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of a text property of a window.
|
* Get the value of a text property of a window.
|
||||||
|
*
|
||||||
|
* @param[out] pstrlst Out parameter for an array of strings, caller needs to free this
|
||||||
|
* array
|
||||||
|
* @param[out] pnstr Number of strings in the array
|
||||||
*/
|
*/
|
||||||
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
|
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
|
||||||
int *pnstr);
|
int *pnstr);
|
||||||
|
|
Loading…
Reference in New Issue