Created
September 20, 2023 00:04
-
-
Save ortango/442d8aa6812c24a955f902eaa42fb715 to your computer and use it in GitHub Desktop.
qwikndutty xcursor support for moving and resizing windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff '--color=always' -ruN a/Makefile b/Makefile | |
--- a/Makefile 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/Makefile 2023-08-14 18:21:34.750469059 -0400 | |
@@ -4,7 +4,7 @@ | |
CPPFLAGS += -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" | |
CFLAGS += -std=c99 -pedantic -Wall -Wextra -DJSMN_STRICT | |
LDFLAGS ?= | |
-LDLIBS = $(LDFLAGS) -lm -lxcb -lxcb-util -lxcb-keysyms -lxcb-icccm -lxcb-ewmh -lxcb-randr -lxcb-xinerama -lxcb-shape | |
+LDLIBS = $(LDFLAGS) -lm -lxcb -lxcb-util -lxcb-keysyms -lxcb-icccm -lxcb-ewmh -lxcb-randr -lxcb-xinerama -lxcb-shape -lxcb-cursor | |
PREFIX ?= /usr/local | |
BINPREFIX ?= $(PREFIX)/bin | |
diff '--color=always' -ruN a/src/bspwm.c b/src/bspwm.c | |
--- a/src/bspwm.c 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/src/bspwm.c 2023-08-14 18:21:34.550462579 -0400 | |
@@ -37,6 +37,7 @@ | |
#include <string.h> | |
#include <xcb/xinerama.h> | |
#include <xcb/xcb_aux.h> | |
+#include <xcb/xcb_cursor.h> | |
#include "types.h" | |
#include "desktop.h" | |
#include "monitor.h" | |
@@ -453,6 +454,7 @@ | |
clear_input_focus(); | |
} | |
free(ifo); | |
+ xcursor_load_cursors(); | |
} | |
void register_events(void) | |
@@ -486,6 +488,7 @@ | |
} | |
empty_history(); | |
+ xcb_cursor_context_free(cursor_context); | |
} | |
bool check_connection (xcb_connection_t *dpy) | |
diff '--color=always' -ruN a/src/bspwm.h b/src/bspwm.h | |
--- a/src/bspwm.h 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/src/bspwm.h 2023-08-14 18:21:34.560462903 -0400 | |
@@ -26,6 +26,7 @@ | |
#define BSPWM_BSPWM_H | |
#include "types.h" | |
+#include "xcb/xcb_cursor.h" | |
#define WM_NAME "bspwm" | |
#define CONFIG_NAME WM_NAME "rc" | |
diff '--color=always' -ruN a/src/pointer.c b/src/pointer.c | |
--- a/src/pointer.c 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/src/pointer.c 2023-08-14 18:21:34.607131082 -0400 | |
@@ -35,6 +35,7 @@ | |
#include "events.h" | |
#include "window.h" | |
#include "pointer.h" | |
+#include <assert.h> | |
uint16_t num_lock; | |
uint16_t caps_lock; | |
@@ -43,6 +44,9 @@ | |
bool grabbing; | |
node_t *grabbed_node; | |
+xcb_cursor_context_t *cursor_context; | |
+xcb_cursor_t cursors[CURSOR_MAX]; | |
+ | |
void pointer_init(void) | |
{ | |
num_lock = modfield_from_keysym(XK_Num_Lock); | |
@@ -237,7 +241,45 @@ | |
return true; | |
} | |
- xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(dpy, xcb_grab_pointer(dpy, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME), NULL); | |
+ resize_handle_t rh = get_handle(loc.node, pos, pac); | |
+ | |
+ int cursor = 0; | |
+ if (pac == ACTION_MOVE) { | |
+ cursor = CURSOR_MOVE; | |
+ } else if (pac == ACTION_RESIZE_SIDE || pac == ACTION_RESIZE_CORNER) { | |
+ cursor = CURSOR_X; | |
+ if (loc.node->client->state == STATE_TILED) { | |
+ if (rh & HANDLE_LEFT) { | |
+ if (find_fence(loc.node, DIR_WEST) == NULL) | |
+ rh ^= HANDLE_LEFT; | |
+ } else if (rh & HANDLE_RIGHT) { | |
+ if (find_fence(loc.node, DIR_EAST) == NULL) | |
+ rh ^= HANDLE_RIGHT; | |
+ } | |
+ if (rh & HANDLE_TOP) { | |
+ if (find_fence(loc.node, DIR_NORTH) == NULL) | |
+ rh ^= HANDLE_TOP; | |
+ } else if (rh & HANDLE_BOTTOM) { | |
+ if (find_fence(loc.node, DIR_SOUTH) == NULL) | |
+ rh ^= HANDLE_BOTTOM; | |
+ } | |
+ } | |
+ if (rh == HANDLE_TOP_LEFT || rh == HANDLE_BOTTOM_RIGHT) { | |
+ cursor = CURSOR_RESIZE_TL; | |
+ } else if (rh == HANDLE_TOP_RIGHT || rh == HANDLE_BOTTOM_LEFT) { | |
+ cursor = CURSOR_RESIZE_TR; | |
+ } else { | |
+ if (rh & (HANDLE_TOP | HANDLE_BOTTOM)) { | |
+ cursor = CURSOR_RESIZE_V; | |
+ } else if (rh & (HANDLE_LEFT | HANDLE_RIGHT)) { | |
+ cursor = CURSOR_RESIZE_H; | |
+ } | |
+ } | |
+ } | |
+ xcb_cursor_t xcursor = cursor ? xcursor_get_cursor(cursor) : XCB_NONE; | |
+ | |
+ xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(dpy, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_MOTION, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, xcursor, XCB_CURRENT_TIME); | |
+ xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(dpy, cookie, NULL); | |
if (reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) { | |
free(reply); | |
@@ -253,15 +295,14 @@ | |
put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_side begin\n", loc.monitor->id, loc.desktop->id, loc.node->id); | |
} | |
- track_pointer(loc, pac, pos); | |
+ track_pointer(loc, pac, pos, rh); | |
return true; | |
} | |
-void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos) | |
+void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos, resize_handle_t rh) | |
{ | |
node_t *n = loc.node; | |
- resize_handle_t rh = get_handle(loc.node, pos, pac); | |
uint16_t last_motion_x = pos.x, last_motion_y = pos.y; | |
xcb_timestamp_t last_motion_time = 0; | |
@@ -312,7 +353,7 @@ | |
if (grabbed_node == NULL) { | |
grabbing = false; | |
return; | |
- } | |
+ } | |
if (pac == ACTION_MOVE) { | |
put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move end\n", loc.monitor->id, loc.desktop->id, n->id); | |
@@ -338,3 +379,29 @@ | |
} | |
} | |
} | |
+ | |
+void xcursor_load_cursors(void) { | |
+ if (xcb_cursor_context_new(dpy, screen, &cursor_context) < 0) { | |
+ warn("Couldn't create the cursor context.\n"); | |
+ } | |
+#define LOAD_CURSOR(constant, name) \ | |
+ do { \ | |
+ cursors[constant] = xcb_cursor_load_cursor(cursor_context, name); \ | |
+ } while (0) | |
+ LOAD_CURSOR(CURSOR_POINTER, "left_ptr"); | |
+ LOAD_CURSOR(CURSOR_RESIZE_H, "sb_h_double_arrow"); | |
+ LOAD_CURSOR(CURSOR_RESIZE_V, "sb_v_double_arrow"); | |
+ LOAD_CURSOR(CURSOR_MOVE, "fleur"); | |
+ LOAD_CURSOR(CURSOR_RESIZE_TL, "top_left_corner"); | |
+ LOAD_CURSOR(CURSOR_RESIZE_TR, "top_right_corner"); | |
+ LOAD_CURSOR(CURSOR_RESIZE_BL, "bottom_left_corner"); | |
+ LOAD_CURSOR(CURSOR_RESIZE_BR, "bottom_right_corner"); | |
+ LOAD_CURSOR(CURSOR_X, "X_cursor"); | |
+#undef LOAD_CURSOR | |
+} | |
+ | |
+ | |
+xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c) { | |
+ assert(c < CURSOR_MAX); | |
+ return cursors[c]; | |
+} | |
diff '--color=always' -ruN a/src/pointer.h b/src/pointer.h | |
--- a/src/pointer.h 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/src/pointer.h 2023-08-14 18:21:34.607131082 -0400 | |
@@ -21,6 +21,7 @@ | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
+#include <xcb/xcb_cursor.h> | |
#ifndef BSPWM_POINTER_H | |
#define BSPWM_POINTER_H | |
@@ -29,6 +30,20 @@ | |
#define XK_Caps_Lock 0xffe5 | |
#define XK_Scroll_Lock 0xff14 | |
+extern enum xcursor_cursor_t { | |
+ CURSOR_POINTER = 0, | |
+ CURSOR_RESIZE_H, | |
+ CURSOR_RESIZE_V, | |
+ CURSOR_RESIZE_TL, | |
+ CURSOR_RESIZE_TR, | |
+ CURSOR_RESIZE_BL, | |
+ CURSOR_RESIZE_BR, | |
+ CURSOR_MOVE, | |
+ CURSOR_X, | |
+ CURSOR_MAX | |
+}; | |
+ | |
+ | |
extern uint16_t num_lock; | |
extern uint16_t caps_lock; | |
extern uint16_t scroll_lock; | |
@@ -36,6 +51,8 @@ | |
extern bool grabbing; | |
extern node_t *grabbed_node; | |
+extern xcb_cursor_context_t *cursor_context; | |
+ | |
void pointer_init(void); | |
void window_grab_buttons(xcb_window_t win); | |
void window_grab_button(xcb_window_t win, uint8_t button, uint16_t modifier); | |
@@ -44,6 +61,8 @@ | |
int16_t modfield_from_keysym(xcb_keysym_t keysym); | |
resize_handle_t get_handle(node_t *n, xcb_point_t pos, pointer_action_t pac); | |
bool grab_pointer(pointer_action_t pac); | |
-void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos); | |
+void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos, resize_handle_t rh); | |
+void xcursor_load_cursors(void); | |
+xcb_cursor_t xcursor_get_cursor(enum xcursor_cursor_t c); | |
#endif | |
diff '--color=always' -ruN a/src/window.c b/src/window.c | |
--- a/src/window.c 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/src/window.c 2023-08-14 18:21:34.653799260 -0400 | |
@@ -27,6 +27,7 @@ | |
#include <stdbool.h> | |
#include <string.h> | |
#include <xcb/shape.h> | |
+#include <xcb/xcb_cursor.h> | |
#include "bspwm.h" | |
#include "ewmh.h" | |
#include "monitor.h" | |
@@ -917,6 +918,13 @@ | |
window_set_visibility(win, true); | |
} | |
+void window_set_cursor(xcb_window_t win, char *name) | |
+{ | |
+ xcb_cursor_t cursor = xcb_cursor_load_cursor(cursor_context, name); | |
+ uint32_t values[] = {cursor}; | |
+ xcb_change_window_attributes(dpy, win, XCB_CW_CURSOR, values); | |
+} | |
+ | |
void update_input_focus(void) | |
{ | |
set_input_focus(mon->desk->focus); | |
diff '--color=always' -ruN a/src/window.h b/src/window.h | |
--- a/src/window.h 2023-08-14 18:21:17.209838188 -0400 | |
+++ b/src/window.h 2023-08-14 18:21:34.657132703 -0400 | |
@@ -68,6 +68,7 @@ | |
void window_set_visibility(xcb_window_t win, bool visible); | |
void window_hide(xcb_window_t win); | |
void window_show(xcb_window_t win); | |
+void window_set_cursor(xcb_window_t, char *); | |
void update_input_focus(void); | |
void set_input_focus(node_t *n); | |
void clear_input_focus(void); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment