Hello community,

here is the log from the commit of package i3lock for openSUSE:Factory checked 
in at 2017-11-27 22:18:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/i3lock (Old)
 and      /work/SRC/openSUSE:Factory/.i3lock.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "i3lock"

Mon Nov 27 22:18:27 2017 rev:13 rq:545890 version:2.10

Changes:
--------
--- /work/SRC/openSUSE:Factory/i3lock/i3lock.changes    2017-11-09 
14:07:55.168986994 +0100
+++ /work/SRC/openSUSE:Factory/.i3lock.new/i3lock.changes       2017-11-27 
22:18:34.242287195 +0100
@@ -1,0 +2,12 @@
+Sun Nov 26 15:52:11 UTC 2017 - [email protected]
+
+- update to 2.10
+ * Only use -lpam when not on OpenBSD
+ * locale: treat empty string same as unset
+ * Fix overwrite of getopt optind
+ * Immediately hide the unlock indicator after ESC / C-u
+ * Measure wall-clock time instead of CPU time for “locking” indicator.
+ * SetInputFocus to the i3lock window to force-close context menus
+ * Use RandR for learning about attached monitors
+
+-------------------------------------------------------------------

Old:
----
  i3lock-2.9.1.tar.bz2

New:
----
  i3lock-2.10.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ i3lock.spec ++++++
--- /var/tmp/diff_new_pack.pC0YNk/_old  2017-11-27 22:18:34.738269193 +0100
+++ /var/tmp/diff_new_pack.pC0YNk/_new  2017-11-27 22:18:34.742269048 +0100
@@ -20,7 +20,7 @@
 
 # Please submit bugfixes or comments via http://bugs.opensuse.org/
 Name:           i3lock
-Version:        2.9.1
+Version:        2.10
 Release:        0
 Summary:        Screen Locker for the i3 Window Manager
 License:        BSD-3-Clause

++++++ i3lock-2.9.1.tar.bz2 -> i3lock-2.10.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/CHANGELOG new/i3lock-2.10/CHANGELOG
--- old/i3lock-2.9.1/CHANGELOG  2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/CHANGELOG   2017-11-25 08:15:59.000000000 +0100
@@ -1,3 +1,13 @@
+2017-11-25 i3lock 2.10
+
+ • Only use -lpam when not on OpenBSD (Thanks Kaashif)
+ • locale: treat empty string same as unset (Thanks Ran)
+ • Fix overwrite of getopt optind (Thanks jakob)
+ • Immediately hide the unlock indicator after ESC / C-u (Thanks Orestis)
+ • Measure wall-clock time instead of CPU time for “locking” indicator.
+ • SetInputFocus to the i3lock window to force-close context menus
+ • Use RandR for learning about attached monitors
+
 2017-06-21 i3lock 2.9.1
 
  • Fix version number mechanism (for --version)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/Makefile new/i3lock-2.10/Makefile
--- old/i3lock-2.9.1/Makefile   2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/Makefile    2017-11-25 08:15:59.000000000 +0100
@@ -15,9 +15,8 @@
 CFLAGS += -pipe
 CFLAGS += -Wall
 CPPFLAGS += -D_GNU_SOURCE
-CFLAGS += $(shell $(PKG_CONFIG) --cflags cairo xcb-xinerama xcb-atom xcb-image 
xcb-xkb xkbcommon xkbcommon-x11)
-LIBS += $(shell $(PKG_CONFIG) --libs cairo xcb-xinerama xcb-atom xcb-image 
xcb-xkb xkbcommon xkbcommon-x11)
-LIBS += -lpam
+CFLAGS += $(shell $(PKG_CONFIG) --cflags cairo xcb-xinerama xcb-randr xcb-atom 
xcb-image xcb-xkb xkbcommon xkbcommon-x11)
+LIBS += $(shell $(PKG_CONFIG) --libs cairo xcb-xinerama xcb-randr xcb-atom 
xcb-image xcb-xkb xkbcommon xkbcommon-x11)
 LIBS += -lev
 LIBS += -lm
 
@@ -32,10 +31,10 @@
 ifeq ($(wildcard .git),)
   # not in git repository
   VERSION := $(shell [ -f $(TOPDIR)/I3LOCK_VERSION ] && cat 
$(TOPDIR)/I3LOCK_VERSION | cut -d '-' -f 1)
-I3LOCK_VERSION:="2.9.1 (2017-06-21)"
+I3LOCK_VERSION:="2.10 (2017-11-25)"
 else
   VERSION:=$(shell git describe --tags --abbrev=0)
-I3LOCK_VERSION:="2.9.1 (2017-06-21)"
+I3LOCK_VERSION:="2.10 (2017-11-25)"
 endif
 CPPFLAGS += -DVERSION=\"${I3LOCK_VERSION}\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/README.md new/i3lock-2.10/README.md
--- old/i3lock-2.9.1/README.md  2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/README.md   2017-11-25 08:15:59.000000000 +0100
@@ -26,6 +26,7 @@
 - libpam-dev
 - libcairo-dev
 - libxcb-xinerama
+- libxcb-randr
 - libev
 - libx11-dev
 - libx11-xcb-dev
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/i3lock.c new/i3lock-2.10/i3lock.c
--- old/i3lock-2.9.1/i3lock.c   2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/i3lock.c    2017-11-25 08:15:59.000000000 +0100
@@ -35,12 +35,14 @@
 #ifdef __OpenBSD__
 #include <strings.h> /* explicit_bzero(3) */
 #endif
+#include <xcb/xcb_aux.h>
+#include <xcb/randr.h>
 
 #include "i3lock.h"
 #include "xcb.h"
 #include "cursors.h"
 #include "unlock_indicator.h"
-#include "xinerama.h"
+#include "randr.h"
 
 #define TSTAMP_N_SECS(n) (n * 1.0)
 #define TSTAMP_N_MINS(n) (60 * TSTAMP_N_SECS(n))
@@ -84,6 +86,7 @@
 static struct xkb_compose_state *xkb_compose_state;
 static uint8_t xkb_base_event;
 static uint8_t xkb_base_error;
+static int randr_base = -1;
 
 cairo_surface_t *img = NULL;
 bool tile = false;
@@ -278,7 +281,8 @@
         DEBUG("successfully authenticated\n");
         clear_password_memory();
 
-        exit(0);
+        ev_break(EV_DEFAULT, EVBREAK_ALL);
+        return;
     }
 #else
     if (pam_authenticate(pam_handle, 0) == PAM_SUCCESS) {
@@ -292,7 +296,8 @@
         pam_setcred(pam_handle, PAM_REFRESH_CRED);
         pam_end(pam_handle, PAM_SUCCESS);
 
-        exit(0);
+        ev_break(EV_DEFAULT, EVBREAK_ALL);
+        return;
     }
 #endif
 
@@ -445,14 +450,9 @@
                 ksym == XKB_KEY_Escape) {
                 DEBUG("C-u pressed\n");
                 clear_input();
-                /* Hide the unlock indicator after a bit if the password 
buffer is
-                 * empty. */
-                if (unlock_indicator) {
-                    START_TIMER(clear_indicator_timeout, 1.0, 
clear_indicator_cb);
-                    unlock_state = STATE_BACKSPACE_ACTIVE;
-                    redraw_screen();
-                    unlock_state = STATE_KEY_PRESSED;
-                }
+                /* Also hide the unlock indicator */
+                if (unlock_indicator)
+                    clear_indicator();
                 return;
             }
             break;
@@ -622,7 +622,7 @@
     xcb_configure_window(conn, win, mask, last_resolution);
     xcb_flush(conn);
 
-    xinerama_query_screens();
+    randr_query(screen->root);
     redraw_screen();
 }
 
@@ -745,8 +745,14 @@
                 break;
 
             default:
-                if (type == xkb_base_event)
+                if (type == xkb_base_event) {
                     process_xkb_event(event);
+                }
+                if (randr_base > -1 &&
+                    type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
+                    randr_query(screen->root);
+                    handle_screen_resize();
+                }
         }
 
         free(event);
@@ -819,7 +825,7 @@
 #endif
     int curs_choice = CURS_NONE;
     int o;
-    int optind = 0;
+    int longoptind = 0;
     struct option longopts[] = {
         {"version", no_argument, NULL, 'v'},
         {"nofork", no_argument, NULL, 'n'},
@@ -843,7 +849,7 @@
         errx(EXIT_FAILURE, "pw->pw_name is NULL.\n");
 
     char *optstring = "hvnbdc:p:ui:teI:f";
-    while ((o = getopt_long(argc, argv, optstring, longopts, &optind)) != -1) {
+    while ((o = getopt_long(argc, argv, optstring, longopts, &longoptind)) != 
-1) {
         switch (o) {
             case 'v':
                 errx(EXIT_SUCCESS, "version " VERSION " © 2010 Michael 
Stapelberg");
@@ -894,7 +900,7 @@
                 ignore_empty_password = true;
                 break;
             case 0:
-                if (strcmp(longopts[optind].name, "debug") == 0)
+                if (strcmp(longopts[longoptind].name, "debug") == 0)
                     debug_mode = true;
                 break;
             case 'f':
@@ -977,11 +983,11 @@
         errx(EXIT_FAILURE, "Could not load keymap");
 
     const char *locale = getenv("LC_ALL");
-    if (!locale)
+    if (!locale || !*locale)
         locale = getenv("LC_CTYPE");
-    if (!locale)
+    if (!locale || !*locale)
         locale = getenv("LANG");
-    if (!locale) {
+    if (!locale || !*locale) {
         if (debug_mode)
             fprintf(stderr, "Can't detect your locale, fallback to C\n");
         locale = "C";
@@ -989,11 +995,11 @@
 
     load_compose_table(locale);
 
-    xinerama_init();
-    xinerama_query_screens();
-
     screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
 
+    randr_init(&randr_base, screen->root);
+    randr_query(screen->root);
+
     last_resolution[0] = screen->width_in_pixels;
     last_resolution[1] = screen->height_in_pixels;
 
@@ -1015,6 +1021,8 @@
     /* Pixmap on which the image is rendered to (if any) */
     xcb_pixmap_t bg_pixmap = draw_image(last_resolution);
 
+    xcb_window_t stolen_focus = find_focused_window(conn, screen->root);
+
     /* Open the fullscreen window, already with the correct pixmap in place */
     win = open_fullscreen_window(conn, screen, color, bg_pixmap);
     xcb_free_pixmap(conn, bg_pixmap);
@@ -1023,7 +1031,23 @@
 
     /* Display the "locking…" message while trying to grab the 
pointer/keyboard. */
     auth_state = STATE_AUTH_LOCK;
-    grab_pointer_and_keyboard(conn, screen, cursor);
+    if (!grab_pointer_and_keyboard(conn, screen, cursor, 1000)) {
+        DEBUG("stole focus from X11 window 0x%08x\n", stolen_focus);
+
+        /* Set the focus to i3lock, possibly closing context menus which would
+         * otherwise prevent us from grabbing keyboard/pointer.
+         *
+         * We cannot use set_focused_window because _NET_ACTIVE_WINDOW only
+         * works for managed windows, but i3lock uses an unmanaged window
+         * (override_redirect=1). */
+        xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT /* revert_to */, win, 
XCB_CURRENT_TIME);
+        if (!grab_pointer_and_keyboard(conn, screen, cursor, 9000)) {
+            auth_state = STATE_I3LOCK_LOCK_FAILED;
+            redraw_screen();
+            sleep(1);
+            errx(EXIT_FAILURE, "Cannot grab pointer/keyboard");
+        }
+    }
 
     pid_t pid = fork();
     /* The pid == -1 case is intentionally ignored here:
@@ -1070,4 +1094,17 @@
      * file descriptor becomes readable). */
     ev_invoke(main_loop, xcb_check, 0);
     ev_loop(main_loop, 0);
+
+    if (stolen_focus == XCB_NONE) {
+        return 0;
+    }
+
+    DEBUG("restoring focus to X11 window 0x%08x\n", stolen_focus);
+    xcb_ungrab_pointer(conn, XCB_CURRENT_TIME);
+    xcb_ungrab_keyboard(conn, XCB_CURRENT_TIME);
+    xcb_destroy_window(conn, win);
+    set_focused_window(conn, screen->root, stolen_focus);
+    xcb_aux_sync(conn);
+
+    return 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/randr.c new/i3lock-2.10/randr.c
--- old/i3lock-2.9.1/randr.c    1970-01-01 01:00:00.000000000 +0100
+++ new/i3lock-2.10/randr.c     2017-11-25 08:15:59.000000000 +0100
@@ -0,0 +1,297 @@
+/*
+ * vim:ts=4:sw=4:expandtab
+ *
+ * © 2010 Michael Stapelberg
+ *
+ * See LICENSE for licensing information
+ *
+ */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <xcb/xcb.h>
+#include <xcb/xinerama.h>
+#include <xcb/randr.h>
+
+#include "i3lock.h"
+#include "xcb.h"
+#include "randr.h"
+
+/* Number of Xinerama screens which are currently present. */
+int xr_screens = 0;
+
+/* The resolutions of the currently present Xinerama screens. */
+Rect *xr_resolutions = NULL;
+
+static bool xinerama_active;
+static bool has_randr = false;
+static bool has_randr_1_5 = false;
+extern bool debug_mode;
+
+void _xinerama_init(void);
+
+void randr_init(int *event_base, xcb_window_t root) {
+    const xcb_query_extension_reply_t *extreply;
+
+    extreply = xcb_get_extension_data(conn, &xcb_randr_id);
+    if (!extreply->present) {
+        DEBUG("RandR is not present, falling back to Xinerama.\n");
+        _xinerama_init();
+        return;
+    }
+
+    xcb_generic_error_t *err;
+    xcb_randr_query_version_reply_t *randr_version =
+        xcb_randr_query_version_reply(
+            conn, xcb_randr_query_version(conn, XCB_RANDR_MAJOR_VERSION, 
XCB_RANDR_MINOR_VERSION), &err);
+    if (err != NULL) {
+        DEBUG("Could not query RandR version: X11 error code %d\n", 
err->error_code);
+        _xinerama_init();
+        return;
+    }
+
+    has_randr = true;
+
+    has_randr_1_5 = (randr_version->major_version >= 1) &&
+                    (randr_version->minor_version >= 5);
+
+    free(randr_version);
+
+    if (event_base != NULL)
+        *event_base = extreply->first_event;
+
+    xcb_randr_select_input(conn, root,
+                           XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
+                               XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
+                               XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
+                               XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
+
+    xcb_flush(conn);
+}
+
+void _xinerama_init(void) {
+    if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) {
+        DEBUG("Xinerama extension not found, disabling.\n");
+        return;
+    }
+
+    xcb_xinerama_is_active_cookie_t cookie;
+    xcb_xinerama_is_active_reply_t *reply;
+
+    cookie = xcb_xinerama_is_active(conn);
+    reply = xcb_xinerama_is_active_reply(conn, cookie, NULL);
+    if (!reply)
+        return;
+
+    if (!reply->state) {
+        free(reply);
+        return;
+    }
+
+    xinerama_active = true;
+    free(reply);
+}
+
+/*
+ * randr_query_outputs_15 uses RandR ≥ 1.5 to update outputs.
+ *
+ */
+static bool _randr_query_monitors_15(xcb_window_t root) {
+#if XCB_RANDR_MINOR_VERSION < 5
+    return false;
+#else
+    /* RandR 1.5 available at compile-time, i.e. libxcb is new enough */
+    if (!has_randr_1_5) {
+        return false;
+    }
+    /* RandR 1.5 available at run-time (supported by the server) */
+    DEBUG("Querying monitors using RandR 1.5\n");
+    xcb_generic_error_t *err;
+    xcb_randr_get_monitors_reply_t *monitors =
+        xcb_randr_get_monitors_reply(
+            conn, xcb_randr_get_monitors(conn, root, true), &err);
+    if (err != NULL) {
+        DEBUG("Could not get RandR monitors: X11 error code %d\n", 
err->error_code);
+        free(err);
+        /* Fall back to RandR ≤ 1.4 */
+        return false;
+    }
+
+    int screens = xcb_randr_get_monitors_monitors_length(monitors);
+    DEBUG("%d RandR monitors found (timestamp %d)\n",
+          screens, monitors->timestamp);
+
+    Rect *resolutions = malloc(screens * sizeof(Rect));
+    /* No memory? Just keep on using the old information. */
+    if (!resolutions) {
+        free(monitors);
+        return true;
+    }
+
+    xcb_randr_monitor_info_iterator_t iter;
+    int screen;
+    for (iter = xcb_randr_get_monitors_monitors_iterator(monitors), screen = 0;
+         iter.rem;
+         xcb_randr_monitor_info_next(&iter), screen++) {
+        const xcb_randr_monitor_info_t *monitor_info = iter.data;
+
+        resolutions[screen].x = monitor_info->x;
+        resolutions[screen].y = monitor_info->y;
+        resolutions[screen].width = monitor_info->width;
+        resolutions[screen].height = monitor_info->height;
+        DEBUG("found RandR monitor: %d x %d at %d x %d\n",
+              monitor_info->width, monitor_info->height,
+              monitor_info->x, monitor_info->y);
+    }
+    free(xr_resolutions);
+    xr_resolutions = resolutions;
+    xr_screens = screens;
+
+    free(monitors);
+    return true;
+#endif
+}
+
+/*
+ * randr_query_outputs_14 uses RandR ≤ 1.4 to update outputs.
+ *
+ */
+static bool _randr_query_outputs_14(xcb_window_t root) {
+    if (!has_randr) {
+        return false;
+    }
+    DEBUG("Querying outputs using RandR ≤ 1.4\n");
+
+    /* Get screen resources (primary output, crtcs, outputs, modes) */
+    xcb_randr_get_screen_resources_current_cookie_t rcookie;
+    rcookie = xcb_randr_get_screen_resources_current(conn, root);
+
+    xcb_randr_get_screen_resources_current_reply_t *res =
+        xcb_randr_get_screen_resources_current_reply(conn, rcookie, NULL);
+    if (res == NULL) {
+        DEBUG("Could not query screen resources.\n");
+        return false;
+    }
+
+    /* timestamp of the configuration so that we get consistent replies to all
+     * requests (if the configuration changes between our different calls) */
+    const xcb_timestamp_t cts = res->config_timestamp;
+
+    const int len = xcb_randr_get_screen_resources_current_outputs_length(res);
+
+    /* an output is VGA-1, LVDS-1, etc. (usually physical video outputs) */
+    xcb_randr_output_t *randr_outputs = 
xcb_randr_get_screen_resources_current_outputs(res);
+
+    /* Request information for each output */
+    xcb_randr_get_output_info_cookie_t ocookie[len];
+    for (int i = 0; i < len; i++) {
+        ocookie[i] = xcb_randr_get_output_info(conn, randr_outputs[i], cts);
+    }
+    Rect *resolutions = malloc(len * sizeof(Rect));
+    /* No memory? Just keep on using the old information. */
+    if (!resolutions) {
+        free(res);
+        return true;
+    }
+
+    /* Loop through all outputs available for this X11 screen */
+    int screen = 0;
+
+    for (int i = 0; i < len; i++) {
+        xcb_randr_get_output_info_reply_t *output;
+
+        if ((output = xcb_randr_get_output_info_reply(conn, ocookie[i], NULL)) 
== NULL) {
+            continue;
+        }
+
+        if (output->crtc == XCB_NONE) {
+            free(output);
+            continue;
+        }
+
+        xcb_randr_get_crtc_info_cookie_t icookie;
+        xcb_randr_get_crtc_info_reply_t *crtc;
+        icookie = xcb_randr_get_crtc_info(conn, output->crtc, cts);
+        if ((crtc = xcb_randr_get_crtc_info_reply(conn, icookie, NULL)) == 
NULL) {
+            DEBUG("Skipping output: could not get CRTC (0x%08x)\n", 
output->crtc);
+            free(output);
+            continue;
+        }
+
+        resolutions[screen].x = crtc->x;
+        resolutions[screen].y = crtc->y;
+        resolutions[screen].width = crtc->width;
+        resolutions[screen].height = crtc->height;
+
+        DEBUG("found RandR output: %d x %d at %d x %d\n",
+              crtc->width, crtc->height,
+              crtc->x, crtc->y);
+
+        screen++;
+
+        free(crtc);
+
+        free(output);
+    }
+    free(xr_resolutions);
+    xr_resolutions = resolutions;
+    xr_screens = screen;
+    free(res);
+    return true;
+}
+
+void _xinerama_query_screens(void) {
+    if (!xinerama_active) {
+        return;
+    }
+
+    xcb_xinerama_query_screens_cookie_t cookie;
+    xcb_xinerama_query_screens_reply_t *reply;
+    xcb_xinerama_screen_info_t *screen_info;
+    xcb_generic_error_t *err;
+    cookie = xcb_xinerama_query_screens_unchecked(conn);
+    reply = xcb_xinerama_query_screens_reply(conn, cookie, &err);
+    if (!reply) {
+        DEBUG("Couldn't get Xinerama screens: X11 error code %d\n", 
err->error_code);
+        free(err);
+        return;
+    }
+    screen_info = xcb_xinerama_query_screens_screen_info(reply);
+    int screens = xcb_xinerama_query_screens_screen_info_length(reply);
+
+    Rect *resolutions = malloc(screens * sizeof(Rect));
+    /* No memory? Just keep on using the old information. */
+    if (!resolutions) {
+        free(reply);
+        return;
+    }
+
+    for (int screen = 0; screen < xr_screens; screen++) {
+        resolutions[screen].x = screen_info[screen].x_org;
+        resolutions[screen].y = screen_info[screen].y_org;
+        resolutions[screen].width = screen_info[screen].width;
+        resolutions[screen].height = screen_info[screen].height;
+        DEBUG("found Xinerama screen: %d x %d at %d x %d\n",
+              screen_info[screen].width, screen_info[screen].height,
+              screen_info[screen].x_org, screen_info[screen].y_org);
+    }
+
+    free(xr_resolutions);
+    xr_resolutions = resolutions;
+    xr_screens = screens;
+
+    free(reply);
+}
+
+void randr_query(xcb_window_t root) {
+    if (_randr_query_monitors_15(root)) {
+        return;
+    }
+
+    if (_randr_query_outputs_14(root)) {
+        return;
+    }
+
+    _xinerama_query_screens();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/randr.h new/i3lock-2.10/randr.h
--- old/i3lock-2.9.1/randr.h    1970-01-01 01:00:00.000000000 +0100
+++ new/i3lock-2.10/randr.h     2017-11-25 08:15:59.000000000 +0100
@@ -0,0 +1,17 @@
+#ifndef _XINERAMA_H
+#define _XINERAMA_H
+
+typedef struct Rect {
+    int16_t x;
+    int16_t y;
+    uint16_t width;
+    uint16_t height;
+} Rect;
+
+extern int xr_screens;
+extern Rect *xr_resolutions;
+
+void randr_init(int *event_base, xcb_window_t root);
+void randr_query(xcb_window_t root);
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/unlock_indicator.c 
new/i3lock-2.10/unlock_indicator.c
--- old/i3lock-2.9.1/unlock_indicator.c 2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/unlock_indicator.c  2017-11-25 08:15:59.000000000 +0100
@@ -19,7 +19,7 @@
 #include "i3lock.h"
 #include "xcb.h"
 #include "unlock_indicator.h"
-#include "xinerama.h"
+#include "randr.h"
 
 #define BUTTON_RADIUS 90
 #define BUTTON_SPACE (BUTTON_RADIUS + 5)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/xcb.c new/i3lock-2.10/xcb.c
--- old/i3lock-2.9.1/xcb.c      2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/xcb.c       2017-11-25 08:15:59.000000000 +0100
@@ -19,6 +19,7 @@
 #include <assert.h>
 #include <err.h>
 #include <time.h>
+#include <sys/time.h>
 
 #include "cursors.h"
 #include "unlock_indicator.h"
@@ -162,21 +163,27 @@
 }
 
 /*
- * Repeatedly tries to grab pointer and keyboard (up to 10000 times).
+ * Repeatedly tries to grab pointer and keyboard (up to the specified number of
+ * tries).
+ *
+ * Returns true if the grab succeeded, false if not.
  *
  */
-void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, 
xcb_cursor_t cursor) {
+bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, 
xcb_cursor_t cursor, int tries) {
     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 = 10000;
+    const suseconds_t screen_redraw_timeout = 100000; /* 100ms */
 
     /* Using few variables to trigger a redraw_screen() if too many tries */
     bool redrawn = false;
-    time_t start = clock();
+    struct timeval start;
+    if (gettimeofday(&start, NULL) == -1) {
+        err(EXIT_FAILURE, "gettimeofday");
+    }
 
     while (tries-- > 0) {
         pcookie = xcb_grab_pointer(
@@ -199,10 +206,17 @@
         /* Make this quite a bit slower */
         usleep(50);
 
-        /* Measure elapsed time and trigger a screen redraw if elapsed > 
250000 */
+        struct timeval now;
+        if (gettimeofday(&now, NULL) == -1) {
+            err(EXIT_FAILURE, "gettimeofday");
+        }
+
+        struct timeval elapsed;
+        timersub(&now, &start, &elapsed);
+
         if (!redrawn &&
             (tries % 100) == 0 &&
-            (clock() - start) > 250000) {
+            elapsed.tv_usec >= screen_redraw_timeout) {
             redraw_screen();
             redrawn = true;
         }
@@ -226,23 +240,24 @@
         /* Make this quite a bit slower */
         usleep(50);
 
-        /* Measure elapsed time and trigger a screen redraw if elapsed > 
250000 */
+        struct timeval now;
+        if (gettimeofday(&now, NULL) == -1) {
+            err(EXIT_FAILURE, "gettimeofday");
+        }
+
+        struct timeval elapsed;
+        timersub(&now, &start, &elapsed);
+
+        /* Trigger a screen redraw if 100ms elapsed */
         if (!redrawn &&
             (tries % 100) == 0 &&
-            (clock() - start) > 250000) {
+            elapsed.tv_usec >= screen_redraw_timeout) {
             redraw_screen();
             redrawn = true;
         }
     }
 
-    /* After trying for 10000 times, i3lock will display an error message
-     * for 2 sec prior to terminate. */
-    if (tries <= 0) {
-        auth_state = STATE_I3LOCK_LOCK_FAILED;
-        redraw_screen();
-        sleep(1);
-        errx(EXIT_FAILURE, "Cannot grab pointer/keyboard");
-    }
+    return (tries > 0);
 }
 
 xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, 
xcb_window_t win, int choice) {
@@ -307,3 +322,67 @@
 
     return cursor;
 }
+
+static xcb_atom_t _NET_ACTIVE_WINDOW = XCB_NONE;
+void _init_net_active_window(xcb_connection_t *conn) {
+    if (_NET_ACTIVE_WINDOW != XCB_NONE) {
+        /* already initialized */
+        return;
+    }
+    xcb_generic_error_t *err;
+    xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(
+        conn,
+        xcb_intern_atom(conn, 0, strlen("_NET_ACTIVE_WINDOW"), 
"_NET_ACTIVE_WINDOW"),
+        &err);
+    if (atom_reply == NULL) {
+        fprintf(stderr, "X11 Error %d\n", err->error_code);
+        free(err);
+        return;
+    }
+    _NET_ACTIVE_WINDOW = atom_reply->atom;
+    free(atom_reply);
+}
+
+xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t 
root) {
+    xcb_window_t result = XCB_NONE;
+
+    _init_net_active_window(conn);
+
+    xcb_get_property_reply_t *prop_reply = xcb_get_property_reply(
+        conn,
+        xcb_get_property_unchecked(
+            conn, false, root, _NET_ACTIVE_WINDOW, XCB_GET_PROPERTY_TYPE_ANY, 
0, 1 /* word */),
+        NULL);
+    if (prop_reply == NULL) {
+        goto out;
+    }
+    if (xcb_get_property_value_length(prop_reply) == 0) {
+        goto out_prop;
+    }
+    if (prop_reply->type != XCB_ATOM_WINDOW) {
+        goto out_prop;
+    }
+
+    result = *((xcb_window_t *)xcb_get_property_value(prop_reply));
+
+out_prop:
+    free(prop_reply);
+out:
+    return result;
+}
+
+void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const 
xcb_window_t window) {
+    xcb_client_message_event_t ev;
+    memset(&ev, '\0', sizeof(xcb_client_message_event_t));
+
+    _init_net_active_window(conn);
+
+    ev.response_type = XCB_CLIENT_MESSAGE;
+    ev.window = window;
+    ev.type = _NET_ACTIVE_WINDOW;
+    ev.format = 32;
+    ev.data.data32[0] = 2; /* 2 = pager */
+
+    xcb_send_event(conn, false, root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, 
(char *)&ev);
+    xcb_flush(conn);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/xcb.h new/i3lock-2.10/xcb.h
--- old/i3lock-2.9.1/xcb.h      2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/xcb.h       2017-11-25 08:15:59.000000000 +0100
@@ -9,7 +9,9 @@
 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);
-void grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, 
xcb_cursor_t cursor);
+bool grab_pointer_and_keyboard(xcb_connection_t *conn, xcb_screen_t *screen, 
xcb_cursor_t cursor, int tries);
 xcb_cursor_t create_cursor(xcb_connection_t *conn, xcb_screen_t *screen, 
xcb_window_t win, int choice);
+xcb_window_t find_focused_window(xcb_connection_t *conn, const xcb_window_t 
root);
+void set_focused_window(xcb_connection_t *conn, const xcb_window_t root, const 
xcb_window_t window);
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/xinerama.c new/i3lock-2.10/xinerama.c
--- old/i3lock-2.9.1/xinerama.c 2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/xinerama.c  1970-01-01 01:00:00.000000000 +0100
@@ -1,90 +0,0 @@
-/*
- * vim:ts=4:sw=4:expandtab
- *
- * © 2010 Michael Stapelberg
- *
- * See LICENSE for licensing information
- *
- */
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <xcb/xcb.h>
-#include <xcb/xinerama.h>
-
-#include "i3lock.h"
-#include "xcb.h"
-#include "xinerama.h"
-
-/* Number of Xinerama screens which are currently present. */
-int xr_screens = 0;
-
-/* The resolutions of the currently present Xinerama screens. */
-Rect *xr_resolutions;
-
-static bool xinerama_active;
-extern bool debug_mode;
-
-void xinerama_init(void) {
-    if (!xcb_get_extension_data(conn, &xcb_xinerama_id)->present) {
-        DEBUG("Xinerama extension not found, disabling.\n");
-        return;
-    }
-
-    xcb_xinerama_is_active_cookie_t cookie;
-    xcb_xinerama_is_active_reply_t *reply;
-
-    cookie = xcb_xinerama_is_active(conn);
-    reply = xcb_xinerama_is_active_reply(conn, cookie, NULL);
-    if (!reply)
-        return;
-
-    if (!reply->state) {
-        free(reply);
-        return;
-    }
-
-    xinerama_active = true;
-    free(reply);
-}
-
-void xinerama_query_screens(void) {
-    if (!xinerama_active)
-        return;
-
-    xcb_xinerama_query_screens_cookie_t cookie;
-    xcb_xinerama_query_screens_reply_t *reply;
-    xcb_xinerama_screen_info_t *screen_info;
-
-    cookie = xcb_xinerama_query_screens_unchecked(conn);
-    reply = xcb_xinerama_query_screens_reply(conn, cookie, NULL);
-    if (!reply) {
-        if (debug_mode)
-            fprintf(stderr, "Couldn't get Xinerama screens\n");
-        return;
-    }
-    screen_info = xcb_xinerama_query_screens_screen_info(reply);
-    int screens = xcb_xinerama_query_screens_screen_info_length(reply);
-
-    Rect *resolutions = malloc(screens * sizeof(Rect));
-    /* No memory? Just keep on using the old information. */
-    if (!resolutions) {
-        free(reply);
-        return;
-    }
-    xr_resolutions = resolutions;
-    xr_screens = screens;
-
-    for (int screen = 0; screen < xr_screens; screen++) {
-        xr_resolutions[screen].x = screen_info[screen].x_org;
-        xr_resolutions[screen].y = screen_info[screen].y_org;
-        xr_resolutions[screen].width = screen_info[screen].width;
-        xr_resolutions[screen].height = screen_info[screen].height;
-        DEBUG("found Xinerama screen: %d x %d at %d x %d\n",
-              screen_info[screen].width, screen_info[screen].height,
-              screen_info[screen].x_org, screen_info[screen].y_org);
-    }
-
-    free(reply);
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/i3lock-2.9.1/xinerama.h new/i3lock-2.10/xinerama.h
--- old/i3lock-2.9.1/xinerama.h 2017-06-21 18:18:26.000000000 +0200
+++ new/i3lock-2.10/xinerama.h  1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-#ifndef _XINERAMA_H
-#define _XINERAMA_H
-
-typedef struct Rect {
-    int16_t x;
-    int16_t y;
-    uint16_t width;
-    uint16_t height;
-} Rect;
-
-extern int xr_screens;
-extern Rect *xr_resolutions;
-
-void xinerama_init(void);
-void xinerama_query_screens(void);
-
-#endif



Reply via email to