From efebf35181554c40dc633e53329617c2b3990c83 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 21 Oct 2024 12:04:09 -0700 Subject: get focused window and set window name --- src/Makefile | 4 +- src/config.h | 9 +++- src/scapx | Bin 0 -> 26000 bytes src/scapx.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++------------ src/scapx.h | 19 ++++---- src/x.c | 53 ++++++++++++++++++++-- src/x.h | 5 ++- 7 files changed, 187 insertions(+), 45 deletions(-) create mode 100755 src/scapx (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 3aeea52..1a95772 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 -lxcb-keysyms -BIN_DIR = ../bin +BIN_DIR = $(PWD)#../bin TARGET = $(BIN_DIR)/scapx -SRC = scapx.c x.c #keysyms.c +SRC = *.c # scapx.c x.c #HEADERS = scapx.h diff --git a/src/config.h b/src/config.h index 5291767..d07c777 100644 --- a/src/config.h +++ b/src/config.h @@ -1,11 +1,16 @@ #ifndef CONFIG_H #define CONFIG_H -#define DEBUG 1 - +#include +// Debugging Mode +#define DEBUG 1 +// Mouse buttons #define M_BTN_1 1 #define M_BTN_2 3 +// Mouse Cursor +#define M_CURSOR XC_cross + #endif diff --git a/src/scapx b/src/scapx new file mode 100755 index 0000000..61090cf Binary files /dev/null and b/src/scapx differ diff --git a/src/scapx.c b/src/scapx.c index 50edc7f..1b37bf5 100644 --- a/src/scapx.c +++ b/src/scapx.c @@ -3,36 +3,64 @@ #include #include #include +#include +#include // X #include #include #include -#include -//#include -// #include -// #include +#include #include +// #include +// #include +// #include + // local #include "types.h" +#include "config.h" #include "scapx.h" #include "x.h" -#include "config.h" +// Project TODO: +/* + +Stages: + + // 1. WINDOWS: + - 1. get rid of visible window + - 2. grab info on currently focused window from WM + - 3. if simply left click, grab that whole window and window only for image capture (notice in maim, this scr does not take background?) + + // 2. DRAWING + - 4. draw rectangle selection + - 5. draw lasso selection + + // 3. screen capture3 + - 6. capture drawn polygon selection + - 7. capture drawn irregular (lasso) polygon selection + // _NET_WM_WINDOW_TYPE_DND // indicates win is being dragged + + // 4. FILE I/O + - 8. image file I/O +*/ void dbg_printf(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); } + int main(int argc, char **argv) { // TODO: parse flags + (void)argc; + (void)argv; Server_context_t *info; @@ -44,6 +72,10 @@ int main(int argc, char **argv) xcb_generic_event_t *event; xcb_cursor_t mptr; + xcb_set_win_name(info->con, win, "scapx"); + + // TODO: refactor + bool done = 0; while (!done && (event = xcb_wait_for_event(info->con))) { if (event->response_type == 0 ) @@ -51,9 +83,9 @@ int main(int argc, char **argv) switch (event->response_type & ~0x80) { { // mouse - static bool lmbtn = 0; - static bool rmbtn = 0; - case XCB_BUTTON_PRESS: + 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"); @@ -64,7 +96,7 @@ int main(int argc, char **argv) rmbtn = 1; } break; - case XCB_BUTTON_RELEASE: + case XCB_BUTTON_RELEASE: cursor_die(info->con, win, mptr); if (((xcb_button_press_event_t *)event)->detail == M_BTN_1) { lmbtn = 0; @@ -73,35 +105,91 @@ int main(int argc, char **argv) rmbtn = 0; } break; - case XCB_MOTION_NOTIFY: + case XCB_MOTION_NOTIFY: if (lmbtn || rmbtn) { - mptr = cursor_set(info->con, info->scr, win, XC_cross); + mptr = cursor_set(info->con, win, M_CURSOR); printf("%s drag.\n", lmbtn ? "left" : "right"); } else printf("moving.\n"); break; + case XCB_LEAVE_NOTIFY: + printf("left window.\n"); + { // get focused window + xcb_window_t focused_win = get_focused_win(info->con); + xcb_get_geometry_reply_t *geo_rep = xcb_get_geometry_reply(info->con, xcb_get_geometry(info->con, focused_win), NULL); + + xcb_flush(info->con); + xcb_unmap_window(info->con, win); + + // TODO: 1. put this on the top of the stack (fix the new window onto that which was focused) + // first: remove WM decoration + // TODO: instead of deleting the old window and creating a new, simply use xcb_configure_window to modify the existing window with focused win attr. + + xcb_create_window(info->con, + geo_rep->depth, + focused_win, + geo_rep->root, + geo_rep->x, geo_rep->y, + geo_rep->width, geo_rep->height, + geo_rep->border_width, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + info->scr->root_visual, + XCB_CW_EVENT_MASK | XCB_CW_CURSOR | XCB_CW_OVERRIDE_REDIRECT, + (u32[]){ + 0, + XCB_EVENT_MASK_BUTTON_1_MOTION | + XCB_EVENT_MASK_POINTER_MOTION | + XCB_MOTION_NOTIFY | + XCB_EVENT_MASK_BUTTON_MOTION | + XCB_EVENT_MASK_LEAVE_WINDOW, 1 + } + ); + + xcb_change_window_attributes(info->con, focused_win, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT, (u32[]){info->scr->black_pixel, 0}); + xcb_map_window(info->con, focused_win); + xcb_flush(info->con); + + // event loop for new window + + + while (xcb_wait_for_event(info->con)) { + switch (geo_rep->response_type & ~0x80) { + case XCB_MOTION_NOTIFY: + printf("motion received.\n"); + break; + default: + printf("event received.\n"); + break; + } + + printf("focused window width %u height %u\n", geo_rep->width, geo_rep->height); + } + + free(geo_rep); + } + break; } case XCB_KEY_PRESS: - printf("\nKeyPress event received:\n"); - xcb_key_press_event_t *kevent = (xcb_key_press_event_t *)event; + 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); + // 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); + 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); + 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; + printf("keysym [%#x %s]\n", ksym, sym_str ? sym_str : ""); + break; case XCB_KEY_RELEASE: - break; + break; } free(event); diff --git a/src/scapx.h b/src/scapx.h index c232067..47427db 100644 --- a/src/scapx.h +++ b/src/scapx.h @@ -10,21 +10,22 @@ fprintf(stdout, "-h, --help\t\t print this menu and quit. Alternatively, man scapx\n"); \ fprintf(stdout, "-v, --version\t\t print program version and quit\n\n"); \ exit(EXIT_FAILURE); \ - } while (0) - + } while (0) -#define SLOG(...) (fprintf(stderr, __VA_ARGS__)) +// TODO: put in util.h -#define DEBUG_INFO(FMT, ARGS...) do { \ - if (DEBUG) \ - fprintf(stderr, "%s:%d " FMT "\n", __FUNCTION__, __LINE__, ## ARGS); \ - } while (0) +#ifdef DEBUG + #define SLOG(...) (fprintf(stderr, ##__VA_ARGS__)) + #define DEBUG_INFO(FMT, ...) do { \ + if (DEBUG) \ + fprintf(stderr, "%s:%d " FMT "\n", __func__, __LINE__, ##__VA_ARGS__); \ + } while (0) +#endif -#define FATAL_ERROR(errstr, ...) \ +#define FATAL_ERROR(errstr, ...) \ do { \ fprintf(stderr, (errstr), ##__VA_ARGS__); \ exit(EXIT_FAILURE); \ } while (0) - #endif diff --git a/src/x.c b/src/x.c index 828445f..61a0fc0 100644 --- a/src/x.c +++ b/src/x.c @@ -4,8 +4,12 @@ #include #include +// #include very versatile + #include "x.h" #include "types.h" +#include "config.h" +#include "scapx.h" Server_context_t *init_XCB_server(); xcb_window_t create_win(Server_context_t *info); @@ -22,8 +26,7 @@ Server_context_t *init_XCB_server() 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; + free(info); return NULL; } info->iter = xcb_setup_roots_iterator(xcb_get_setup(info->con)); @@ -68,6 +71,7 @@ xcb_window_t create_win(Server_context_t *info) XCB_EVENT_MASK_POINTER_MOTION | // mouse is moving without clicking XCB_MOTION_NOTIFY | XCB_EVENT_MASK_BUTTON_MOTION | + XCB_EVENT_MASK_LEAVE_WINDOW | /* XCB_MOTION_NOTIFY | XCB_EVENT_MASK_EXPOSURE | @@ -98,7 +102,7 @@ xcb_window_t create_win(Server_context_t *info) return win; } -xcb_cursor_t cursor_set(xcb_connection_t *c, xcb_screen_t *scr, xcb_window_t win, u32 cid) +xcb_cursor_t cursor_set(xcb_connection_t *c, xcb_window_t win, u32 cid) { xcb_font_t font; xcb_cursor_t ptr; @@ -115,7 +119,6 @@ xcb_cursor_t cursor_set(xcb_connection_t *c, xcb_screen_t *scr, xcb_window_t win 0, 0, 0, 0, 0, 0); - mask = XCB_CW_CURSOR; value_list = ptr; xcb_change_window_attributes(c, win, mask, &value_list); @@ -156,3 +159,45 @@ void die(xcb_key_symbols_t *sym, Server_context_t *s_info, xcb_drawable_t win) free(s_info); exit(0); } + +xcb_window_t get_focused_win(xcb_connection_t *con) +{ + xcb_get_input_focus_reply_t *in_fo_reply = NULL; + + in_fo_reply = xcb_get_input_focus_reply(con, xcb_get_input_focus(con), NULL); + if (!in_fo_reply) { + DEBUG_INFO("could not get input focus reply: %s\n", ""); + return XCB_WINDOW_NONE; + } + + xcb_window_t focused_win = in_fo_reply->focus; + free(in_fo_reply); + + if (focused_win == XCB_WINDOW_NONE) { + DEBUG_INFO("could not retrieve focused window: %s\n", ""); + return XCB_WINDOW_NONE; + } + + return focused_win; +} + +xcb_atom_t get_atom(xcb_connection_t *c, const char *atom_name) +{ + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, 0, strlen(atom_name), atom_name); + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(c, cookie, NULL); + xcb_atom_t atom = reply->atom; + free(reply); + + return atom; +} + +void xcb_set_win_name(xcb_connection_t *c, xcb_window_t w, const char *title) +{ + xcb_atom_t WM_NAME = get_atom(c, "WM_NAME"); + xcb_atom_t STRING = get_atom(c, "STRING"); + xcb_change_property(c, XCB_PROP_MODE_REPLACE, w, WM_NAME, STRING, 8, + strlen(title), title); + + xcb_map_window (c, w); + xcb_flush (c); +} diff --git a/src/x.h b/src/x.h index 632a7a4..f4b69bc 100644 --- a/src/x.h +++ b/src/x.h @@ -15,9 +15,12 @@ typedef struct { 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); +xcb_cursor_t cursor_set(xcb_connection_t *c, 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); +xcb_window_t get_focused_win(xcb_connection_t *con); +xcb_atom_t get_atom(xcb_connection_t *c, const char *atom_name); +void xcb_set_win_name(xcb_connection_t *c, xcb_window_t w, const char *title); #endif -- cgit v1.2.3