]> git.sur5r.net Git - i3/i3lock/blobdiff - xcb.c
manpage: add missing "specify" (Thanks xeen)
[i3/i3lock] / xcb.c
diff --git a/xcb.c b/xcb.c
index 5627af1c09a7c0ae0f02e64abced53a8e3b32047..bf9f9948c134e5c4468189b18e64c77f27d3b9a7 100644 (file)
--- a/xcb.c
+++ b/xcb.c
@@ -9,13 +9,41 @@
  */
 #include <xcb/xcb.h>
 #include <xcb/xcb_keysyms.h>
+#include <xcb/xcb_image.h>
 #include <xcb/dpms.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <unistd.h>
 #include <assert.h>
 #include <err.h>
 
+#include "cursors.h"
+
+#define curs_invisible_width 8
+#define curs_invisible_height 8
+
+static unsigned char curs_invisible_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+#define curs_windows_width 11
+#define curs_windows_height 19
+
+static unsigned char curs_windows_bits[] = {
+ 0xfe, 0x07, 0xfc, 0x07, 0xfa, 0x07, 0xf6, 0x07, 0xee, 0x07, 0xde, 0x07,
+ 0xbe, 0x07, 0x7e, 0x07, 0xfe, 0x06, 0xfe, 0x05, 0x3e, 0x00, 0xb6, 0x07,
+ 0x6a, 0x07, 0x6c, 0x07, 0xde, 0x06, 0xdf, 0x06, 0xbf, 0x05, 0xbf, 0x05,
+ 0x7f, 0x06 };
+
+#define mask_windows_width 11
+#define mask_windows_height 19
+
+static unsigned char mask_windows_bits[] = {
+ 0x01, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00,
+ 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01, 0xff, 0x03, 0xff, 0x07, 0x7f, 0x00,
+ 0xf7, 0x00, 0xf3, 0x00, 0xe1, 0x01, 0xe0, 0x01, 0xc0, 0x03, 0xc0, 0x03,
+ 0x80, 0x01 };
+
 static uint32_t get_colorpixel(char *hex) {
     char strgroups[3][3] = {{hex[0], hex[1], '\0'},
                             {hex[2], hex[3], '\0'},
@@ -62,7 +90,10 @@ xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, c
     values[1] = 1;
 
     mask |= XCB_CW_EVENT_MASK;
-    values[2] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE;
+    values[2] = XCB_EVENT_MASK_EXPOSURE |
+                XCB_EVENT_MASK_KEY_PRESS |
+                XCB_EVENT_MASK_KEY_RELEASE |
+                XCB_EVENT_MASK_VISIBILITY_CHANGE;
 
     xcb_create_window(conn,
                       24,
@@ -128,14 +159,14 @@ 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;
 
     xcb_grab_keyboard_cookie_t kcookie;
     xcb_grab_keyboard_reply_t *kreply;
 
-    int tries = 1000;
+    int tries = 10000;
 
     while (tries-- > 0) {
         pcookie = xcb_grab_pointer(
@@ -146,7 +177,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
         );
 
@@ -155,8 +186,14 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen) {
             free(preply);
             break;
         }
+
+        /* Make this quite a bit slower */
+        usleep(50);
     }
 
+    if (cursor != XCB_NONE)
+        xcb_free_cursor(conn, cursor);
+
     while (tries-- > 0) {
         kcookie = xcb_grab_keyboard(
             conn,
@@ -172,8 +209,74 @@ void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen) {
             free(kreply);
             break;
         }
+
+        /* Make this quite a bit slower */
+        usleep(50);
     }
 
-    if (tries == 0)
+    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;
+}