aboutsummaryrefslogtreecommitdiff
path: root/src/common.h
diff options
context:
space:
mode:
authorAllusive_ <[email protected]>2023-08-01 09:00:18 +1000
committerGitHub <[email protected]>2023-08-01 09:00:18 +1000
commit0147e7dd165f837662a480938e2083a5ac707586 (patch)
tree3e38624c86c7119703cddb524ac01278491c8a3f /src/common.h
parentAdd files via upload (diff)
downloadcompfy-0147e7dd165f837662a480938e2083a5ac707586.tar.xz
compfy-0147e7dd165f837662a480938e2083a5ac707586.zip
Add files via upload
Diffstat (limited to 'src/common.h')
-rw-r--r--src/common.h541
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;
+ }
+}