diff --git a/common.h b/common.h index f8531bcbd..469f8f1ae 100644 --- a/common.h +++ b/common.h @@ -60,6 +60,10 @@ #error Cannot enable c2 debugging without c2 support. #endif +#ifndef COMPTON_VERSION +#define COMPTON_VERSION "unknown" +#endif + // === Includes === // For some special functions @@ -132,6 +136,12 @@ #define MSTR_(s) #s #define MSTR(s) MSTR_(s) +/// @brief Wrapper for gcc branch prediction builtin, for likely branch. +#define likely(x) __builtin_expect(!!(x), 1) + +/// @brief Wrapper for gcc branch prediction builtin, for unlikely branch. +#define unlikely(x) __builtin_expect(!!(x), 0) + /// Print out an error message. #define printf_err(format, ...) \ fprintf(stderr, format "\n", ## __VA_ARGS__) @@ -431,9 +441,13 @@ typedef struct { // === General === /// The configuration file we used. char *config_file; + /// Path to write PID to. + char *write_pid_path; /// The display name we used. NULL means we are using the value of the /// DISPLAY environment variable. char *display; + /// Safe representation of display name. + char *display_repr; /// The backend in use. enum backend backend; /// Whether to avoid using stencil buffer under GLX backend. Might be @@ -986,7 +1000,7 @@ typedef struct _win { /// _NET_WM_OPACITY value opacity_t opacity_prop_client; /// Last window opacity value we set. - long opacity_set; + opacity_t opacity_set; // Fading-related members /// Do not fade if it's false. Change on window type change. @@ -1150,6 +1164,15 @@ allocchk_(const char *func_name, void *ptr) { /// @brief Wrapper of allocchk_(). #define allocchk(ptr) allocchk_(__func__, ptr) +/// @brief Wrapper of malloc(). +#define cmalloc(nmemb, type) ((type *) allocchk(malloc((nmemb) * sizeof(type)))) + +/// @brief Wrapper of calloc(). +#define ccalloc(nmemb, type) ((type *) allocchk(calloc((nmemb), sizeof(type)))) + +/// @brief Wrapper of ealloc(). +#define crealloc(ptr, nmemb, type) ((type *) allocchk(realloc((ptr), (nmemb) * sizeof(type)))) + /** * Return whether a struct timeval value is empty. */ @@ -1310,10 +1333,7 @@ print_timestamp(session_t *ps) { */ static inline char * mstrcpy(const char *src) { - char *str = malloc(sizeof(char) * (strlen(src) + 1)); - - if (!str) - printf_errfq(1, "(): Failed to allocate memory."); + char *str = cmalloc(strlen(src) + 1, char); strcpy(str, src); @@ -1325,10 +1345,7 @@ mstrcpy(const char *src) { */ static inline char * mstrncpy(const char *src, unsigned len) { - char *str = malloc(sizeof(char) * (len + 1)); - - if (!str) - printf_errfq(1, "(): Failed to allocate memory."); + char *str = cmalloc(len + 1, char); strncpy(str, src, len); str[len] = '\0'; @@ -1341,7 +1358,7 @@ mstrncpy(const char *src, unsigned len) { */ static inline char * mstrjoin(const char *src1, const char *src2) { - char *str = malloc(sizeof(char) * (strlen(src1) + strlen(src2) + 1)); + char *str = cmalloc(strlen(src1) + strlen(src2) + 1, char); strcpy(str, src1); strcat(str, src2); @@ -1354,8 +1371,8 @@ mstrjoin(const char *src1, const char *src2) { */ static inline char * mstrjoin3(const char *src1, const char *src2, const char *src3) { - char *str = malloc(sizeof(char) * (strlen(src1) + strlen(src2) - + strlen(src3) + 1)); + char *str = cmalloc(strlen(src1) + strlen(src2) + + strlen(src3) + 1, char); strcpy(str, src1); strcat(str, src2); @@ -1369,7 +1386,8 @@ mstrjoin3(const char *src1, const char *src2, const char *src3) { */ static inline void mstrextend(char **psrc1, const char *src2) { - *psrc1 = realloc(*psrc1, (*psrc1 ? strlen(*psrc1): 0) + strlen(src2) + 1); + *psrc1 = crealloc(*psrc1, (*psrc1 ? strlen(*psrc1): 0) + strlen(src2) + 1, + char); strcat(*psrc1, src2); } diff --git a/compton.c b/compton.c index 0c9855281..770721596 100644 --- a/compton.c +++ b/compton.c @@ -1571,7 +1571,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, } } - double dopacity = get_opacity_percent(w);; + double dopacity = get_opacity_percent(w); if (!w->frame_opacity) { win_render(ps, w, 0, 0, wid, hei, dopacity, reg_paint, pcache_reg, pict); @@ -4309,6 +4309,8 @@ usage(int ret) { " Enable synchronous operation (for debugging).\n" "--config path\n" " Look for configuration file at the path.\n" + "--write-pid-path path\n" + " Write process ID to a file.\n" "--shadow-red value\n" " Red color value of shadow (0.0 - 1.0, defaults to 0).\n" "--shadow-green value\n" @@ -4584,7 +4586,7 @@ ostream_reopen(session_t *ps, const char *path) { /** * Fork program to background and disable all I/O streams. */ -static bool +static inline bool fork_after(session_t *ps) { if (getppid() == 1) return true; @@ -4627,6 +4629,26 @@ fork_after(session_t *ps) { return success; } +/** + * Write PID to a file. + */ +static inline bool +write_pid(session_t *ps) { + if (!ps->o.write_pid_path) + return true; + + FILE *f = fopen(ps->o.write_pid_path, "w"); + if (unlikely(!f)) { + printf_errf("(): Failed to write PID to \"%s\".", ps->o.write_pid_path); + return false; + } + + fprintf(f, "%ld\n", (long) getpid()); + fclose(f); + + return true; +} + /** * Parse a long number. */ @@ -5360,6 +5382,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { { "xinerama-shadow-crop", no_argument, NULL, 307 }, { "unredir-if-possible-exclude", required_argument, NULL, 308 }, { "unredir-if-possible-delay", required_argument, NULL, 309 }, + { "write-pid-path", required_argument, NULL, 310 }, // Must terminate with a NULL entry { NULL, 0, NULL, 0 }, }; @@ -5603,6 +5626,10 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { condlst_add(ps, &ps->o.unredir_if_possible_blacklist, optarg); break; P_CASELONG(309, unredir_if_possible_delay); + case 310: + // --write-pid-path + ps->o.write_pid_path = mstrcpy(optarg); + break; default: usage(1); break; @@ -6800,6 +6827,27 @@ session_init(session_t *ps_old, int argc, char **argv) { ps->shape_exists = true; } + // Build a safe representation of display name + { + char *display_repr = DisplayString(ps->dpy); + if (!display_repr) + display_repr = "unknown"; + display_repr = mstrcpy(display_repr); + + // Convert all special characters in display_repr name to underscore + { + char *pdisp = display_repr; + + while (*pdisp) { + if (!isalnum(*pdisp)) + *pdisp = '_'; + ++pdisp; + } + } + + ps->o.display_repr = display_repr; + } + // Second pass get_cfg(ps, argc, argv, false); @@ -6974,6 +7022,8 @@ session_init(session_t *ps_old, int argc, char **argv) { } } + write_pid(ps); + // Free the old session if (ps_old) free(ps_old); @@ -7099,9 +7149,12 @@ session_destroy(session_t *ps) { free(ps->shadow_corner); free(ps->shadow_top); free(ps->gaussian_map); + + free(ps->o.config_file); + free(ps->o.write_pid_path); free(ps->o.display); + free(ps->o.display_repr); free(ps->o.logpath); - free(ps->o.config_file); for (int i = 0; i < MAX_BLUR_PASS; ++i) { free(ps->o.blur_kerns[i]); free(ps->blur_kerns_cache[i]); diff --git a/dbus.c b/dbus.c index 1d20a061a..8aec9ea82 100644 --- a/dbus.c +++ b/dbus.c @@ -39,30 +39,10 @@ cdbus_init(session_t *ps) { // Request service name { - // Get display name - char *display = DisplayString(ps->dpy); - if (!display) - display = "unknown"; - display = mstrcpy(display); - - // Convert all special characters in display name to underscore - { - char *pdisp = display; - - while (*pdisp) { - if (!isalnum(*pdisp)) - *pdisp = '_'; - ++pdisp; - } - } - // Build service name - char *service = mstrjoin3(CDBUS_SERVICE_NAME, ".", display); + char *service = mstrjoin3(CDBUS_SERVICE_NAME, ".", ps->o.display_repr); ps->dbus_service = service; - free(display); - display = NULL; - // Request for the name int ret = dbus_bus_request_name(ps->dbus_conn, service, DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); @@ -735,7 +715,13 @@ cdbus_process_win_get(session_t *ps, DBusMessage *msg) { cdbus_m_win_get_do(class_instance, cdbus_reply_string); cdbus_m_win_get_do(class_general, cdbus_reply_string); cdbus_m_win_get_do(role, cdbus_reply_string); + cdbus_m_win_get_do(opacity, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity_tgt, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity_prop_client, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity_set, cdbus_reply_uint32); + cdbus_m_win_get_do(frame_opacity, cdbus_reply_double); cdbus_m_win_get_do(left_width, cdbus_reply_uint32); cdbus_m_win_get_do(right_width, cdbus_reply_uint32); @@ -889,6 +875,18 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { return true; \ } + // version + if (!strcmp("version", target)) { + cdbus_reply_string(ps, msg, COMPTON_VERSION); + return true; + } + + // pid + if (!strcmp("pid", target)) { + cdbus_reply_int32(ps, msg, getpid()); + return true; + } + // display if (!strcmp("display", target)) { cdbus_reply_string(ps, msg, DisplayString(ps->dpy)); @@ -896,6 +894,8 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { } cdbus_m_opts_get_do(config_file, cdbus_reply_string); + cdbus_m_opts_get_do(display_repr, cdbus_reply_string); + cdbus_m_opts_get_do(write_pid_path, cdbus_reply_string); cdbus_m_opts_get_do(mark_wmwin_focused, cdbus_reply_bool); cdbus_m_opts_get_do(mark_ovredir_focused, cdbus_reply_bool); cdbus_m_opts_get_do(fork_after_register, cdbus_reply_bool); diff --git a/dbus.h b/dbus.h index 50770d63c..a806c2de9 100644 --- a/dbus.h +++ b/dbus.h @@ -10,6 +10,8 @@ #include "common.h" #include +#include +#include #define CDBUS_SERVICE_NAME "com.github.chjj.compton" #define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME