From 639e8280cc4440f4162c3488f1b5c8ad36dec346 Mon Sep 17 00:00:00 2001 From: ben Date: Thu, 17 Oct 2024 18:19:25 -0700 Subject: Key symbols and mouse pointer added --- src/Makefile | 4 +- src/config.h | 11 ++++ src/defs.h | 14 ----- src/scapx.c | 165 ++++++++++++++++++++++++++++++++++------------------------- src/scapx.h | 24 +++++---- src/types.h | 19 +++++++ src/x.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/x.h | 23 +++++++++ 8 files changed, 323 insertions(+), 95 deletions(-) create mode 100644 src/config.h delete mode 100644 src/defs.h create mode 100644 src/types.h create mode 100644 src/x.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 7b4ec09..3aeea52 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,9 +1,9 @@ CC = gcc CFLAGS = -Wall -Wextra -Wpedantic -std=c99 -Wunreachable-code -Werror-implicit-function-declaration -LD_CFLAGS = -lxcb +LD_CFLAGS = -lxcb -lxcb-keysyms BIN_DIR = ../bin TARGET = $(BIN_DIR)/scapx -SRC = scapx.c +SRC = scapx.c x.c #keysyms.c #HEADERS = scapx.h diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..5291767 --- /dev/null +++ b/src/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define DEBUG 1 + + + +#define M_BTN_1 1 +#define M_BTN_2 3 + +#endif diff --git a/src/defs.h b/src/defs.h deleted file mode 100644 index 2e40298..0000000 --- a/src/defs.h +++ /dev/null @@ -1,14 +0,0 @@ -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t i8; -typedef int16_t i16; -typedef int32_t i32; -typedef int64_t i64; - -typedef float f32; -typedef double f64; diff --git a/src/scapx.c b/src/scapx.c index 09b597e..50edc7f 100644 --- a/src/scapx.c +++ b/src/scapx.c @@ -1,89 +1,114 @@ // std #include #include -#include +#include +#include + +// X +#include +#include +#include +#include +//#include +// #include +// #include +#include // local +#include "types.h" #include "scapx.h" -#include "defs.h" +#include "x.h" +#include "config.h" -// TODO: move this all to x.c -static Server_context_t *init_XCB_server(); -static xcb_window_t create_win(Server_context_t *info); -static Server_context_t *init_XCB_server() +void dbg_printf(const char *fmt, ...) { - Server_context_t *info; + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} - if (!(info = malloc(sizeof(Server_context_t)))) { - fprintf(stderr, "memory allocation failed.\n"); - return NULL; - } +int main(int argc, char **argv) +{ + // TODO: parse flags - info->con = xcb_connect(NULL, &info->scr_nbr); - if (xcb_connection_has_error(info->con) > 0) { - fprintf(stderr, "Error opening display.\n"); - free(info); - return NULL; - } + Server_context_t *info; - info->iter = xcb_setup_roots_iterator(xcb_get_setup(info->con)); - for (; info->iter.rem; --info->scr_nbr, xcb_screen_next(&info->iter)) - if (info->scr_nbr == 0) { - info->scr = info->iter.data; - break; + if (!(info = init_XCB_server())) + FATAL_ERROR("Couldn't make a connection to the x server. %s", ""); + + xcb_drawable_t win = create_win(info); + xcb_key_symbols_t *ksymbols = xcb_key_symbols_alloc(info->con); + xcb_generic_event_t *event; + xcb_cursor_t mptr; + + bool done = 0; + while (!done && (event = xcb_wait_for_event(info->con))) { + if (event->response_type == 0 ) + SLOG("Error reported by the x server.\n"); + + switch (event->response_type & ~0x80) { + { // mouse + static bool lmbtn = 0; + static bool rmbtn = 0; + case XCB_BUTTON_PRESS: + if (((xcb_button_press_event_t *)event)->detail == M_BTN_1) { + lmbtn = 1; + printf("left clicked.\n"); + } + + if (((xcb_button_press_event_t *)event)->detail == M_BTN_2) { + printf("right clicked.\n"); + rmbtn = 1; + } + break; + case XCB_BUTTON_RELEASE: + cursor_die(info->con, win, mptr); + if (((xcb_button_press_event_t *)event)->detail == M_BTN_1) { + lmbtn = 0; + } + if (((xcb_button_press_event_t *)event)->detail == M_BTN_2) { + rmbtn = 0; + } + break; + case XCB_MOTION_NOTIFY: + if (lmbtn || rmbtn) { + mptr = cursor_set(info->con, info->scr, win, XC_cross); + printf("%s drag.\n", lmbtn ? "left" : "right"); + } else + printf("moving.\n"); + break; + } + + case XCB_KEY_PRESS: + printf("\nKeyPress event received:\n"); + xcb_key_press_event_t *kevent = (xcb_key_press_event_t *)event; + + // NOTE: field is a mask of the buttons held down during the event + printf("state %#x ", kevent->state); + printf("keycode %u ", kevent->detail); + + + xcb_keysym_t ksym = xcb_key_symbols_get_keysym(ksymbols, kevent->detail, kevent->state); + const char *sym_str = ksym_to_str(&ksym); + + if (ksym == XK_Escape || ksym == XK_q || ksym == XK_Q) + die(ksymbols, info, win); + + + printf("keysym [%#x %s]\n", ksym, sym_str ? sym_str : ""); + break; + case XCB_KEY_RELEASE: + break; } - return info; -} - -static xcb_window_t create_win(Server_context_t *info) -{ - xcb_gcontext_t gc; - xcb_window_t win; - u32 vmask, vlist[2]; - - // create gc - win = info->scr->root; - gc = xcb_generate_id(info->con); - vmask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; - vlist[0] = info->scr->black_pixel; - vlist[1] = 0; - xcb_create_gc (info->con, gc, win, vmask, vlist); - - // create window - win = xcb_generate_id(info->con); - vmask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - vlist[0] = info->scr->white_pixel; - vlist[1] = XCB_EVENT_MASK_EXPOSURE; - - xcb_create_window(info->con, - XCB_COPY_FROM_PARENT, - win, - info->scr->root, - 0, 0, - 150, 150, - 10, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - info->scr->root_visual, - vmask, vlist - ); - xcb_map_window(info->con, win); - xcb_flush(info->con); - - return win; -} - -int main(int argc, char **argv) -{ - // TODO: Parse flags + free(event); + } - Server_context_t *serv_context = init_XCB_server(); - xcb_drawable_t win = create_win(serv_context); - pause(); + xcb_free_cursor(info->con, mptr); - xcb_disconnect(serv_context->con); - free(serv_context); + die(ksymbols, info, win); return 0; } diff --git a/src/scapx.h b/src/scapx.h index 00659d5..c232067 100644 --- a/src/scapx.h +++ b/src/scapx.h @@ -1,9 +1,7 @@ #ifndef SCAPX_H #define SCAPX_H -#include - -#define OPTS(msg) \ +#define POPTS(msg) \ do { \ fprintf(stderr, "Usage: scapx\n"); \ fprintf(stderr, "%s\n\n\n", msg); \ @@ -14,11 +12,19 @@ exit(EXIT_FAILURE); \ } while (0) -typedef struct { - xcb_connection_t *con; - xcb_screen_t *scr; - xcb_screen_iterator_t iter; - int scr_nbr; -} Server_context_t; + +#define SLOG(...) (fprintf(stderr, __VA_ARGS__)) + +#define DEBUG_INFO(FMT, ARGS...) do { \ + if (DEBUG) \ + fprintf(stderr, "%s:%d " FMT "\n", __FUNCTION__, __LINE__, ## ARGS); \ + } while (0) + +#define FATAL_ERROR(errstr, ...) \ + do { \ + fprintf(stderr, (errstr), ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } while (0) + #endif diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..1c5b97a --- /dev/null +++ b/src/types.h @@ -0,0 +1,19 @@ +#ifndef DEFS_H +#define DEFS_H + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef float f32; +typedef double f64; + +#endif diff --git a/src/x.c b/src/x.c index e69de29..828445f 100644 --- a/src/x.c +++ b/src/x.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include + +#include "x.h" +#include "types.h" + +Server_context_t *init_XCB_server(); +xcb_window_t create_win(Server_context_t *info); + +Server_context_t *init_XCB_server() +{ + Server_context_t *info; + + if (!(info = malloc(sizeof(Server_context_t)))) { + fprintf(stderr, "memory allocation failed.\n"); + return NULL; + } + + info->con = xcb_connect(NULL, &info->scr_nbr); + if (xcb_connection_has_error(info->con) > 0) { + fprintf(stderr, "Error opening display.\n"); + free(info); + return NULL; + } + + info->iter = xcb_setup_roots_iterator(xcb_get_setup(info->con)); + for (; info->iter.rem; --info->scr_nbr, xcb_screen_next(&info->iter)) + if (info->scr_nbr == 0) { + info->scr = info->iter.data; + break; + } + + return info; +} + +xcb_window_t create_win(Server_context_t *info) +{ + xcb_gcontext_t gc; + xcb_window_t win; + u32 vmask, vlist[2]; + + // create gc + win = info->scr->root; + gc = xcb_generate_id(info->con); + vmask = XCB_GC_FOREGROUND | + /* + XCB_GC_LINE_WIDTH | + XCB_GC_LINE_STYLE | + XCB_GC_FILL_STYLE | + XCB_GC_ARC_MODE | + */ + XCB_GC_GRAPHICS_EXPOSURES; + vlist[0] = info->scr->black_pixel; + vlist[1] = 0; + xcb_create_gc (info->con, gc, win, vmask, vlist); + + // create window + win = xcb_generate_id(info->con); + vmask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + vlist[0] = /* 0 */ info->scr->white_pixel; + vlist[1] = XCB_EVENT_MASK_EXPOSURE | // window is exposed, needs to be redrawn + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_BUTTON_1_MOTION | // mouse is dragging + XCB_EVENT_MASK_POINTER_MOTION | // mouse is moving without clicking + XCB_MOTION_NOTIFY | + XCB_EVENT_MASK_BUTTON_MOTION | + /* + XCB_MOTION_NOTIFY | + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE; // keyboard + XCB_KEY_PRESS | + XCB_EVENT_MASK_KEY_PRESS | + */ + XCB_KEY_PRESS | + XCB_KEY_RELEASE; + + xcb_create_window(info->con, + XCB_COPY_FROM_PARENT, + win, + info->scr->root, + 0, 0, + info->scr->width_in_pixels, + info->scr->height_in_pixels, + 10, // boarder width + XCB_WINDOW_CLASS_INPUT_OUTPUT, + info->scr->root_visual, + vmask, vlist + ); + + xcb_map_window(info->con, win); + xcb_flush(info->con); + + return win; +} + +xcb_cursor_t cursor_set(xcb_connection_t *c, xcb_screen_t *scr, xcb_window_t win, u32 cid) +{ + xcb_font_t font; + xcb_cursor_t ptr; + u32 mask; + u32 value_list; + + font = xcb_generate_id(c); + xcb_open_font(c, font, strlen("cursor"), "cursor"); + ptr = xcb_generate_id(c); + xcb_create_glyph_cursor(c, + ptr, + font, font, + cid, cid, + 0, 0, 0, + 0, 0, 0); + + + mask = XCB_CW_CURSOR; + value_list = ptr; + xcb_change_window_attributes(c, win, mask, &value_list); + xcb_flush(c); + + return ptr; +} + +void cursor_die(xcb_connection_t *c, xcb_window_t win, u32 value_list) +{ + value_list = 0; + xcb_change_window_attributes(c, win, XCB_CW_CURSOR, &value_list); + // xcb_free_cursor(c, value_list); + xcb_flush(c); +} + +const char *ksym_to_str(const xcb_keysym_t *ksym) +{ + switch (*ksym) { + case XK_Escape: return "Escape"; + case XK_q: return "q"; + case XK_Q: return "Q"; + case XK_l: return "l"; + case XK_w: return "w"; + case XK_c: return "c"; + case XK_r: return "r"; + default: return NULL; + } + + return NULL; +} + +void die(xcb_key_symbols_t *sym, Server_context_t *s_info, xcb_drawable_t win) +{ + xcb_key_symbols_free(sym); + xcb_free_gc(s_info->con, win); + xcb_disconnect(s_info->con); + free(s_info); + exit(0); +} diff --git a/src/x.h b/src/x.h new file mode 100644 index 0000000..632a7a4 --- /dev/null +++ b/src/x.h @@ -0,0 +1,23 @@ +#ifndef X_H +#define X_H + +#include +#include + +#include "types.h" + +typedef struct { + xcb_connection_t *con; + xcb_screen_t *scr; + xcb_screen_iterator_t iter; + int scr_nbr; +} Server_context_t; + +Server_context_t *init_XCB_server(); +xcb_window_t create_win(Server_context_t *info); +xcb_cursor_t cursor_set(xcb_connection_t *c, xcb_screen_t *scr, xcb_window_t win, u32 cid); +void cursor_die(xcb_connection_t *c, xcb_window_t win, u32 value_list); +const char *ksym_to_str(const xcb_keysym_t *ksym); +void die(xcb_key_symbols_t *sym, Server_context_t *s_info, xcb_drawable_t win); + +#endif -- cgit v1.2.3