From 0c4b4df75ecaa79081cda1d488e64e16bc64277b Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Mon, 19 Jul 2010 23:15:50 +0200 Subject: [PATCH] Port the pointer-code to xcb --- Makefile | 2 +- cursors.h | 4 +++ debian/control | 2 +- i3lock.c | 14 ++++++++-- xcb.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++-- xcb.h | 3 ++- 6 files changed, 91 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9d3fb50..7cb5052 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ CFLAGS += -pipe CFLAGS += -Wall CFLAGS += -D_GNU_SOURCE CFLAGS += $(shell pkg-config --cflags cairo xcb-keysyms xcb-dpms) -LDFLAGS += $(shell pkg-config --libs cairo xcb-keysyms xcb-dpms) +LDFLAGS += $(shell pkg-config --libs cairo xcb-keysyms xcb-dpms xcb-image) LDFLAGS += -lpam FILES:=$(wildcard *.c) diff --git a/cursors.h b/cursors.h index 6a0b1f8..23fd30f 100644 --- a/cursors.h +++ b/cursors.h @@ -1,3 +1,7 @@ +#define CURS_NONE 0 +#define CURS_WIN 1 +#define CURS_DEFAULT 2 + #define curs_invisible_width 8 #define curs_invisible_height 8 diff --git a/debian/control b/debian/control index 204b750..436124d 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: utils Priority: extra Maintainer: Michael Stapelberg DM-Upload-Allowed: yes -Build-Depends: debhelper (>= 5), libx11-dev, libpam0g-dev, libcairo2-dev, libxcb1-dev, libxcb-dpms0-dev, libxcb-keysyms1-dev +Build-Depends: debhelper (>= 5), libx11-dev, libpam0g-dev, libcairo2-dev, libxcb1-dev, libxcb-dpms0-dev, libxcb-keysyms1-dev, libxcb-image0-dev Standards-Version: 3.8.2 Homepage: http://i3.zekjur.net/i3lock/ diff --git a/i3lock.c b/i3lock.c index 22317fc..5df9f26 100644 --- a/i3lock.c +++ b/i3lock.c @@ -27,6 +27,7 @@ #include "keysym2ucs.h" #include "ucs2_to_utf8.h" #include "xcb.h" +#include "cursors.h" static xcb_connection_t *conn; static xcb_key_symbols_t *symbols; @@ -230,6 +231,8 @@ int main(int argc, char *argv[]) { xcb_generic_event_t *event; xcb_screen_t *scr; xcb_window_t win; + xcb_cursor_t cursor; + int curs_choice = CURS_NONE; char o; int optind = 0; struct option longopts[] = { @@ -279,7 +282,12 @@ int main(int argc, char *argv[]) { /* TODO: tile image */ break; case 'p': - /* TODO: cursor */ + if (!strcmp(optarg, "win")) { + curs_choice = CURS_WIN; + } + if (!strcmp(optarg, "default")) { + curs_choice = CURS_DEFAULT; + } break; default: errx(1, "i3lock: Unknown option. Syntax: i3lock [-v] [-n] [-b] [-d] [-i image.png] [-c color] [-t] [-p win|default]\n"); @@ -319,7 +327,9 @@ int main(int argc, char *argv[]) { * ready to handle the expose event immediately afterwards) */ win = open_fullscreen_window(conn, scr, color); - grab_pointer_and_keyboard(conn, scr); + cursor = create_cursor(conn, scr, win, curs_choice); + + grab_pointer_and_keyboard(conn, scr, cursor); if (image_path) img = cairo_image_surface_create_from_png(image_path); diff --git a/xcb.c b/xcb.c index 41b007a..70f1374 100644 --- a/xcb.c +++ b/xcb.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -17,6 +18,8 @@ #include #include +#include "cursors.h" + static uint32_t get_colorpixel(char *hex) { char strgroups[3][3] = {{hex[0], hex[1], '\0'}, {hex[2], hex[3], '\0'}, @@ -132,7 +135,7 @@ void dpms_turn_off_screen(xcb_connection_t *conn) { * Repeatedly tries to grab pointer and keyboard (up to 1000 times). * */ -void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen) { +void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor) { xcb_grab_pointer_cookie_t pcookie; xcb_grab_pointer_reply_t *preply; @@ -150,7 +153,7 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen) { XCB_GRAB_MODE_ASYNC, /* pointer events should continue as normal */ XCB_GRAB_MODE_ASYNC, /* keyboard mode */ XCB_NONE, /* confine_to = in which window should the cursor stay */ - XCB_NONE, /* don’t display a special cursor */ + cursor, /* we change the cursor to whatever the user wanted */ XCB_CURRENT_TIME ); @@ -164,6 +167,9 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen) { usleep(50); } + if (cursor != XCB_NONE) + xcb_free_cursor(conn, cursor); + while (tries-- > 0) { kcookie = xcb_grab_keyboard( conn, @@ -187,3 +193,66 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen) { if (tries <= 0) errx(EXIT_FAILURE, "Cannot grab pointer/keyboard"); } + +xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice) { + xcb_pixmap_t bitmap; + xcb_pixmap_t mask; + xcb_cursor_t cursor; + + unsigned char* curs_bits; + unsigned char* mask_bits; + int curs_w, curs_h; + + switch (choice) { + case CURS_NONE: + curs_bits = curs_invisible_bits; + mask_bits = curs_invisible_bits; + curs_w = curs_invisible_width; + curs_h = curs_invisible_height; + break; + case CURS_WIN: + curs_bits = curs_windows_bits; + mask_bits = mask_windows_bits; + curs_w = curs_windows_width; + curs_h = curs_windows_height; + break; + case CURS_DEFAULT: + default: + return XCB_NONE; /* XCB_NONE is xcb's way of saying "don't change the cursor" */ + } + + bitmap = xcb_create_pixmap_from_bitmap_data(conn, + win, + curs_bits, + curs_w, + curs_h, + 1, + screen->white_pixel, + screen->black_pixel, + NULL); + + mask = xcb_create_pixmap_from_bitmap_data(conn, + win, + mask_bits, + curs_w, + curs_h, + 1, + screen->white_pixel, + screen->black_pixel, + NULL); + + cursor = xcb_generate_id(conn); + + xcb_create_cursor(conn, + cursor, + bitmap, + mask, + 65535,65535,65535, + 0,0,0, + 0,0); + + xcb_free_pixmap(conn, bitmap); + xcb_free_pixmap(conn, mask); + + return cursor; +} diff --git a/xcb.h b/xcb.h index 6659024..bae51b2 100644 --- a/xcb.h +++ b/xcb.h @@ -5,8 +5,9 @@ xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s); xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color); -void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen); +void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_t cursor); uint32_t get_mod_mask(xcb_connection_t *conn, xcb_key_symbols_t *symbols, uint32_t keycode); void dpms_turn_off_screen(xcb_connection_t *conn); +xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, xcb_window_t win, int choice); #endif