aboutsummaryrefslogtreecommitdiff
path: root/src/connect.c
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-07-08 15:22:41 +0200
committerFederico Angelilli <code@fedang.net>2024-07-08 15:22:41 +0200
commit5d170a634ead0119f6e5a9f63c23b2b064126f75 (patch)
tree0447d2dbb0da6358d184a4c62d5557d4d22f5e8d /src/connect.c
parent92feb3c130966202c7caa6d9bf3a3800c97ca7a1 (diff)
Remove old files
Diffstat (limited to 'src/connect.c')
-rw-r--r--src/connect.c408
1 files changed, 0 insertions, 408 deletions
diff --git a/src/connect.c b/src/connect.c
deleted file mode 100644
index aaced77..0000000
--- a/src/connect.c
+++ /dev/null
@@ -1,408 +0,0 @@
-#include <glib.h>
-#include <xcb/xcb.h>
-#include <xcb/xcb_aux.h>
-#include <xcb/xcb_ewmh.h>
-#include <xcb/xcb_xrm.h>
-#include <xcb/xcb_errors.h>
-#include <xcb/randr.h>
-
-#include "log.h"
-#include "connect.h"
-#include "state.h"
-
-static bool query_xrm(Connection *con, const char *res, char **value)
-{
- if (xcb_xrm_resource_get_string(con->database, res, res, value) >= 0) {
- log_debug("Xrm query '%s' found '%s'", res, *value);
- return true;
- }
-
- log_debug("Xrm query '%s' not found", res);
- return false;
-}
-
-static void update_xrm(Connection *con)
-{
- xcb_flush(con->connection);
- xcb_xrm_database_t *database = xcb_xrm_database_from_default(con->connection);
-
- if (database == NULL) {
- log_warning("Xrm database couldn't be updated");
- return;
- }
-
- xcb_xrm_database_free(con->database);
- con->database = database;
- log_debug("Xrm database updated");
-}
-
-static void update_scale(Connection *con)
-{
- char *dpi_value;
- if (query_xrm(con, "Xft.dpi", &dpi_value)) {
- con->screen_dpi = strtod(dpi_value, NULL);
- g_free(dpi_value);
- } else {
- con->screen_dpi = (double)con->screen_size->height * 25.4 / (double)con->screen_size->mheight;
- log_debug("Fallback dpi value '%.2lf'", con->screen_dpi);
- }
-}
-
-// Check if point (px, py) is inside a rectangle in (x, y), (x+w, y), (x, y+h) and (w+h, y+h)
-static inline bool in_rect(int px, int py, int x, int y, int w, int h)
-{
- return px >= x && px <= x + w && py >= y && py <= y + h;
-}
-
-// Check if point (px, py) is inside a circle of radius r and center (x, y)
-static inline bool in_circle(int px, int py, int x, int y, int r)
-{
- int dx = x - px;
- int dy = y - py;
- return (dx * dx + dy * dy) <= r * r;
-}
-
-// Check if point (px, py) is inside a capsule in (x, y), (x+w, y), (x, y+h) and (w+h, y+h)
-static inline bool in_capsule(int px, int py, int x, int y, int w, int h)
-{
- g_assert(w >= h);
- int radius = h / 2;
-
- // Circle case
- if (w == h) return in_circle(px, py, x + radius, y + radius, radius);
-
- // Capsule case
- return in_circle(px, py, x + radius, y + radius, radius)
- || in_circle(px, py, x + w - radius, y + radius, radius)
- || in_rect(px, py, x + radius, y, w - 2 * radius, h);
-}
-
-static bool button_action_find(State *state, GList *layouts, int x, int y)
-{
- for (GList *it = layouts; it; it = it->next) {
- const Layout *layout = it->data;
-
- // Skip
- if (layout->x + layout->width < x) continue;
- if (layout->x > x) break;
-
- // Bound check click coordinates
- int w = layout->width - 2 * layout->x_pad;
- int h = layout->height - 2 * layout->y_pad;
-
- if (!in_capsule(x, y, layout->x + layout->x_pad, layout->y + layout->y_pad, w, h))
- continue;
-
- Button *btn = layout->btn;
- if (!layout->btn->simple) {
- log_debug("Button group layout [x=%d, y=%d, w=%d, h=%d, button=%p]",
- layout->x, layout->y, layout->width, layout->height, btn);
-
- // Check the group children
- return button_action_find(state, layout->children, x, y);
- }
-
- log_debug("Button layout [x=%d, y=%d, w=%d, h=%d, button=%p]",
- layout->x, layout->y, layout->width, layout->height, btn);
-
- ButtonAction action = button_simple_get_action(btn);
- if (action == NULL) {
- // TODO: Button labels
- log_debug("Ignoring button without action [button=%p]", btn);
- return true;
- }
-
- // NOTE: Animations may change the layouts!
- Animation *anim = animation_shine_create(MILLIS(250));
- //Animation *anim = animation_pulse_create(MILLIS(200));
-
- if (button_set_animation(btn, anim))
- state_request_animation(state);
- else
- animation_destroy(anim);
-
- log_info("Triggering action for button [text=\"%s\", button=%p]", button_simple_get_text(btn), btn);
- action(btn);
- return true;
- }
-
- return false;
-}
-
-static void button_action(State *state, const char *event, int x, int y)
-{
- double scale = window_get_scale(state->win);
- int digital_x = x / scale;
- int digital_y = y / scale;
-
- log_debug("Checking %s event [device_x=%d, device_y=%d, x=%d, y=%d]", event, x, y, digital_x, digital_y);
- if (!button_action_find(state, state->draw->layouts, digital_x, digital_y))
- log_debug("Ignoring %s", event);
-}
-
-typedef struct {
- GSource source;
- Connection *con;
- gpointer fd_tag;
- xcb_generic_event_t *event;
-} EventSource;
-
-static gboolean source_check(GSource *source)
-{
- EventSource *xsource = (EventSource *)source;
- xcb_flush(xsource->con->connection);
- g_assert_null(xsource->event);
-
- GIOCondition flags = g_source_query_unix_fd(source, xsource->fd_tag);
- if (flags & G_IO_IN) {
- g_assert_false(xcb_connection_has_error(xsource->con->connection));
- xsource->event = xcb_poll_for_event(xsource->con->connection);
- }
-
- return xsource->event != NULL;
-}
-
-static gboolean source_dispatch(GSource *source, GSourceFunc callback, gpointer data)
-{
- EventSource *xsource = (EventSource *)source;
- g_assert_nonnull(xsource->event);
-
- do {
- switch (xsource->event->response_type & ~0x80) {
- case 0: {
- xcb_generic_error_t *error = (xcb_generic_error_t *)xsource->event;
-
- const char *extension;
- const char *name = xcb_errors_get_name_for_error(xsource->con->errors, error->error_code, &extension);
- const char *major = xcb_errors_get_name_for_major_code(xsource->con->errors, error->major_code);
- const char *minor = xcb_errors_get_name_for_minor_code(xsource->con->errors, error->major_code, error->minor_code);
-
- // TODO: Handle errors instead of aborting
- log_error("Xcb error '%s' [extension=%s, major=%s, minor=%s, resource=%u, sequence=%u]",
- name,
- extension ? extension : "none",
- major,
- minor ? minor : "none",
- (unsigned int)error->resource_id,
- (unsigned int)error->sequence);
- break;
- }
-
- case XCB_EXPOSE: {
- xcb_expose_event_t *expose = (xcb_expose_event_t *)xsource->event;
- log_debug("Processing event 'Expose' [type=%d]", XCB_EXPOSE);
-
- for (GList *it = xsource->con->states; it != NULL; it = it->next) {
- State *state = it->data;
- if (state->win->window == expose->window) {
- state_request_redraw(state, true);
- break;
- }
- }
- break;
- }
-
- case XCB_CREATE_NOTIFY: {
- xcb_create_notify_event_t *create = (xcb_create_notify_event_t *)xsource->event;
- log_debug("Processing event 'CreateNotify' [type=%d]", XCB_CREATE_NOTIFY);
-
- // TODO: Circulate top the window if override_redirect == 0
-
- break;
- }
-
- case XCB_BUTTON_RELEASE: {
- xcb_button_release_event_t *button = (xcb_button_release_event_t *)xsource->event;
- log_debug("Processing event 'ButtonRelease' [type=%d]", XCB_BUTTON_RELEASE);
-
- // TODO: Handle different actions properly
- switch (button->detail) {
- case XCB_BUTTON_INDEX_2: // left click
- case XCB_BUTTON_INDEX_1: // right click
- case XCB_BUTTON_INDEX_3: // middle click
- for (GList *it = xsource->con->states; it != NULL; it = it->next) {
- State *state = it->data;
- if (state->win->window == button->event) {
- button_action(state, "button release", button->event_x, button->event_y);
- break;
- }
- }
- break;
-
- default:
- log_debug("Ignoring button release [button=%d]", button->detail);
- break;
- }
- break;
- }
-
- // TODO: Implement correctly hovering
- //case XCB_MOTION_NOTIFY: {
- // xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)xsource->event;
- // log_debug("Processing event 'MotionNotify' [type=%d]", XCB_MOTION_NOTIFY);
- // button_action(xsource->con->state, "motion notify", motion->event_x, motion->event_y);
- // break;
- //}
-
- case XCB_PROPERTY_NOTIFY: {
- xcb_property_notify_event_t *property = (xcb_property_notify_event_t *)xsource->event;
- log_debug("Processing event 'PropertyNotify' [type=%d]", XCB_PROPERTY_NOTIFY);
-
- if (property->atom == XCB_ATOM_RESOURCE_MANAGER) {
- update_xrm(xsource->con);
- update_scale(xsource->con);
- for (GList *it = xsource->con->states; it != NULL; it = it->next)
- state_request_redraw(it->data, true);
- }
- break;
- }
-
- default: {
- const char *extension;
- const char *name = xcb_errors_get_name_for_xcb_event(xsource->con->errors, xsource->event, &extension);
-
- // TODO: Handle XCB_RANDR_SCREEN_CHANGE_NOTIFY
-
- log_debug("Ignoring event '%s' [type=%d, extension=%s]",
- name,
- xsource->event->response_type & 0x7f,
- extension ? extension : "none");
- }
- }
- g_free(xsource->event);
- } while ((xsource->event = xcb_poll_for_event(xsource->con->connection)) != NULL);
-
- return G_SOURCE_CONTINUE;
-}
-
-static GSourceFuncs source_fns = {
- NULL,
- source_check,
- source_dispatch,
- NULL,
-};
-
-static void attach_source(Connection *con)
-{
- EventSource *source = (EventSource *)g_source_new(&source_fns, sizeof(EventSource));
- con->source = (GSource *)source;
- g_source_set_static_name(con->source, "EventSource");
-
- source->con = con;
- source->event = NULL;
- source->fd_tag = g_source_add_unix_fd(con->source, xcb_get_file_descriptor(con->connection), G_IO_IN | G_IO_HUP | G_IO_ERR);
-
- g_source_attach(con->source, NULL);
-}
-
-Connection *connect_create()
-{
- Connection *con = g_malloc0(sizeof(Connection));
- g_assert_nonnull(con);
-
- int preferred_screen = 0;
- con->connection = xcb_connect(NULL, &preferred_screen);
- g_assert_true(con->connection != NULL && !xcb_connection_has_error(con->connection));
- log_debug("Xcb connection established");
-
- log_debug("Default screen '%d'", preferred_screen);
- xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(con->connection));
-
- while (preferred_screen != 0 && iter.rem) {
- xcb_screen_next(&iter);
- preferred_screen--;
- }
-
- con->screen = iter.data;
- xcb_generic_error_t *error;
-
- xcb_randr_query_version_cookie_t version_cookie = xcb_randr_query_version(con->connection,
- XCB_RANDR_MAJOR_VERSION,
- XCB_RANDR_MINOR_VERSION);
-
- xcb_randr_query_version_reply_t *randr_version = xcb_randr_query_version_reply(con->connection,
- version_cookie,
- &error);
-
- g_assert_null(error);
- log_debug("RandR loaded [version=%d.%d]", randr_version->major_version, randr_version->minor_version);
- g_assert_cmpint(randr_version->major_version, >=, 1);
- g_free(randr_version);
-
- xcb_randr_get_screen_info_cookie_t cookie = xcb_randr_get_screen_info(con->connection, con->screen->root);
- con->info_reply = xcb_randr_get_screen_info_reply(con->connection, cookie, &error);
- g_assert_null(error);
-
- con->screen_size = xcb_randr_get_screen_info_sizes(con->info_reply);
- g_assert_nonnull(con->screen_size);
- log_debug("Screen size [width=%d, height=%d]", con->screen_size->width, con->screen_size->height);
-
- xcb_randr_select_input(con->connection,
- con->screen->root,
- XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
- XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
- XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
-
- log_debug("Xcb searching 32 bit visual");
- con->visual_type = xcb_aux_find_visual_by_attrs(con->screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32);
- con->screen_depth = 32;
-
- if (con->visual_type == NULL) {
- // NOTE: 24 bit visuals don't have the alpha channel for transparency
- log_debug("Fallback to 24 bit visual");
- con->visual_type = xcb_aux_find_visual_by_attrs(con->screen, XCB_VISUAL_CLASS_TRUE_COLOR, 24);
- con->screen_depth = 24;
- }
-
- g_assert_nonnull(con->visual_type);
- log_debug("Xcb visual type found [id=%u]", con->visual_type->visual_id);
-
- xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(con->connection, &con->ewmh);
- g_assert_true(xcb_ewmh_init_atoms_replies(&con->ewmh, ewmh_cookie, &error));
- g_assert_null(error);
- log_debug("Xcb ewmh initialized");
-
- con->database = xcb_xrm_database_from_default(con->connection);
- g_assert_nonnull(con->database);
-
- // TODO: Dpi aware scaling
- update_scale(con);
-
- g_assert(xcb_errors_context_new(con->connection, &con->errors) == 0);
- log_debug("Xcb errors loaded");
-
- xcb_flush(con->connection);
- log_debug("Xcb set up");
-
- return con;
-}
-
-void connect_attach_source(Connection *con)
-{
- g_assert_null(con->source);
- attach_source(con);
- log_debug("Xcb event loop attached");
-}
-
-void connect_add_state(Connection *con, State *state)
-{
- g_assert_nonnull(state);
- con->states = g_list_append(con->states, state);
- log_debug("Add state to event loop [state=%p, state=\"%s\"]", state, state->label);
-}
-
-void connect_destroy(Connection *con)
-{
- g_source_destroy(con->source);
- g_source_unref(con->source);
-
- xcb_ewmh_connection_wipe(&con->ewmh);
- xcb_errors_context_free(con->errors);
- xcb_xrm_database_free(con->database);
- xcb_disconnect(con->connection);
-
- g_free(con->info_reply);
- g_free(con);
-}
-
-// vim: ts=4 sw=4 et