summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorben <ben.nagy@arachnida.blog>2024-10-17 18:19:25 -0700
committerben <ben.nagy@arachnida.blog>2024-10-17 18:19:25 -0700
commit639e8280cc4440f4162c3488f1b5c8ad36dec346 (patch)
tree429dd4265ac9dc9fd584b4bc073b149278092d0d
parent88be7c1ea7b8a0eb1909b3ad43ebb8c0ee37a052 (diff)
Key symbols and mouse pointer added
-rw-r--r--src/Makefile4
-rw-r--r--src/config.h11
-rw-r--r--src/scapx.c165
-rw-r--r--src/scapx.h24
-rw-r--r--src/types.h (renamed from src/defs.h)5
-rw-r--r--src/x.c158
-rw-r--r--src/x.h23
7 files changed, 309 insertions, 81 deletions
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/scapx.c b/src/scapx.c
index 09b597e..50edc7f 100644
--- a/src/scapx.c
+++ b/src/scapx.c
@@ -1,89 +1,114 @@
// std
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+// X
+#include <X11/keysymdef.h>
+#include <X11/keysym.h>
+#include <xcb/xcb_keysyms.h>
+#include <X11/cursorfont.h>
+//#include <xcb/xcb_atom.h>
+// #include <xcb/xcb_util.h>
+// #include <X11/Xutil.h>
+#include <xcb/xcb_cursor.h>
// 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 <xcb/xcb.h>
-
-#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/defs.h b/src/types.h
index 2e40298..1c5b97a 100644
--- a/src/defs.h
+++ b/src/types.h
@@ -1,3 +1,6 @@
+#ifndef DEFS_H
+#define DEFS_H
+
#include <stdint.h>
typedef uint8_t u8;
@@ -12,3 +15,5 @@ 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/keysym.h>
+#include <xcb/xcb_keysyms.h>
+
+#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 <xcb/xcb.h>
+#include <xcb/xcb_keysyms.h>
+
+#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