From 908e1d39e2d45bb75fbb2327cc6754b222940d2e Mon Sep 17 00:00:00 2001 From: Syed Daanish Date: Mon, 29 Sep 2025 11:20:05 +0000 Subject: [PATCH] Update X-kutu.c --- X-kutu.c | 316 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 160 insertions(+), 156 deletions(-) diff --git a/X-kutu.c b/X-kutu.c index f7bb02e..ccb6ff6 100644 --- a/X-kutu.c +++ b/X-kutu.c @@ -1,21 +1,32 @@ #define CLEANMASK(m) ((m & ~0x80)) +// Definitions for modifier keys #define SUPER XCB_MOD_MASK_4 #define ALT XCB_MOD_MASK_1 #define CTRL XCB_MOD_MASK_CONTROL #define SHIFT XCB_MOD_MASK_SHIFT + +// Change this to change the modifier key you want to use #define MOD SUPER +// Standard headers #include #include #include + +// XCB headers #include #include +// Global variables +// Connection to X server xcb_connection_t *conn; +// Screen of the X server xcb_screen_t *scr; +// Currently focused window xcb_window_t focuswin; +// Geometry structure for rectangles and positions typedef struct Geometry { int16_t x; int16_t y; @@ -23,161 +34,7 @@ typedef struct Geometry { uint16_t height; } Geometry; -void cleanup(void) { - if (conn != NULL) - xcb_disconnect(conn); -} - -void add_keybind(int key) { - xcb_grab_key(conn, 0, scr->root, MOD, key, XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_ASYNC); -} - -void add_mousebind(int button) { - xcb_grab_button(conn, 0, scr->root, - XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, - button, MOD); -} - -int deploy(void) { - uint32_t values[2]; - int mask; - - if (xcb_connection_has_error(conn = xcb_connect(NULL, NULL))) - return -1; - - scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; - focuswin = scr->root; - - mask = XCB_CW_EVENT_MASK; - values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes_checked(conn, scr->root, mask, values); - - xcb_flush(conn); - - return 0; -} - -void free_geometry(Geometry *g) { free(g); } - -Geometry *xrandr_get_monitors(void) { - xcb_randr_get_screen_resources_current_cookie_t res_cookie = - xcb_randr_get_screen_resources_current(conn, scr->root); - xcb_randr_get_screen_resources_current_reply_t *res = - xcb_randr_get_screen_resources_current_reply(conn, res_cookie, NULL); - if (!res) - return NULL; - int num_outputs = xcb_randr_get_screen_resources_current_outputs_length(res); - xcb_randr_output_t *outputs = - xcb_randr_get_screen_resources_current_outputs(res); - Geometry *all = calloc(2, sizeof(Geometry)); - int count = 0; - for (int i = 0; i < num_outputs && count < 2; i++) { - xcb_randr_get_output_info_cookie_t ocookie = - xcb_randr_get_output_info(conn, outputs[i], XCB_CURRENT_TIME); - xcb_randr_get_output_info_reply_t *oinfo = - xcb_randr_get_output_info_reply(conn, ocookie, NULL); - if (!oinfo) - continue; - if (oinfo->connection == XCB_RANDR_CONNECTION_CONNECTED && - oinfo->crtc != XCB_NONE) { - xcb_randr_get_crtc_info_cookie_t ccookie = - xcb_randr_get_crtc_info(conn, oinfo->crtc, XCB_CURRENT_TIME); - xcb_randr_get_crtc_info_reply_t *cinfo = - xcb_randr_get_crtc_info_reply(conn, ccookie, NULL); - if (cinfo) { - all[count].x = cinfo->x; - all[count].y = cinfo->y; - all[count].width = cinfo->width; - all[count].height = cinfo->height; - free(cinfo); - count++; - } - } - free(oinfo); - } - free(res); - return all; -} - -void focus(xcb_window_t win) { - xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, win, - XCB_CURRENT_TIME); - if (win != focuswin) - focuswin = win; -} - -xcb_window_t get_focus(void) { return focuswin; } - -void subscribe(xcb_window_t win) { - uint32_t values[2]; - - values[0] = XCB_EVENT_MASK_ENTER_WINDOW; - values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes(conn, win, XCB_CW_EVENT_MASK, values); -} - -void kill(xcb_window_t window) { - xcb_kill_client(conn, window); - xcb_flush(conn); -} - -void show(xcb_window_t window) { - xcb_map_window(conn, window); - xcb_flush(conn); -} - -void hide(xcb_window_t window) { - xcb_unmap_window(conn, window); - xcb_flush(conn); -} - -void send_to_top(xcb_window_t win) { - uint32_t values[1] = {XCB_STACK_MODE_ABOVE}; - xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values); - xcb_flush(conn); -} - -Geometry get_geometry(xcb_window_t win) { - xcb_get_geometry_reply_t *geom = - xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); - Geometry g = {geom->x, geom->y, geom->width, geom->height}; - free(geom); - return g; -} - -Geometry get_pointer(void) { - xcb_query_pointer_reply_t *geom; - geom = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, scr->root), 0); - Geometry g = {geom->root_x, geom->root_y, 0, 0}; - free(geom); - return g; -} - -Geometry get_screen(void) { - return (Geometry){0, 0, scr->width_in_pixels, scr->height_in_pixels}; -} - -void warp_pointer(xcb_window_t win, int x, int y) { - xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0, x, y); - xcb_flush(conn); -} - -void move_window(xcb_window_t win, int x, int y) { - uint32_t values[2] = {x, y}; - xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, - values); - xcb_flush(conn); -} - -void resize_window(xcb_window_t win, int width, int height) { - uint32_t values[2] = {width, height}; - xcb_configure_window( - conn, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); - xcb_flush(conn); -} - +// Event structure to represent various X events typedef struct Event { int32_t type; uint32_t window; @@ -191,6 +48,151 @@ typedef struct Event { int8_t is_root; } Event; +// Cleanup function to close the X connection on exit +void cleanup(void) { + if (conn != NULL) + xcb_disconnect(conn); +} + +// Keybind function to setup a key grab if the keycode is clicked along with the MOD key +void add_keybind(int key) { + xcb_grab_key(conn, 0, scr->root, MOD, key, XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC); +} + +// Mousebind function to setup a mouse button grab if the button is clicked along with the MOD key +void add_mousebind(int button) { + xcb_grab_button(conn, 0, scr->root, + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, + button, MOD); +} + +// Deploy function to initialize the X connection, set up event masks, and prepare the window manager +int deploy(void) { + uint32_t values[2]; + int mask; + + // Start X connection and return -1 if it fails + if (xcb_connection_has_error(conn = xcb_connect(NULL, NULL))) + return -1; + + // Define screen and focus window + scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; + focuswin = scr->root; + + // Setuup event masks + mask = XCB_CW_EVENT_MASK; + values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + xcb_change_window_attributes_checked(conn, scr->root, mask, values); + + xcb_flush(conn); + + return 0; +} + +// Free a geometry structure +void free_geometry(Geometry *g) { free(g); } + +// Get monitor geometries using XRandR, returns an array of Geometry structures +// The caller is responsible for freeing the returned array +Geometry *xrandr_get_monitors(void) { + // TODO: Loop through monitors and return their geometries + return all; +} + +// Set input focus to a window +void focus(xcb_window_t win) { + xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, win, + XCB_CURRENT_TIME); + focuswin = win; +} + +// Get the currently focused window +xcb_window_t get_focus(void) { return focuswin; } + +// Subscribe to events on a window +void subscribe(xcb_window_t win) { + uint32_t values[2]; + values[0] = XCB_EVENT_MASK_ENTER_WINDOW; + values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + xcb_change_window_attributes(conn, win, XCB_CW_EVENT_MASK, values); +} + +// Kill a window +void kill(xcb_window_t window) { + xcb_kill_client(conn, window); + xcb_flush(conn); +} + +// Show a window +void show(xcb_window_t window) { + xcb_map_window(conn, window); + xcb_flush(conn); +} + +// Hide a window +void hide(xcb_window_t window) { + xcb_unmap_window(conn, window); + xcb_flush(conn); +} + +// Bring a window to the top of the stack +void send_to_top(xcb_window_t win) { + uint32_t values[1] = {XCB_STACK_MODE_ABOVE}; + xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_STACK_MODE, values); + xcb_flush(conn); +} + +// Get the geometry of a window +Geometry get_geometry(xcb_window_t win) { + xcb_get_geometry_reply_t *geom = + xcb_get_geometry_reply(conn, xcb_get_geometry(conn, win), NULL); + Geometry g = {geom->x, geom->y, geom->width, geom->height}; + free(geom); + return g; +} + +// Get the current pointer position +Geometry get_pointer(void) { + xcb_query_pointer_reply_t *geom; + geom = xcb_query_pointer_reply(conn, xcb_query_pointer(conn, scr->root), 0); + Geometry g = {geom->root_x, geom->root_y, 0, 0}; + free(geom); + return g; +} + +// Get the screen geometry +Geometry get_screen(void) { + return (Geometry){0, 0, scr->width_in_pixels, scr->height_in_pixels}; +} + +// Warp the pointer to a specific position in a window +// Can be used with get_geometry to warp to a specific position in a window (eg. the center) +void warp_pointer(xcb_window_t win, int x, int y) { + xcb_warp_pointer(conn, XCB_NONE, win, 0, 0, 0, 0, x, y); + xcb_flush(conn); +} + +// Move a window to a specific position +void move_window(xcb_window_t win, int x, int y) { + uint32_t values[2] = {x, y}; + xcb_configure_window(conn, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, + values); + xcb_flush(conn); +} + +// Resize a window to specific dimensions +void resize_window(xcb_window_t win, int width, int height) { + uint32_t values[2] = {width, height}; + xcb_configure_window( + conn, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); + xcb_flush(conn); +} + +// Wait for an event and return it as an Event structure +// This function is blocking +// The event is sent by value, so no need to free anything Event wait_for_event(void) { Event ret = {0}; @@ -235,6 +237,7 @@ Event wait_for_event(void) { xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; if (!e->child) break; + // Grab pointer for dragging xcb_grab_pointer(conn, 0, e->child, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | @@ -260,6 +263,7 @@ Event wait_for_event(void) { case XCB_BUTTON_RELEASE: { xcb_button_release_event_t *e = (xcb_button_release_event_t *)ev; + // Ungrab pointer after dragging xcb_ungrab_pointer(conn, XCB_CURRENT_TIME); ret.type = 7; ret.x = e->event_x; @@ -300,4 +304,4 @@ Event wait_for_event(void) { xcb_flush(conn); free(ev); return ret; -} +} \ No newline at end of file