From 72a8d9babf1f80f372f25dfd0a23516b3027f2bb Mon Sep 17 00:00:00 2001 From: randomuser Date: Fri, 16 Sep 2022 12:41:52 -0500 Subject: [PATCH] more baseline things --- bspwm.h | 99 ++++++++++++++ helpers.c | 194 +++++++++++++++++++++++++++ types.h | 391 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 684 insertions(+) create mode 100644 bspwm.h create mode 100644 helpers.c create mode 100644 types.h diff --git a/bspwm.h b/bspwm.h new file mode 100644 index 0000000..139d4c3 --- /dev/null +++ b/bspwm.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2012, Bastien Dejean + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BSPWM_BSPWM_H +#define BSPWM_BSPWM_H + +#include "types.h" + +#define WM_NAME "bspwm" +#define CONFIG_NAME WM_NAME "rc" +#define CONFIG_HOME_ENV "XDG_CONFIG_HOME" +#define RUNTIME_DIR_ENV "XDG_RUNTIME_DIR" + +#define STATE_PATH_TPL "/tmp/bspwm%s_%i_%i-state" + +#define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_BUTTON_PRESS) +#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE) +#define BSPWM_CLASS_NAME "Bspwm" +#define META_WINDOW_IC "wm\0" BSPWM_CLASS_NAME +#define ROOT_WINDOW_IC "root\0" BSPWM_CLASS_NAME +#define PRESEL_FEEDBACK_I "presel_feedback" +#define PRESEL_FEEDBACK_IC PRESEL_FEEDBACK_I "\0" BSPWM_CLASS_NAME +#define MOTION_RECORDER_I "motion_recorder" +#define MOTION_RECORDER_IC MOTION_RECORDER_I "\0" BSPWM_CLASS_NAME + +typedef struct { + xcb_window_t id; + uint16_t sequence; + bool enabled; +} motion_recorder_t; + +extern xcb_connection_t *dpy; +extern int default_screen, screen_width, screen_height; +extern uint32_t clients_count; +extern xcb_screen_t *screen; +extern xcb_window_t root; +extern char config_path[MAXLEN]; + +extern monitor_t *mon; +extern monitor_t *mon_head; +extern monitor_t *mon_tail; +extern monitor_t *pri_mon; +extern history_t *history_head; +extern history_t *history_tail; +extern history_t *history_needle; +extern rule_t *rule_head; +extern rule_t *rule_tail; +extern stacking_list_t *stack_head; +extern stacking_list_t *stack_tail; +extern subscriber_list_t *subscribe_head; +extern subscriber_list_t *subscribe_tail; +extern pending_rule_t *pending_rule_head; +extern pending_rule_t *pending_rule_tail; + +extern xcb_window_t meta_window; +extern motion_recorder_t motion_recorder; +extern xcb_atom_t WM_STATE; +extern xcb_atom_t WM_TAKE_FOCUS; +extern xcb_atom_t WM_DELETE_WINDOW; +extern int exit_status; + +extern bool auto_raise; +extern bool sticky_still; +extern bool hide_sticky; +extern bool record_history; +extern bool running; +extern bool restart; +extern bool randr; + +void init(void); +void setup(void); +void register_events(void); +void cleanup(void); +bool check_connection (xcb_connection_t *dpy); +void sig_handler(int sig); +uint32_t get_color_pixel(const char *color); + +#endif diff --git a/helpers.c b/helpers.c new file mode 100644 index 0000000..7e8da5a --- /dev/null +++ b/helpers.c @@ -0,0 +1,194 @@ +/* Copyright (c) 2012, Bastien Dejean + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void warn(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +__attribute__((noreturn)) +void err(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + +char *read_string(const char *file_path, size_t *tlen) +{ + if (file_path == NULL) { + return NULL; + } + + int fd = open(file_path, O_RDONLY); + + if (fd == -1) { + perror("Read file: open"); + return NULL; + } + + char buf[BUFSIZ], *content = NULL; + size_t len = sizeof(buf); + + if ((content = calloc(len, sizeof(char))) == NULL) { + perror("Read file: calloc"); + goto end; + } + + int nb; + *tlen = 0; + + while (true) { + nb = read(fd, buf, sizeof(buf)); + if (nb < 0) { + perror("Restore tree: read"); + free(content); + content = NULL; + goto end; + } else if (nb == 0) { + break; + } else { + *tlen += nb; + if (*tlen > len) { + len *= 2; + char *rcontent = realloc(content, len * sizeof(char)); + if (rcontent == NULL) { + perror("Read file: realloc"); + free(content); + content = NULL; + goto end; + } else { + content = rcontent; + } + } + strncpy(content + (*tlen - nb), buf, nb); + } + } + +end: + close(fd); + return content; +} + +char *copy_string(char *str, size_t len) +{ + char *cpy = calloc(1, ((len+1) * sizeof(char))); + if (cpy == NULL) { + perror("Copy string: calloc"); + return NULL; + } + strncpy(cpy, str, len); + cpy[len] = '\0'; + return cpy; +} + +char *mktempfifo(const char *template) +{ + int tempfd; + char *runtime_dir = getenv(RUNTIME_DIR_ENV); + if (runtime_dir == NULL) { + runtime_dir = "/tmp"; + } + + char *fifo_path = malloc(strlen(runtime_dir)+1+strlen(template)+1); + if (fifo_path == NULL) { + return NULL; + } + + sprintf(fifo_path, "%s/%s", runtime_dir, template); + + if ((tempfd = mkstemp(fifo_path)) == -1) { + free(fifo_path); + return NULL; + } + + close(tempfd); + unlink(fifo_path); + + if (mkfifo(fifo_path, 0666) == -1) { + free(fifo_path); + return NULL; + } + + return fifo_path; +} + +int asprintf(char **buf, const char *fmt, ...) +{ + int size = 0; + va_list args; + va_start(args, fmt); + size = vasprintf(buf, fmt, args); + va_end(args); + return size; +} + +int vasprintf(char **buf, const char *fmt, va_list args) +{ + va_list tmp; + va_copy(tmp, args); + int size = vsnprintf(NULL, 0, fmt, tmp); + va_end(tmp); + + if (size < 0) { + return -1; + } + + *buf = malloc(size + 1); + + if (*buf == NULL) { + return -1; + } + + size = vsprintf(*buf, fmt, args); + return size; +} + +bool is_hex_color(const char *color) +{ + if (color[0] != '#' || strlen(color) != 7) { + return false; + } + for (int i = 1; i < 7; i++) { + if (!isxdigit(color[i])) { + return false; + } + } + return true; +} diff --git a/types.h b/types.h new file mode 100644 index 0000000..c11b591 --- /dev/null +++ b/types.h @@ -0,0 +1,391 @@ +/* Copyright (c) 2012, Bastien Dejean + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BSPWM_TYPES_H +#define BSPWM_TYPES_H +#include +#include +#include +#include +#include +#include "helpers.h" + +#define MISSING_VALUE "N/A" +#define MAX_WM_STATES 4 + +typedef enum { + TYPE_HORIZONTAL, + TYPE_VERTICAL +} split_type_t; + +typedef enum { + MODE_AUTOMATIC, + MODE_MANUAL +} split_mode_t; + +typedef enum { + SCHEME_LONGEST_SIDE, + SCHEME_ALTERNATE, + SCHEME_SPIRAL +} automatic_scheme_t; + +typedef enum { + STATE_TILED, + STATE_PSEUDO_TILED, + STATE_FLOATING, + STATE_FULLSCREEN +} client_state_t; + +typedef enum { + WM_FLAG_MODAL = 1 << 0, + WM_FLAG_STICKY = 1 << 1, + WM_FLAG_MAXIMIZED_VERT = 1 << 2, + WM_FLAG_MAXIMIZED_HORZ = 1 << 3, + WM_FLAG_SHADED = 1 << 4, + WM_FLAG_SKIP_TASKBAR = 1 << 5, + WM_FLAG_SKIP_PAGER = 1 << 6, + WM_FLAG_HIDDEN = 1 << 7, + WM_FLAG_FULLSCREEN = 1 << 8, + WM_FLAG_ABOVE = 1 << 9, + WM_FLAG_BELOW = 1 << 10, + WM_FLAG_DEMANDS_ATTENTION = 1 << 11, +} wm_flags_t; + +typedef enum { + LAYER_BELOW, + LAYER_NORMAL, + LAYER_ABOVE +} stack_layer_t; + +typedef enum { + OPTION_NONE, + OPTION_TRUE, + OPTION_FALSE +} option_bool_t; + +typedef enum { + ALTER_TOGGLE, + ALTER_SET +} alter_state_t; + +typedef enum { + CYCLE_NEXT, + CYCLE_PREV +} cycle_dir_t; + +typedef enum { + CIRCULATE_FORWARD, + CIRCULATE_BACKWARD +} circulate_dir_t; + +typedef enum { + HISTORY_OLDER, + HISTORY_NEWER +} history_dir_t; + +typedef enum { + DIR_NORTH, + DIR_WEST, + DIR_SOUTH, + DIR_EAST +} direction_t; + +typedef enum { + HANDLE_LEFT = 1 << 0, + HANDLE_TOP = 1 << 1, + HANDLE_RIGHT = 1 << 2, + HANDLE_BOTTOM = 1 << 3, + HANDLE_TOP_LEFT = HANDLE_TOP | HANDLE_LEFT, + HANDLE_TOP_RIGHT = HANDLE_TOP | HANDLE_RIGHT, + HANDLE_BOTTOM_RIGHT = HANDLE_BOTTOM | HANDLE_RIGHT, + HANDLE_BOTTOM_LEFT = HANDLE_BOTTOM | HANDLE_LEFT +} resize_handle_t; + +typedef enum { + ACTION_NONE, + ACTION_FOCUS, + ACTION_MOVE, + ACTION_RESIZE_SIDE, + ACTION_RESIZE_CORNER +} pointer_action_t; + +typedef enum { + LAYOUT_TILED, + LAYOUT_MONOCLE +} layout_t; + +typedef enum { + FLIP_HORIZONTAL, + FLIP_VERTICAL +} flip_t; + +typedef enum { + FIRST_CHILD, + SECOND_CHILD +} child_polarity_t; + +typedef enum { + TIGHTNESS_LOW, + TIGHTNESS_HIGH, +} tightness_t; + +typedef enum { + AREA_BIGGEST, + AREA_SMALLEST, +} area_peak_t; + +typedef enum { + STATE_TRANSITION_ENTER = 1 << 0, + STATE_TRANSITION_EXIT = 1 << 1, +} state_transition_t; + +typedef struct { + option_bool_t automatic; + option_bool_t focused; + option_bool_t active; + option_bool_t local; + option_bool_t leaf; + option_bool_t window; + option_bool_t tiled; + option_bool_t pseudo_tiled; + option_bool_t floating; + option_bool_t fullscreen; + option_bool_t hidden; + option_bool_t sticky; + option_bool_t private; + option_bool_t locked; + option_bool_t marked; + option_bool_t urgent; + option_bool_t same_class; + option_bool_t descendant_of; + option_bool_t ancestor_of; + option_bool_t below; + option_bool_t normal; + option_bool_t above; + option_bool_t horizontal; + option_bool_t vertical; +} node_select_t; + +typedef struct { + option_bool_t occupied; + option_bool_t focused; + option_bool_t active; + option_bool_t urgent; + option_bool_t local; + option_bool_t tiled; + option_bool_t monocle; + option_bool_t user_tiled; + option_bool_t user_monocle; +} desktop_select_t; + +typedef struct { + option_bool_t occupied; + option_bool_t focused; +} monitor_select_t; + +typedef struct icccm_props_t icccm_props_t; +struct icccm_props_t { + bool take_focus; + bool input_hint; + bool delete_window; +}; + +typedef struct { + char class_name[MAXLEN]; + char instance_name[MAXLEN]; + char name[MAXLEN]; + unsigned int border_width; + bool urgent; + bool shown; + client_state_t state; + client_state_t last_state; + stack_layer_t layer; + stack_layer_t last_layer; + xcb_rectangle_t floating_rectangle; + xcb_rectangle_t tiled_rectangle; + xcb_size_hints_t size_hints; + icccm_props_t icccm_props; + wm_flags_t wm_flags; +} client_t; + +typedef struct presel_t presel_t; +struct presel_t { + double split_ratio; + direction_t split_dir; + xcb_window_t feedback; +}; + +typedef struct constraints_t constraints_t; +struct constraints_t { + uint16_t min_width; + uint16_t min_height; +}; + +typedef struct node_t node_t; +struct node_t { + uint32_t id; + split_type_t split_type; + double split_ratio; + presel_t *presel; + xcb_rectangle_t rectangle; + constraints_t constraints; + bool vacant; + bool hidden; + bool sticky; + bool private; + bool locked; + bool marked; + node_t *first_child; + node_t *second_child; + node_t *parent; + client_t *client; +}; + +typedef struct padding_t padding_t; +struct padding_t { + int top; + int right; + int bottom; + int left; +}; + +typedef struct desktop_t desktop_t; +struct desktop_t { + char name[SMALEN]; + uint32_t id; + layout_t layout; + layout_t user_layout; + node_t *root; + node_t *focus; + desktop_t *prev; + desktop_t *next; + padding_t padding; + int window_gap; + unsigned int border_width; +}; + +typedef struct monitor_t monitor_t; +struct monitor_t { + char name[SMALEN]; + uint32_t id; + xcb_randr_output_t randr_id; + xcb_window_t root; + bool wired; + padding_t padding; + unsigned int sticky_count; + int window_gap; + unsigned int border_width; + xcb_rectangle_t rectangle; + desktop_t *desk; + desktop_t *desk_head; + desktop_t *desk_tail; + monitor_t *prev; + monitor_t *next; +}; + +typedef struct { + monitor_t *monitor; + desktop_t *desktop; + node_t *node; +} coordinates_t; + +typedef struct history_t history_t; +struct history_t { + coordinates_t loc; + bool latest; + history_t *prev; + history_t *next; +}; + +typedef struct stacking_list_t stacking_list_t; +struct stacking_list_t { + node_t *node; + stacking_list_t *prev; + stacking_list_t *next; +}; + +typedef struct event_queue_t event_queue_t; +struct event_queue_t { + xcb_generic_event_t event; + event_queue_t *prev; + event_queue_t *next; +}; + +typedef struct subscriber_list_t subscriber_list_t; +struct subscriber_list_t { + FILE *stream; + char* fifo_path; + int field; + int count; + subscriber_list_t *prev; + subscriber_list_t *next; +}; + +typedef struct rule_t rule_t; +struct rule_t { + char class_name[MAXLEN]; + char instance_name[MAXLEN]; + char name[MAXLEN]; + char effect[MAXLEN]; + bool one_shot; + rule_t *prev; + rule_t *next; +}; + +typedef struct { + char class_name[MAXLEN]; + char instance_name[MAXLEN]; + char name[MAXLEN]; + char monitor_desc[MAXLEN]; + char desktop_desc[MAXLEN]; + char node_desc[MAXLEN]; + direction_t *split_dir; + double split_ratio; + stack_layer_t *layer; + client_state_t *state; + bool hidden; + bool sticky; + bool private; + bool locked; + bool marked; + bool center; + bool follow; + bool manage; + bool focus; + bool border; + xcb_rectangle_t *rect; +} rule_consequence_t; + +typedef struct pending_rule_t pending_rule_t; +struct pending_rule_t { + int fd; + xcb_window_t win; + rule_consequence_t *csq; + event_queue_t *event_head; + event_queue_t *event_tail; + pending_rule_t *prev; + pending_rule_t *next; +}; + +#endif