Skip to content

Commit c06ff2c

Browse files
fix: mouse cursor properly restored after typing hides it
showCursor was using XCB_CURSOR_NONE (0) which doesn't reliably restore the cursor on all X11 setups. Now creates a proper left_ptr cursor from the X11 cursor font (glyph 68) at init and restores it explicitly.
1 parent a92a783 commit c06ff2c

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

src/platform/linux/x11.zig

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ extern "xcb" fn xcb_create_pixmap(conn: *xcb_connection_t, depth: u8, pid: u32,
184184
extern "xcb" fn xcb_free_pixmap(conn: *xcb_connection_t, pixmap: u32) callconv(.c) xcb_void_cookie_t;
185185
extern "xcb" fn xcb_create_cursor(conn: *xcb_connection_t, cid: u32, source: u32, mask: u32, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16, x: u16, y: u16) callconv(.c) xcb_void_cookie_t;
186186
extern "xcb" fn xcb_free_cursor(conn: *xcb_connection_t, cursor: u32) callconv(.c) xcb_void_cookie_t;
187+
extern "xcb" fn xcb_open_font(conn: *xcb_connection_t, fid: u32, name_len: u16, name: [*]const u8) callconv(.c) xcb_void_cookie_t;
188+
extern "xcb" fn xcb_close_font(conn: *xcb_connection_t, fid: u32) callconv(.c) xcb_void_cookie_t;
189+
extern "xcb" fn xcb_create_glyph_cursor(conn: *xcb_connection_t, cid: u32, source_font: u32, mask_font: u32, source_char: u16, mask_char: u16, fore_red: u16, fore_green: u16, fore_blue: u16, back_red: u16, back_green: u16, back_blue: u16) callconv(.c) xcb_void_cookie_t;
187190
extern "xcb" fn xcb_change_window_attributes(conn: *xcb_connection_t, window: xcb_window_t, value_mask: u32, value_list: ?*const anyopaque) callconv(.c) xcb_void_cookie_t;
188191
extern "xcb" fn xcb_configure_window(conn: *xcb_connection_t, window: xcb_window_t, value_mask: u16, value_list: *const anyopaque) callconv(.c) xcb_void_cookie_t;
189192

@@ -208,8 +211,9 @@ pub const X11Window = struct {
208211
wm_delete_window: xcb_atom_t,
209212
depth: u8,
210213

211-
// Invisible cursor for mouse_hide_when_typing
214+
// Cursors for mouse_hide_when_typing
212215
invisible_cursor: u32 = 0,
216+
default_cursor: u32 = 0,
213217

214218
// SHM state (zero-copy framebuffer)
215219
shm_seg: xcb_shm_seg_t = 0,
@@ -307,13 +311,22 @@ pub const X11Window = struct {
307311
// Try to set up SHM for zero-copy framebuffer
308312
self.setupShm(width, height);
309313

310-
// Create invisible cursor for mouse_hide_when_typing
314+
// Create cursors for mouse_hide_when_typing
315+
// Invisible cursor: 1x1 blank pixmap
311316
const pixmap = xcb_generate_id(connection);
312317
_ = xcb_create_pixmap(connection, 1, pixmap, win_id, 1, 1);
313318
self.invisible_cursor = xcb_generate_id(connection);
314319
_ = xcb_create_cursor(connection, self.invisible_cursor, pixmap, pixmap, 0, 0, 0, 0, 0, 0, 0, 0);
315320
_ = xcb_free_pixmap(connection, pixmap);
316321

322+
// Default cursor: left_ptr from X11 cursor font (glyph 68)
323+
const cursor_font = xcb_generate_id(connection);
324+
_ = xcb_open_font(connection, cursor_font, 6, "cursor");
325+
self.default_cursor = xcb_generate_id(connection);
326+
// XC_left_ptr = 68, mask = 69 (next glyph)
327+
_ = xcb_create_glyph_cursor(connection, self.default_cursor, cursor_font, cursor_font, 68, 69, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF);
328+
_ = xcb_close_font(connection, cursor_font);
329+
317330
return self;
318331
}
319332

@@ -325,13 +338,14 @@ pub const X11Window = struct {
325338
}
326339

327340
pub fn showCursor(self: *X11Window) void {
328-
const cursor_val = [1]u32{0}; // XCB_CURSOR_NONE restores default
341+
const cursor_val = [1]u32{self.default_cursor};
329342
_ = xcb_change_window_attributes(self.connection, self.window, XCB_CW_CURSOR, &cursor_val);
330343
_ = xcb_flush(self.connection);
331344
}
332345

333346
pub fn deinit(self: *X11Window) void {
334347
if (self.invisible_cursor != 0) _ = xcb_free_cursor(self.connection, self.invisible_cursor);
348+
if (self.default_cursor != 0) _ = xcb_free_cursor(self.connection, self.default_cursor);
335349
self.teardownShm();
336350
_ = xcb_free_gc(self.connection, self.gc);
337351
_ = xcb_destroy_window(self.connection, self.window);

0 commit comments

Comments
 (0)