diff options
| author | allusive-dev <[email protected]> | 2023-09-19 17:47:33 +1000 |
|---|---|---|
| committer | allusive-dev <[email protected]> | 2023-09-19 17:47:33 +1000 |
| commit | a93aba600b1c5d019b680b9f4ff3fa85d5d43a60 (patch) | |
| tree | 77f8152222655657472a70e0bfa413a0495dd555 /src/common.h | |
| parent | reset (diff) | |
| download | compfy-a93aba600b1c5d019b680b9f4ff3fa85d5d43a60.tar.xz compfy-a93aba600b1c5d019b680b9f4ff3fa85d5d43a60.zip | |
Fixed broken files/code and other errors
Diffstat (limited to 'src/common.h')
| -rw-r--r-- | src/common.h | 541 |
1 files changed, 541 insertions, 0 deletions
diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..b7f2fe0 --- /dev/null +++ b/src/common.h @@ -0,0 +1,541 @@ +// SPDX-License-Identifier: MIT +/* + * Compton - a compositor for X11 + * + * Based on `xcompmgr` - Copyright (c) 2003, Keith Packard + * + * Copyright (c) 2011-2013, Christopher Jeffrey + * Copyright (c) 2018, Yuxuan Shui <[email protected]> + * + * See LICENSE-mit for more information. + * + */ + +#pragma once + +// === Options === + +// Debug options, enable them using -D in CFLAGS +// #define DEBUG_REPAINT 1 +// #define DEBUG_EVENTS 1 +// #define DEBUG_RESTACK 1 +// #define DEBUG_WINMATCH 1 +// #define DEBUG_C2 1 +// #define DEBUG_GLX_DEBUG_CONTEXT 1 + +#define MAX_ALPHA (255) + +// === Includes === + +// For some special functions +#include <assert.h> +#include <stdbool.h> +#include <sys/time.h> +#include <time.h> + +#include <X11/Xlib.h> +#include <ev.h> +#include <pixman.h> +#include <xcb/xproto.h> +#include <xcb/render.h> +#include <xcb/sync.h> + +#include "uthash_extra.h" +#ifdef CONFIG_OPENGL +#include "backend/gl/glx.h" +#endif + +// X resource checker +#ifdef DEBUG_XRC +#include "xrescheck.h" +#endif + +// FIXME This list of includes should get shorter +#include "backend/backend.h" +#include "backend/driver.h" +#include "compiler.h" +#include "config.h" +#include "region.h" +#include "types.h" +#include "utils.h" +#include "list.h" +#include "render.h" +#include "win_defs.h" +#include "x.h" + +// === Constants ===0 + +#define NS_PER_SEC 1000000000L +#define US_PER_SEC 1000000L +#define MS_PER_SEC 1000 + +/// @brief Maximum OpenGL FBConfig depth. +#define OPENGL_MAX_DEPTH 32 + +/// @brief Maximum OpenGL buffer age. +#define CGLX_MAX_BUFFER_AGE 5 + +// Window flags + +// === Types === +typedef struct glx_fbconfig glx_fbconfig_t; +struct glx_session; +struct atom; +struct conv; + +typedef struct _ignore { + struct _ignore *next; + unsigned long sequence; +} ignore_t; + +#ifdef CONFIG_OPENGL +#ifdef DEBUG_GLX_DEBUG_CONTEXT +typedef GLXContext (*f_glXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config, + GLXContext share_context, Bool direct, + const int *attrib_list); +typedef void (*GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar *message, GLvoid *userParam); +typedef void (*f_DebugMessageCallback)(GLDEBUGPROC, void *userParam); +#endif + +typedef struct glx_prog_main { + /// GLSL program. + GLuint prog; + /// Location of uniform "opacity" in window GLSL program. + GLint unifm_opacity; + /// Location of uniform "invert_color" in blur GLSL program. + GLint unifm_invert_color; + /// Location of uniform "tex" in window GLSL program. + GLint unifm_tex; + /// Location of uniform "time" in window GLSL program. + GLint unifm_time; +} glx_prog_main_t; + +#define GLX_PROG_MAIN_INIT \ + { \ + .prog = 0, .unifm_opacity = -1, .unifm_invert_color = -1, \ + .unifm_tex = -1, .unifm_time = -1 \ + } + +#else +struct glx_prog_main {}; +#endif + +#define PAINT_INIT \ + { .pixmap = XCB_NONE, .pict = XCB_NONE } + +/// Linked list type of atoms. +typedef struct _latom { + xcb_atom_t atom; + struct _latom *next; +} latom_t; + +/// Structure containing all necessary data for a session. +typedef struct session { + // === Event handlers === + /// ev_io for X connection + ev_io xiow; + /// Timeout for delayed unredirection. + ev_timer unredir_timer; + /// Timer for fading + ev_timer fade_timer; + /// Timer for animations + ev_timer animation_timer; + /// Timer for delayed drawing, right now only used by + /// swopti + ev_timer delayed_draw_timer; + /// Use an ev_idle callback for drawing + /// So we only start drawing when events are processed + ev_idle draw_idle; + /// Called everytime we have timeouts or new data on socket, + /// so we can be sure if xcb read from X socket at anytime during event + /// handling, we will not left any event unhandled in the queue + ev_prepare event_check; + /// Signal handler for SIGUSR1 + ev_signal usr1_signal; + /// Signal handler for SIGINT + ev_signal int_signal; + /// backend data + backend_t *backend_data; + /// backend blur context + void *backend_blur_context; + /// graphic drivers used + enum driver drivers; + /// file watch handle + void *file_watch_handle; + /// libev mainloop + struct ev_loop *loop; + + // === Display related === + /// Whether the X server is grabbed by us + bool server_grabbed; + /// Display in use. + Display *dpy; + /// Previous handler of X errors + XErrorHandler previous_xerror_handler; + /// Default screen. + int scr; + /// XCB connection. + xcb_connection_t *c; + /// Default visual. + xcb_visualid_t vis; + /// Default depth. + int depth; + /// Root window. + xcb_window_t root; + /// Height of root window. + int root_height; + /// Width of root window. + int root_width; + /// Current desktop number of root window + int root_desktop_num; + /// Desktop switch direction + int root_desktop_switch_direction; + // Damage of root window. + // Damage root_damage; + /// X Composite overlay window. Used if <code>--paint-on-overlay</code>. + xcb_window_t overlay; + /// The target window for debug mode + xcb_window_t debug_window; + /// Whether the root tile is filled by us. + bool root_tile_fill; + /// Picture of the root window background. + paint_t root_tile_paint; + /// The backend data the root pixmap bound to + void *root_image; + /// A region of the size of the screen. + region_t screen_reg; + /// Picture of root window. Destination of painting in no-DBE painting + /// mode. + xcb_render_picture_t root_picture; + /// A Picture acting as the painting target. + xcb_render_picture_t tgt_picture; + /// Temporary buffer to paint to before sending to display. + paint_t tgt_buffer; + /// Window ID of the window we register as a symbol. + xcb_window_t reg_win; +#ifdef CONFIG_OPENGL + /// Pointer to GLX data. + struct glx_session *psglx; + /// Custom GLX program used for painting window. + // XXX should be in struct glx_session + glx_prog_main_t glx_prog_win; + struct glx_fbconfig_info *argb_fbconfig; +#endif + /// Sync fence to sync draw operations + xcb_sync_fence_t sync_fence; + /// Whether we are rendering the first frame after screen is redirected + bool first_frame; + + // === Operation related === + /// Flags related to the root window + uint64_t root_flags; + /// Program options. + options_t o; + /// Whether we have hit unredirection timeout. + bool tmout_unredir_hit; + /// Whether we need to redraw the screen + bool redraw_needed; + + /// Cache a xfixes region so we don't need to allocate it everytime. + /// A workaround for yshui/picom#301 + xcb_xfixes_region_t damaged_region; + /// The region needs to painted on next paint. + region_t *damage; + /// The region damaged on the last paint. + region_t *damage_ring; + /// Number of damage regions we track + int ndamage; + /// Whether all windows are currently redirected. + bool redirected; + /// Pre-generated alpha pictures. + xcb_render_picture_t *alpha_picts; + /// Time of last fading. In milliseconds. + long fade_time; + /// Time of last window animation step. In milliseconds. + long animation_time; + /// Head pointer of the error ignore linked list. + ignore_t *ignore_head; + /// Pointer to the <code>next</code> member of tail element of the error + /// ignore linked list. + ignore_t **ignore_tail; + // Cached blur convolution kernels. + struct x_convolution_kernel **blur_kerns_cache; + /// If we should quit + bool quit:1; + // TODO(yshui) use separate flags for dfferent kinds of updates so we don't + // waste our time. + /// Whether there are pending updates, like window creation, etc. + bool pending_updates:1; + + // === Expose event related === + /// Pointer to an array of <code>XRectangle</code>-s of exposed region. + /// XXX why do we need this array? + rect_t *expose_rects; + /// Number of <code>XRectangle</code>-s in <code>expose_rects</code>. + int size_expose; + /// Index of the next free slot in <code>expose_rects</code>. + int n_expose; + + // === Window related === + /// A hash table of all windows. + struct win *windows; + /// Windows in their stacking order + struct list_node window_stack; + /// Pointer to <code>win</code> of current active window. Used by + /// EWMH <code>_NET_ACTIVE_WINDOW</code> focus detection. In theory, + /// it's more reliable to store the window ID directly here, just in + /// case the WM does something extraordinary, but caching the pointer + /// means another layer of complexity. + struct managed_win *active_win; + /// Window ID of leader window of currently active window. Used for + /// subsidiary window detection. + xcb_window_t active_leader; + + // === Shadow/dimming related === + /// 1x1 black Picture. + xcb_render_picture_t black_picture; + /// 1x1 Picture of the shadow color. + xcb_render_picture_t cshadow_picture; + /// 1x1 white Picture. + xcb_render_picture_t white_picture; + /// Gaussian map of shadow. + struct conv *gaussian_map; + // for shadow precomputation + /// A region in which shadow is not painted on. + region_t shadow_exclude_reg; + + // === Software-optimization-related === + /// Currently used refresh rate. + int refresh_rate; + /// Interval between refresh in nanoseconds. + long refresh_intv; + /// Nanosecond offset of the first painting. + long paint_tm_offset; + +#ifdef CONFIG_VSYNC_DRM + // === DRM VSync related === + /// File descriptor of DRI device file. Used for DRM VSync. + int drm_fd; +#endif + + // === X extension related === + /// Event base number for X Fixes extension. + int xfixes_event; + /// Error base number for X Fixes extension. + int xfixes_error; + /// Event base number for X Damage extension. + int damage_event; + /// Error base number for X Damage extension. + int damage_error; + /// Event base number for X Render extension. + int render_event; + /// Error base number for X Render extension. + int render_error; + /// Event base number for X Composite extension. + int composite_event; + /// Error base number for X Composite extension. + int composite_error; + /// Major opcode for X Composite extension. + int composite_opcode; + /// Whether X Shape extension exists. + bool shape_exists; + /// Event base number for X Shape extension. + int shape_event; + /// Error base number for X Shape extension. + int shape_error; + /// Whether X RandR extension exists. + bool randr_exists; + /// Event base number for X RandR extension. + int randr_event; + /// Error base number for X RandR extension. + int randr_error; + /// Whether X Present extension exists. + bool present_exists; + /// Whether X GLX extension exists. + bool glx_exists; + /// Event base number for X GLX extension. + int glx_event; + /// Error base number for X GLX extension. + int glx_error; + /// Whether X Xinerama extension exists. + bool xinerama_exists; + /// Xinerama screen regions. + region_t *xinerama_scr_regs; + /// Number of Xinerama screens. + int xinerama_nscrs; + /// Whether X Sync extension exists. + bool xsync_exists; + /// Event base number for X Sync extension. + int xsync_event; + /// Error base number for X Sync extension. + int xsync_error; + /// Whether X Render convolution filter exists. + bool xrfilter_convolution_exists; + + // === Atoms === + struct atom *atoms; + /// Array of atoms of all possible window types. + xcb_atom_t atoms_wintypes[NUM_WINTYPES]; + /// Linked list of additional atoms to track. + latom_t *track_atom_lst; + +#ifdef CONFIG_DBUS + // === DBus related === + void *dbus_data; +#endif + + int (*vsync_wait)(session_t *); +} session_t; + +/// Enumeration for window event hints. +typedef enum { WIN_EVMODE_UNKNOWN, WIN_EVMODE_FRAME, WIN_EVMODE_CLIENT } win_evmode_t; + +extern const char *const WINTYPES[NUM_WINTYPES]; +extern session_t *ps_g; + +void ev_xcb_error(session_t *ps, xcb_generic_error_t *err); + +// === Functions === + +/** + * Subtracting two struct timespec values. + * + * Taken from glibc manual. + * + * Subtract the `struct timespec' values X and Y, + * storing the result in RESULT. + * Return 1 if the difference is negative, otherwise 0. + */ +static inline int +timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) { + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_nsec < y->tv_nsec) { + long nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1; + y->tv_nsec -= NS_PER_SEC * nsec; + y->tv_sec += nsec; + } + + if (x->tv_nsec - y->tv_nsec > NS_PER_SEC) { + long nsec = (x->tv_nsec - y->tv_nsec) / NS_PER_SEC; + y->tv_nsec += NS_PER_SEC * nsec; + y->tv_sec -= nsec; + } + + /* Compute the time remaining to wait. + tv_nsec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_nsec = x->tv_nsec - y->tv_nsec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + +/** + * Get current time in struct timeval. + */ +static inline struct timeval get_time_timeval(void) { + struct timeval tv = {0, 0}; + + gettimeofday(&tv, NULL); + + // Return a time of all 0 if the call fails + return tv; +} + +/** + * Get current time in struct timespec. + * + * Note its starting time is unspecified. + */ +static inline struct timespec get_time_timespec(void) { + struct timespec tm = {0, 0}; + + clock_gettime(CLOCK_MONOTONIC, &tm); + + // Return a time of all 0 if the call fails + return tm; +} + +/** + * Return the painting target window. + */ +static inline xcb_window_t get_tgt_window(session_t *ps) { + return ps->overlay != XCB_NONE ? ps->overlay : ps->root; +} + +/** + * Check if current backend uses GLX. + */ +static inline bool bkend_use_glx(session_t *ps) { + return BKEND_GLX == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend; +} + +static void set_ignore(session_t *ps, unsigned long sequence) { + if (ps->o.show_all_xerrors) + return; + + auto i = cmalloc(ignore_t); + if (!i) + return; + + i->sequence = sequence; + i->next = 0; + *ps->ignore_tail = i; + ps->ignore_tail = &i->next; +} + +/** + * Ignore X errors caused by given X request. + */ +static inline void set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) { + set_ignore(ps, cookie.sequence); +} + +/** + * Determine if a window has a specific property. + * + * @param ps current session + * @param w window to check + * @param atom atom of property to check + * @return true if it has the attribute, false otherwise + */ +static inline bool wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) { + auto r = xcb_get_property_reply( + ps->c, xcb_get_property(ps->c, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0), NULL); + if (!r) { + return false; + } + + auto rtype = r->type; + free(r); + + if (rtype != XCB_NONE) { + return true; + } + return false; +} + +void force_repaint(session_t *ps); + +/** @name DBus handling + */ +///@{ +#ifdef CONFIG_DBUS +/** @name DBus hooks + */ +///@{ +void opts_set_no_fading_openclose(session_t *ps, bool newval); +//!@} +#endif + +/** + * Set a <code>bool</code> array of all wintypes to true. + */ +static inline void wintype_arr_enable(bool arr[]) { + wintype_t i; + + for (i = 0; i < NUM_WINTYPES; ++i) { + arr[i] = true; + } +} |