Skip to content

Instantly share code, notes, and snippets.

@ortango
Created September 20, 2023 00:04
Show Gist options
  • Save ortango/442d8aa6812c24a955f902eaa42fb715 to your computer and use it in GitHub Desktop.
Save ortango/442d8aa6812c24a955f902eaa42fb715 to your computer and use it in GitHub Desktop.
qwikndutty xcursor support for moving and resizing windows
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