]> git.sur5r.net Git - i3/i3lock/commitdiff
Refactor the unlock indicator into its own source code file
authorMichael Stapelberg <michael@stapelberg.de>
Tue, 3 Jan 2012 20:56:05 +0000 (20:56 +0000)
committerMichael Stapelberg <michael@stapelberg.de>
Tue, 3 Jan 2012 20:56:05 +0000 (20:56 +0000)
i3lock.c
unlock_indicator.c [new file with mode: 0644]
unlock_indicator.h [new file with mode: 0644]
xcb.c
xcb.h

index f9255d7241e3cf0b7a3e16acbe1f82391f5fc12d..8a365f30ea83a4ada902862a8f2ab83cbfa6c9f7 100644 (file)
--- a/i3lock.c
+++ b/i3lock.c
@@ -22,7 +22,6 @@
 #include <X11/keysym.h>
 #include <getopt.h>
 #include <string.h>
-#include <math.h>
 #include <ev.h>
 #include <sys/mman.h>
 
 #include "ucs2_to_utf8.h"
 #include "xcb.h"
 #include "cursors.h"
+#include "unlock_indicator.h"
 
-#define BUTTON_RADIUS 90
-#define BUTTON_SPACE (BUTTON_RADIUS + 5)
-#define BUTTON_CENTER (BUTTON_RADIUS + 5)
-#define BUTTON_DIAMETER (5 * BUTTON_SPACE)
-
-static char color[7] = "ffffff";
-static uint32_t last_resolution[2];
-static xcb_connection_t *conn;
-static xcb_window_t win;
-static xcb_visualtype_t *vistype;
+char color[7] = "ffffff";
+uint32_t last_resolution[2];
+xcb_window_t win;
 static xcb_cursor_t cursor;
 static xcb_key_symbols_t *symbols;
-static xcb_screen_t *scr;
 static pam_handle_t *pam_handle;
 static int input_position = 0;
 /* Holds the password you enter (in UTF-8). */
@@ -62,26 +54,13 @@ static int numlockmask;
 static bool beep = false;
 static bool debug_mode = false;
 static bool dpms = false;
-static bool unlock_indicator = true;
+bool unlock_indicator = true;
 static bool dont_fork = false;
 static struct ev_loop *main_loop;
 static struct ev_timer *clear_pam_wrong_timeout;
 static struct ev_timer *clear_indicator_timeout;
-
-static enum {
-    STATE_STARTED = 0,          /* default state */
-    STATE_KEY_PRESSED = 1,      /* key was pressed, show unlock indicator */
-    STATE_KEY_ACTIVE = 2,       /* a key was pressed recently, highlight part
-                                   of the unlock indicator. */
-    STATE_BACKSPACE_ACTIVE = 3  /* backspace was pressed recently, highlight
-                                   part of the unlock indicator in red. */
-} unlock_state;
-
-static enum {
-    STATE_PAM_IDLE = 0,         /* no PAM interaction at the moment */
-    STATE_PAM_VERIFY = 1,       /* currently verifying the password via PAM */
-    STATE_PAM_WRONG = 2         /* the password was wrong */
-} pam_state;
+extern unlock_state_t unlock_state;
+extern pam_state_t pam_state;
 
 #define DEBUG(fmt, ...) do { \
     if (debug_mode) \
@@ -89,8 +68,8 @@ static enum {
 } while (0)
 
 #ifndef NOLIBCAIRO
-static cairo_surface_t *img = NULL;
-static bool tile = false;
+cairo_surface_t *img = NULL;
+bool tile = false;
 #endif
 
 /*
@@ -110,188 +89,6 @@ static void clear_password_memory() {
         vpassword[c] = c + (int)beep;
 }
 
-/*
- * Draws global image with fill color onto a pixmap with the given
- * resolution and returns it.
- *
- */
-static xcb_pixmap_t draw_image(xcb_visualtype_t *vistype, u_int32_t* resolution) {
-    xcb_pixmap_t bg_pixmap = XCB_NONE;
-
-#ifndef NOLIBCAIRO
-    bg_pixmap = create_bg_pixmap(conn, scr, resolution, color);
-    /* Initialize cairo */
-    cairo_surface_t *output;
-    output = cairo_xcb_surface_create(conn, bg_pixmap, vistype,
-             resolution[0], resolution[1]);
-    cairo_t *ctx = cairo_create(output);
-    if (img) {
-        if (!tile) {
-            cairo_set_source_surface(ctx, img, 0, 0);
-            cairo_paint(ctx);
-        } else {
-            /* create a pattern and fill a rectangle as big as the screen */
-            cairo_pattern_t *pattern;
-            pattern = cairo_pattern_create_for_surface(img);
-            cairo_set_source(ctx, pattern);
-            cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
-            cairo_rectangle(ctx, 0, 0, resolution[0], resolution[1]);
-            cairo_fill(ctx);
-            cairo_pattern_destroy(pattern);
-        }
-    }
-
-    if (unlock_state >= STATE_KEY_PRESSED && unlock_indicator) {
-        cairo_pattern_t *outer_pat = NULL;
-
-        outer_pat = cairo_pattern_create_linear(0, 0, 0, BUTTON_DIAMETER);
-        switch (pam_state) {
-            case STATE_PAM_VERIFY:
-                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 139.0/255, 0, 250.0/255);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 51.0/255, 0, 250.0/255);
-                break;
-            case STATE_PAM_WRONG:
-                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 255.0/250, 139.0/255, 0);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 125.0/255, 51.0/255, 0);
-                break;
-            case STATE_PAM_IDLE:
-                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 139.0/255, 125.0/255, 0);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 51.0/255, 125.0/255, 0);
-                break;
-        }
-
-        /* Draw a (centered) circle with transparent background. */
-        cairo_set_line_width(ctx, 10.0);
-        cairo_arc(ctx,
-                  (resolution[0] / 2) /* x */,
-                  (resolution[1] / 2) /* y */,
-                  BUTTON_RADIUS /* radius */,
-                  0 /* start */,
-                  2 * M_PI /* end */);
-
-        /* Use the appropriate color for the different PAM states
-         * (currently verifying, wrong password, or default) */
-        switch (pam_state) {
-            case STATE_PAM_VERIFY:
-                cairo_set_source_rgba(ctx, 0, 114.0/255, 255.0/255, 0.75);
-                break;
-            case STATE_PAM_WRONG:
-                cairo_set_source_rgba(ctx, 250.0/255, 0, 0, 0.75);
-                break;
-            default:
-                cairo_set_source_rgba(ctx, 0, 0, 0, 0.75);
-                break;
-        }
-        cairo_fill_preserve(ctx);
-        cairo_set_source(ctx, outer_pat);
-        cairo_stroke(ctx);
-
-        /* Draw an inner seperator line. */
-        cairo_set_source_rgb(ctx, 0, 0, 0);
-        cairo_set_line_width(ctx, 2.0);
-        cairo_arc(ctx,
-                  (resolution[0] / 2) /* x */,
-                  (resolution[1] / 2) /* y */,
-                  BUTTON_RADIUS - 5 /* radius */,
-                  0,
-                  2 * M_PI);
-        cairo_stroke(ctx);
-
-        cairo_set_line_width(ctx, 10.0);
-
-        /* Display a (centered) text of the current PAM state. */
-        char *text = NULL;
-        switch (pam_state) {
-            case STATE_PAM_VERIFY:
-                text = "verifying…";
-                break;
-            case STATE_PAM_WRONG:
-                text = "wrong!";
-                break;
-            default:
-                break;
-        }
-
-        if (text) {
-            cairo_text_extents_t extents;
-            double x, y;
-
-            cairo_set_source_rgb(ctx, 0, 0, 0);
-            cairo_set_font_size(ctx, 28.0);
-
-            cairo_text_extents(ctx, text, &extents);
-            x = (resolution[0] / 2.0) - ((extents.width / 2) + extents.x_bearing);
-            y = (resolution[1] / 2.0) - ((extents.height / 2) + extents.y_bearing);
-
-            cairo_move_to(ctx, x, y);
-            cairo_show_text(ctx, text);
-            cairo_close_path(ctx);
-        }
-
-        /* After the user pressed any valid key or the backspace key, we
-         * highlight a random part of the unlock indicator to confirm this
-         * keypress. */
-        if (unlock_state == STATE_KEY_ACTIVE ||
-            unlock_state == STATE_BACKSPACE_ACTIVE) {
-            cairo_new_sub_path(ctx);
-            double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0;
-            DEBUG("Highlighting part %.2f\n", highlight_start);
-            cairo_arc(ctx, resolution[0] / 2 /* x */, resolution[1] / 2 /* y */,
-                      BUTTON_RADIUS /* radius */, highlight_start,
-                      highlight_start + (M_PI / 3.0));
-            if (unlock_state == STATE_KEY_ACTIVE) {
-                /* For normal keys, we use a lighter green. */
-                outer_pat = cairo_pattern_create_linear(0, 0, 0, BUTTON_DIAMETER);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 139.0/255, 219.0/255, 0);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 51.0/255, 219.0/255, 0);
-            } else {
-                /* For backspace, we use red. */
-                outer_pat = cairo_pattern_create_linear(0, 0, 0, BUTTON_DIAMETER);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 219.0/255, 139.0/255, 0);
-                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 219.0/255, 51.0/255, 0);
-            }
-            cairo_set_source(ctx, outer_pat);
-            cairo_stroke(ctx);
-
-            /* Draw two little separators for the highlighted part of the
-             * unlock indicator. */
-            cairo_set_source_rgb(ctx, 0, 0, 0);
-            cairo_arc(ctx,
-                      (resolution[0] / 2) /* x */,
-                      (resolution[1] / 2) /* y */,
-                      BUTTON_RADIUS /* radius */,
-                      highlight_start /* start */,
-                      highlight_start + (M_PI / 128.0) /* end */);
-            cairo_stroke(ctx);
-            cairo_arc(ctx,
-                      (resolution[0] / 2) /* x */,
-                      (resolution[1] / 2) /* y */,
-                      BUTTON_RADIUS /* radius */,
-                      highlight_start + (M_PI / 3.0) /* start */,
-                      (highlight_start + (M_PI / 3.0)) + (M_PI / 128.0) /* end */);
-            cairo_stroke(ctx);
-        }
-    }
-
-    cairo_surface_destroy(output);
-    cairo_destroy(ctx);
-#endif
-    return bg_pixmap;
-}
-
-/*
- * Calls draw_image on a new pixmap and swaps that with the current pixmap
- *
- */
-static void redraw_screen() {
-    xcb_pixmap_t bg_pixmap = draw_image(vistype, last_resolution);
-    xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){ bg_pixmap });
-    /* XXX: Possible optimization: Only update the area in the middle of the
-     * screen instead of the whole screen. */
-    xcb_clear_area(conn, 0, win, 0, 0, scr->width_in_pixels, scr->height_in_pixels);
-    xcb_free_pixmap(conn, bg_pixmap);
-    xcb_flush(conn);
-}
 
 /*
  * Resets pam_state to STATE_PAM_IDLE 2 seconds after an unsuccesful
@@ -594,10 +391,10 @@ static void handle_mapping_notify(xcb_mapping_notify_event_t *event) {
  * and also redraw the image, if any.
  *
  */
-void handle_screen_resize(xcb_visualtype_t *vistype, xcb_window_t win, uint32_t* last_resolution) {
+void handle_screen_resize(xcb_window_t win, uint32_t* last_resolution) {
     xcb_get_geometry_cookie_t geomc;
     xcb_get_geometry_reply_t *geom;
-    geomc = xcb_get_geometry(conn, scr->root);
+    geomc = xcb_get_geometry(conn, screen->root);
     if ((geom = xcb_get_geometry_reply(conn, geomc, 0)) == NULL) {
       return;
     }
@@ -609,11 +406,7 @@ void handle_screen_resize(xcb_visualtype_t *vistype, xcb_window_t win, uint32_t*
     last_resolution[1] = geom->height;
 
 #ifndef NOLIBCAIRO
-    if (img) {
-        xcb_pixmap_t bg_pixmap = draw_image(vistype, last_resolution);
-        xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){ bg_pixmap });
-        xcb_free_pixmap(conn, bg_pixmap);
-    }
+    redraw_screen();
 #endif
 
     uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
@@ -730,7 +523,7 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
         }
 
         if (type == XCB_CONFIGURE_NOTIFY) {
-            handle_screen_resize(vistype, win, last_resolution);
+            handle_screen_resize(win, last_resolution);
             continue;
         }
 
@@ -747,7 +540,7 @@ int main(int argc, char *argv[]) {
 #endif
     int ret;
     struct pam_conv conv = {conv_callback, NULL};
-    int screen;
+    int nscreen;
     int curs_choice = CURS_NONE;
     char o;
     int optind = 0;
@@ -851,7 +644,7 @@ int main(int argc, char *argv[]) {
         err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK");
 
     /* Initialize connection to X11 */
-    if ((conn = xcb_connect(NULL, &screen)) == NULL ||
+    if ((conn = xcb_connect(NULL, &nscreen)) == NULL ||
         xcb_connection_has_error(conn))
         errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?");
 
@@ -865,11 +658,10 @@ int main(int argc, char *argv[]) {
         }
     }
 
-    scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
-    vistype = get_root_visual_type(scr);
+    screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
 
-    last_resolution[0] = scr->width_in_pixels;
-    last_resolution[1] = scr->height_in_pixels;
+    last_resolution[0] = screen->width_in_pixels;
+    last_resolution[1] = screen->height_in_pixels;
 
 
 #ifndef NOLIBCAIRO
@@ -880,15 +672,15 @@ int main(int argc, char *argv[]) {
 #endif
 
     /* Pixmap on which the image is rendered to (if any) */
-    xcb_pixmap_t bg_pixmap = draw_image(vistype, last_resolution);
+    xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
 
     /* open the fullscreen window, already with the correct pixmap in place */
-    win = open_fullscreen_window(conn, scr, color, bg_pixmap);
+    win = open_fullscreen_window(conn, screen, color, bg_pixmap);
     xcb_free_pixmap(conn, bg_pixmap);
 
-    cursor = create_cursor(conn, scr, win, curs_choice);
+    cursor = create_cursor(conn, screen, win, curs_choice);
 
-    grab_pointer_and_keyboard(conn, scr, cursor);
+    grab_pointer_and_keyboard(conn, screen, cursor);
 
     symbols = xcb_key_symbols_alloc(conn);
     modeswitchmask = get_mod_mask(conn, symbols, XK_Mode_switch);
diff --git a/unlock_indicator.c b/unlock_indicator.c
new file mode 100644 (file)
index 0000000..2c4d054
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * vim:ts=4:sw=4:expandtab
+ *
+ * © 2010-2012 Michael Stapelberg
+ *
+ * See LICENSE for licensing information
+ *
+ */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <math.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_keysyms.h>
+
+#ifndef NOLIBCAIRO
+#include <cairo.h>
+#include <cairo/cairo-xcb.h>
+#endif
+
+#include "xcb.h"
+#include "unlock_indicator.h"
+
+#define BUTTON_RADIUS 90
+#define BUTTON_SPACE (BUTTON_RADIUS + 5)
+#define BUTTON_CENTER (BUTTON_RADIUS + 5)
+#define BUTTON_DIAMETER (5 * BUTTON_SPACE)
+
+/*******************************************************************************
+ * Variables defined in i3lock.c.
+ ******************************************************************************/
+
+/* The lock window. */
+extern xcb_window_t win;
+
+/* The current resolution of the X11 root window. */
+extern uint32_t last_resolution[2];
+
+/* Whether the unlock indicator is enabled (defaults to true). */
+extern bool unlock_indicator;
+
+/* A Cairo surface containing the specified image (-i), if any. */
+extern cairo_surface_t *img;
+/* Whether the image should be tiled. */
+extern bool tile;
+/* The background color to use (in hex). */
+extern char color[7];
+
+/*******************************************************************************
+ * Local variables.
+ ******************************************************************************/
+
+/* Cache the screen’s visual, necessary for creating a Cairo context. */
+static xcb_visualtype_t *vistype;
+
+/* Maintain the current unlock/PAM state to draw the appropriate unlock
+ * indicator. */
+unlock_state_t unlock_state;
+pam_state_t pam_state;
+
+/*
+ * Draws global image with fill color onto a pixmap with the given
+ * resolution and returns it.
+ *
+ */
+xcb_pixmap_t draw_image(uint32_t *resolution) {
+    xcb_pixmap_t bg_pixmap = XCB_NONE;
+
+#ifndef NOLIBCAIRO
+    if (!vistype)
+        vistype = get_root_visual_type(screen);
+    bg_pixmap = create_bg_pixmap(conn, screen, resolution, color);
+    /* Initialize cairo */
+    cairo_surface_t *output;
+    output = cairo_xcb_surface_create(conn, bg_pixmap, vistype,
+             resolution[0], resolution[1]);
+    cairo_t *ctx = cairo_create(output);
+    if (img) {
+        if (!tile) {
+            cairo_set_source_surface(ctx, img, 0, 0);
+            cairo_paint(ctx);
+        } else {
+            /* create a pattern and fill a rectangle as big as the screen */
+            cairo_pattern_t *pattern;
+            pattern = cairo_pattern_create_for_surface(img);
+            cairo_set_source(ctx, pattern);
+            cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+            cairo_rectangle(ctx, 0, 0, resolution[0], resolution[1]);
+            cairo_fill(ctx);
+            cairo_pattern_destroy(pattern);
+        }
+    }
+
+    if (unlock_state >= STATE_KEY_PRESSED && unlock_indicator) {
+        cairo_pattern_t *outer_pat = NULL;
+
+        outer_pat = cairo_pattern_create_linear(0, 0, 0, BUTTON_DIAMETER);
+        switch (pam_state) {
+            case STATE_PAM_VERIFY:
+                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 139.0/255, 0, 250.0/255);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 51.0/255, 0, 250.0/255);
+                break;
+            case STATE_PAM_WRONG:
+                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 255.0/250, 139.0/255, 0);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 125.0/255, 51.0/255, 0);
+                break;
+            case STATE_PAM_IDLE:
+                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 139.0/255, 125.0/255, 0);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 51.0/255, 125.0/255, 0);
+                break;
+        }
+
+        /* Draw a (centered) circle with transparent background. */
+        cairo_set_line_width(ctx, 10.0);
+        cairo_arc(ctx,
+                  (resolution[0] / 2) /* x */,
+                  (resolution[1] / 2) /* y */,
+                  BUTTON_RADIUS /* radius */,
+                  0 /* start */,
+                  2 * M_PI /* end */);
+
+        /* Use the appropriate color for the different PAM states
+         * (currently verifying, wrong password, or default) */
+        switch (pam_state) {
+            case STATE_PAM_VERIFY:
+                cairo_set_source_rgba(ctx, 0, 114.0/255, 255.0/255, 0.75);
+                break;
+            case STATE_PAM_WRONG:
+                cairo_set_source_rgba(ctx, 250.0/255, 0, 0, 0.75);
+                break;
+            default:
+                cairo_set_source_rgba(ctx, 0, 0, 0, 0.75);
+                break;
+        }
+        cairo_fill_preserve(ctx);
+        cairo_set_source(ctx, outer_pat);
+        cairo_stroke(ctx);
+
+        /* Draw an inner seperator line. */
+        cairo_set_source_rgb(ctx, 0, 0, 0);
+        cairo_set_line_width(ctx, 2.0);
+        cairo_arc(ctx,
+                  (resolution[0] / 2) /* x */,
+                  (resolution[1] / 2) /* y */,
+                  BUTTON_RADIUS - 5 /* radius */,
+                  0,
+                  2 * M_PI);
+        cairo_stroke(ctx);
+
+        cairo_set_line_width(ctx, 10.0);
+
+        /* Display a (centered) text of the current PAM state. */
+        char *text = NULL;
+        switch (pam_state) {
+            case STATE_PAM_VERIFY:
+                text = "verifying…";
+                break;
+            case STATE_PAM_WRONG:
+                text = "wrong!";
+                break;
+            default:
+                break;
+        }
+
+        if (text) {
+            cairo_text_extents_t extents;
+            double x, y;
+
+            cairo_set_source_rgb(ctx, 0, 0, 0);
+            cairo_set_font_size(ctx, 28.0);
+
+            cairo_text_extents(ctx, text, &extents);
+            x = (resolution[0] / 2.0) - ((extents.width / 2) + extents.x_bearing);
+            y = (resolution[1] / 2.0) - ((extents.height / 2) + extents.y_bearing);
+
+            cairo_move_to(ctx, x, y);
+            cairo_show_text(ctx, text);
+            cairo_close_path(ctx);
+        }
+
+        /* After the user pressed any valid key or the backspace key, we
+         * highlight a random part of the unlock indicator to confirm this
+         * keypress. */
+        if (unlock_state == STATE_KEY_ACTIVE ||
+            unlock_state == STATE_BACKSPACE_ACTIVE) {
+            cairo_new_sub_path(ctx);
+            double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0;
+            cairo_arc(ctx, resolution[0] / 2 /* x */, resolution[1] / 2 /* y */,
+                      BUTTON_RADIUS /* radius */, highlight_start,
+                      highlight_start + (M_PI / 3.0));
+            if (unlock_state == STATE_KEY_ACTIVE) {
+                /* For normal keys, we use a lighter green. */
+                outer_pat = cairo_pattern_create_linear(0, 0, 0, BUTTON_DIAMETER);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 139.0/255, 219.0/255, 0);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 51.0/255, 219.0/255, 0);
+            } else {
+                /* For backspace, we use red. */
+                outer_pat = cairo_pattern_create_linear(0, 0, 0, BUTTON_DIAMETER);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 0, 219.0/255, 139.0/255, 0);
+                cairo_pattern_add_color_stop_rgb(outer_pat, 1, 219.0/255, 51.0/255, 0);
+            }
+            cairo_set_source(ctx, outer_pat);
+            cairo_stroke(ctx);
+
+            /* Draw two little separators for the highlighted part of the
+             * unlock indicator. */
+            cairo_set_source_rgb(ctx, 0, 0, 0);
+            cairo_arc(ctx,
+                      (resolution[0] / 2) /* x */,
+                      (resolution[1] / 2) /* y */,
+                      BUTTON_RADIUS /* radius */,
+                      highlight_start /* start */,
+                      highlight_start + (M_PI / 128.0) /* end */);
+            cairo_stroke(ctx);
+            cairo_arc(ctx,
+                      (resolution[0] / 2) /* x */,
+                      (resolution[1] / 2) /* y */,
+                      BUTTON_RADIUS /* radius */,
+                      highlight_start + (M_PI / 3.0) /* start */,
+                      (highlight_start + (M_PI / 3.0)) + (M_PI / 128.0) /* end */);
+            cairo_stroke(ctx);
+        }
+    }
+
+    cairo_surface_destroy(output);
+    cairo_destroy(ctx);
+#endif
+    return bg_pixmap;
+}
+
+/*
+ * Calls draw_image on a new pixmap and swaps that with the current pixmap
+ *
+ */
+void redraw_screen() {
+    xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
+    xcb_change_window_attributes(conn, win, XCB_CW_BACK_PIXMAP, (uint32_t[1]){ bg_pixmap });
+    /* XXX: Possible optimization: Only update the area in the middle of the
+     * screen instead of the whole screen. */
+    xcb_clear_area(conn, 0, win, 0, 0, screen->width_in_pixels, screen->height_in_pixels);
+    xcb_free_pixmap(conn, bg_pixmap);
+    xcb_flush(conn);
+}
diff --git a/unlock_indicator.h b/unlock_indicator.h
new file mode 100644 (file)
index 0000000..6cd7b54
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _UNLOCK_INDICATOR_H
+#define _UNLOCK_INDICATOR_H
+
+typedef enum {
+    STATE_STARTED = 0,          /* default state */
+    STATE_KEY_PRESSED = 1,      /* key was pressed, show unlock indicator */
+    STATE_KEY_ACTIVE = 2,       /* a key was pressed recently, highlight part
+                                   of the unlock indicator. */
+    STATE_BACKSPACE_ACTIVE = 3  /* backspace was pressed recently, highlight
+                                   part of the unlock indicator in red. */
+} unlock_state_t;
+
+typedef enum {
+    STATE_PAM_IDLE = 0,         /* no PAM interaction at the moment */
+    STATE_PAM_VERIFY = 1,       /* currently verifying the password via PAM */
+    STATE_PAM_WRONG = 2         /* the password was wrong */
+} pam_state_t;
+
+xcb_pixmap_t draw_image(uint32_t* resolution);
+void redraw_screen();
+
+#endif
diff --git a/xcb.c b/xcb.c
index 65493a332ad98500e837b7483a0661cf85eb053c..d27b98cf89ecd0e6de7862e1da538f581b1422aa 100644 (file)
--- a/xcb.c
+++ b/xcb.c
@@ -20,6 +20,9 @@
 
 #include "cursors.h"
 
+xcb_connection_t *conn;
+xcb_screen_t *screen;
+
 #define curs_invisible_width 8
 #define curs_invisible_height 8
 
diff --git a/xcb.h b/xcb.h
index 54d667e5748559c2a5d36fe1f08d7a3587d7d075..e4f700c56e6856f00c45cf681aecac7c9a3a4955 100644 (file)
--- a/xcb.h
+++ b/xcb.h
@@ -3,6 +3,9 @@
 
 #include <xcb/xcb.h>
 
+extern xcb_connection_t *conn;
+extern xcb_screen_t *screen;
+
 xcb_visualtype_t *get_root_visual_type(xcb_screen_t *s);
 xcb_pixmap_t create_bg_pixmap(xcb_connection_t *conn, xcb_screen_t *scr, u_int32_t *resolution, char *color);
 xcb_window_t open_fullscreen_window(xcb_connection_t *conn, xcb_screen_t *scr, char *color, xcb_pixmap_t pixmap);